Concurrency Model
gRPCClient.jl runs background tasks for socket I/O, streaming request and response pumps, and asynchronous unary fan-out. The gRPCCURL handle decides how those tasks are scheduled through its sticky property, so a single setting controls the model for every request made through that handle.
Two models are available:
- Non-sticky (
sticky = false, the default) usesThreads.@spawn. Tasks are migratable and can run on any thread, so the client scales across threads when Julia is started with more than one (for examplejulia -t auto). This is the right choice when you run multithreaded or have CPU-bound encode and decode work - Sticky (
sticky = true) uses@async. Tasks are pinned to the thread that spawned them and run under cooperative, single-threaded scheduling. This model is incompatible with multithreading: it does not parallelize across threads even when more than one is available. It has lower scheduling overhead and avoids cross-thread data movement, which suits purely I/O-bound workloads and single-threaded deployments
The property is set when the handle is constructed and applies to every client that uses it:
# Coroutine model, pinned to the calling threadh = gRPCCURL(sticky = true)grpc_init(h)chan = gRPCChannel("localhost", 50051; grpc = h)response = MyService.MyRPC(chan, MyRequest(...))The global handle returned by grpc_global_handle() uses the default sticky = false.