@@ -1489,21 +1489,21 @@ https://github.com/temporalio/samples-python/tree/nexus/hello_nexus).
14891489
14901490### Plugins
14911491
1492- Plugins provide a way to extend and customize the behavior of Temporal clients and workers through a chain of
1493- responsibility pattern. They allow you to intercept and modify client creation, service connections, worker
1492+ Plugins provide a way to extend and customize the behavior of Temporal clients and workers through a chain of
1493+ responsibility pattern. They allow you to intercept and modify client creation, service connections, worker
14941494configuration, and worker execution. Common customizations may include but are not limited to:
14951495
149614961. DataConverter
149714972. Activities
149814983. Workflows
149914994. Interceptors
15001500
1501- A single plugin class can implement both client and worker plugin interfaces to share common logic between both
1501+ A single plugin class can implement both client and worker plugin interfaces to share common logic between both
15021502contexts. When used with a client, it will automatically be propagated to any workers created with that client.
15031503
15041504#### Client Plugins
15051505
1506- Client plugins can intercept and modify client configuration and service connections. They are useful for adding
1506+ Client plugins can intercept and modify client configuration and service connections. They are useful for adding
15071507authentication, modifying connection parameters, or adding custom behavior during client creation.
15081508
15091509Here's an example of a client plugin that adds custom authentication:
@@ -1515,7 +1515,7 @@ import temporalio.service
15151515class AuthenticationPlugin(Plugin):
15161516 def __init__(self, api_key: str):
15171517 self.api_key = api_key
1518-
1518+
15191519 def init_client_plugin(self, next: Plugin) -> None:
15201520 self.next_client_plugin = next
15211521
@@ -1540,10 +1540,10 @@ client = await Client.connect(
15401540
15411541#### Worker Plugins
15421542
1543- Worker plugins can modify worker configuration and intercept worker execution. They are useful for adding monitoring,
1544- custom lifecycle management, or modifying worker settings. Worker plugins can also configure replay.
1545- They should do this in the case that they modified the worker in a way which would also need to be present
1546- for replay to function. For instance, changing the data converter or adding workflows.
1543+ Worker plugins can modify worker configuration and intercept worker execution. They are useful for adding monitoring,
1544+ custom lifecycle management, or modifying worker settings. Worker plugins can also configure replay.
1545+ They should do this in the case that they modified the worker in a way which would also need to be present
1546+ for replay to function. For instance, changing the data converter or adding workflows.
15471547
15481548Here's an example of a worker plugin that adds custom monitoring:
15491549
@@ -1560,7 +1560,7 @@ class MonitoringPlugin(Plugin):
15601560
15611561 def init_worker_plugin (self , next : Plugin) -> None :
15621562 self .next_worker_plugin = next
1563-
1563+
15641564 def configure_worker (self , config : WorkerConfig) -> WorkerConfig:
15651565 # Modify worker configuration
15661566 original_task_queue = config[" task_queue" ]
@@ -1574,22 +1574,22 @@ class MonitoringPlugin(Plugin):
15741574 await self .next_worker_plugin.run_worker(worker)
15751575 finally :
15761576 self .logger.info(" Worker execution completed" )
1577-
1578- def configure_replayer (self , config : ReplayerConfig) -> ReplayerConfig:
1579- return self .next_worker_plugin.configure_replayer(config)
1580-
1581- @asynccontextmanager
1582- async def run_replayer (
1583- self ,
1584- replayer : Replayer,
1585- histories : AsyncIterator[temporalio.client.WorkflowHistory],
1586- ) -> AsyncIterator[AsyncIterator[WorkflowReplayResult]]:
1587- self .logger.info(" Starting replay execution" )
1588- try :
1589- async with self .next_worker_plugin.run_replayer(replayer, histories) as results:
1590- yield results
1591- finally :
1592- self .logger.info(" Replay execution completed" )
1577+
1578+ def configure_replayer (self , config : ReplayerConfig) -> ReplayerConfig:
1579+ return self .next_worker_plugin.configure_replayer(config)
1580+
1581+ @asynccontextmanager
1582+ async def run_replayer (
1583+ self ,
1584+ replayer : Replayer,
1585+ histories : AsyncIterator[temporalio.client.WorkflowHistory],
1586+ ) -> AsyncIterator[AsyncIterator[WorkflowReplayResult]]:
1587+ self .logger.info(" Starting replay execution" )
1588+ try :
1589+ async with self .next_worker_plugin.run_replayer(replayer, histories) as results:
1590+ yield results
1591+ finally :
1592+ self .logger.info(" Replay execution completed" )
15931593
15941594# Use the plugin when creating a worker
15951595worker = Worker(
@@ -1617,38 +1617,38 @@ class UnifiedPlugin(ClientPlugin, WorkerPlugin):
16171617
16181618 def init_worker_plugin (self , next : WorkerPlugin) -> None :
16191619 self .next_worker_plugin = next
1620-
1620+
16211621 def configure_client (self , config : ClientConfig) -> ClientConfig:
16221622 # Client-side customization
16231623 config[" data_converter" ] = pydantic_data_converter
16241624 return self .next_client_plugin.configure_client(config)
1625-
1625+
16261626 async def connect_service_client (
16271627 self , config : temporalio.service.ConnectConfig
16281628 ) -> temporalio.service.ServiceClient:
16291629 # Add authentication to the connection
16301630 config.api_key = self .api_key
16311631 return await self .next_client_plugin.connect_service_client(config)
1632-
1632+
16331633 def configure_worker (self , config : WorkerConfig) -> WorkerConfig:
16341634 # Worker-side customization
16351635 return self .next_worker_plugin.configure_worker(config)
1636-
1636+
16371637 async def run_worker (self , worker : Worker) -> None :
16381638 print (" Starting unified worker" )
16391639 await self .next_worker_plugin.run_worker(worker)
1640-
1640+
16411641 def configure_replayer (self , config : ReplayerConfig) -> ReplayerConfig:
16421642 config[" data_converter" ] = pydantic_data_converter
16431643 return self .next_worker_plugin.configure_replayer(config)
1644-
1645- def run_replayer (
1644+
1645+ async def run_replayer (
16461646 self ,
16471647 replayer : Replayer,
16481648 histories : AsyncIterator[temporalio.client.WorkflowHistory],
16491649 ) -> AbstractAsyncContextManager[AsyncIterator[WorkflowReplayResult]]:
16501650 return self .next_worker_plugin.run_replayer(replayer, histories)
1651-
1651+
16521652# Create client with the unified plugin
16531653client = await Client.connect(
16541654 " localhost:7233" ,
0 commit comments