Python client connection management and reuse

Hi Temporal Community,

I have two questions which I will state first. Then I will explain the background context.
1. Should we be reusing temporal client connections?
2. What are some good patterns for temporal client connection reuse in the context of a python web application?

We are currently in the early stages of our temporal implementation. One aspect of our implementation is the use of the Python SDK in the context of a django web server that kicks off temporal workflows, and also sends signals to those workflows. There is a separate service that runs the temporal worker.

My first attempt at using the python client was in this way:

client = asyncio.run(Client.connect(host_uri, namespace=namespace))
client.start_workflow(workflow_name, workflow_args, id=workflow_id, task_queue=task_queue)

The client object was created on each invocation to a web server endpoint and then I assume garbage collected after the web request completed.

I wanted to understand if the underlying gRPC connection was being closed or reused between these invocations by some mechanism in the python SDK. When using wireshark to inspect the packets on port 7233, I saw that when the client object was created on each via the example above, the connection was open and then gracefully closed as indicated by FIN, ACK sequence.

When I changed the example to store the client object in a global variable in the module, the gRPC connection that I observed via wireshark remained open.

One other thing I noticed is that in the docs for the temporal typescript SDK there’s this warning:

Connections are expensive to construct and should be reused. Make sure to close any unused connections to avoid leaking resources.

That’s the info I have gathered up to this point. I’d appreciate any thoughts on the matter. Thank you!

Yes

Create it once for the event loop and reuse while in the event loop

Most web frameworks have ways to run async def code, but if you must run from a synchronous context, see Developing with asyncio — Python 3.12.0 documentation. Many use run_coroutine_threadsafe. Temporal client works like any other asyncio lib, so you can use normal asyncio approaches.

Reused for the same client, but if you’re connecting a client each time, you’re making a new connection.

That is specific to TypeScript. Python client is backed by Rust core and cleans itself up when no longer referenced. There is no close.

1 Like