Subprocess worker pools¶
VgiWorkerPool is a thread-safe pool for one subprocess command and client
configuration. Create separate pools for different commands or configurations.
Each lease owns exclusive access to one client until released. Pooling does not
make an individual VgiClient thread-safe.
#include <vgi_rpc/pool.h>
struct VgiWorkerPoolOptions options;
VgiWorkerPoolOptionsInit(&options);
const char *command[] = {"./build/vgi-rpc-calculator", NULL};
options.client.argv = command;
options.client.protocol = "Calculator";
options.client.protocol_version = "1.0.0";
options.max_workers = 4;
options.max_idle = 4;
options.acquire_timeout_ms = 5000;
struct ArrowError error = {{0}};
struct VgiWorkerPool *pool = NULL;
int rc = VgiWorkerPoolNew(&options, &pool, &error);
struct VgiWorkerLease *lease = NULL;
if (!rc) rc = VgiWorkerPoolAcquire(pool, &lease, &error);
if (!rc) {
struct VgiClient *client = VgiWorkerLeaseClient(lease);
/* Build a request and call VgiClientUnary(client, ...). */
(void)client;
VgiWorkerLeaseRelease(lease);
}
VgiWorkerPoolFree(pool);
Defaults are four total/idle workers, a 30-second acquisition timeout, and a
60-second idle timeout. At capacity, acquisition waits on a condition variable
and returns ETIMEDOUT when its deadline expires. A background reaper evicts
expired or exited idle workers. Healthy idle workers are reused in LIFO order.
VgiWorkerPoolGetStats exposes spawns, reuse, discard, eviction, timeout, and
active/idle/waiter counts.
Application RPC errors can leave a worker reusable after framing has been
drained. Transport errors, exited peers, unexpected unread bytes, and abandoned
streams cause the worker to be discarded. VgiWorkerLeaseDiscard also forces
discard. The next acquisition spawns a replacement; failed RPCs are never
automatically replayed because they may have had side effects.
VgiWorkerPoolClose rejects new acquisitions, wakes waiters with ECANCELED,
and disposes idle workers. Free additionally joins the reaper and releases the
pool owner's reference. Outstanding leases remain valid until returned; the
last return releases the remaining pool storage. Begin no new pool operations
after Free, and return each lease exactly once. Never free the leased client
directly. Callback state, external policy, and a configured telemetry instance
must outlive the pool and all outstanding leases.
The pool copies argv and routing strings. Configure options.client to use
shared memory or telemetry. The pool does not alter the process environment or
working directory; workers inherit the spawning application's environment and cwd.