@@ -94,6 +94,7 @@ informal introduction to the features and their implementation.
9494 - [ Heartbeating and Cancellation] ( #heartbeating-and-cancellation )
9595 - [ Worker Shutdown] ( #worker-shutdown )
9696 - [ Testing] ( #testing-1 )
97+ - [ Interceptors] ( #interceptors )
9798 - [ Nexus] ( #nexus )
9899 - [ Workflow Replay] ( #workflow-replay )
99100 - [ Observability] ( #observability )
@@ -1256,6 +1257,7 @@ calls in the `temporalio.activity` package make use of it. Specifically:
12561257
12571258* ` in_activity() ` - Whether an activity context is present
12581259* ` info() ` - Returns the immutable info of the currently running activity
1260+ * ` client() ` - Returns the Temporal client used by this worker. Only available in ` async def ` activities.
12591261* ` heartbeat(*details) ` - Record a heartbeat
12601262* ` is_cancelled() ` - Whether a cancellation has been requested on this activity
12611263* ` wait_for_cancelled() ` - ` async ` call to wait for cancellation request
@@ -1310,6 +1312,70 @@ affect calls activity code might make to functions on the `temporalio.activity`
13101312* ` worker_shutdown() ` can be invoked to simulate a worker shutdown during execution of the activity
13111313
13121314
1315+ ### Interceptors
1316+
1317+ The behavior of the SDK can be customized in many useful ways by modifying inbound and outbound calls using
1318+ interceptors. This is similar to the use of middleware in other frameworks.
1319+
1320+ There are five categories of inbound and outbound calls that you can modify in this way:
1321+
1322+ 1 . Outbound client calls, such as ` start_workflow() ` , ` signal_workflow() ` , ` list_workflows() ` , ` update_schedule() ` , etc.
1323+
1324+ 2 . Inbound workflow calls: ` execute_workflow() ` , ` handle_signal() ` , ` handle_update_handler() ` , etc
1325+
1326+ 3 . Outbound workflow calls: ` start_activity() ` , ` start_child_workflow() ` , ` start_nexus_operation() ` , etc
1327+
1328+ 4 . Inbound call to execute an activity: ` execute_activity() `
1329+
1330+ 5 . Outbound activity calls: ` info() ` and ` heartbeat() `
1331+
1332+
1333+ To modify outbound client calls, define a class inheriting from
1334+ [ ` client.Interceptor ` ] ( https://python.temporal.io/temporalio.client.Interceptor.html ) , and implement the method
1335+ ` intercept_client() ` to return an instance of
1336+ [ ` OutboundInterceptor ` ] ( https://python.temporal.io/temporalio.client.OutboundInterceptor.html ) that implements the
1337+ subset of outbound client calls that you wish to modify.
1338+
1339+ Then, pass a list containing an instance of your ` client.Interceptor ` class as the
1340+ ` interceptors ` argument of [ ` Client.connect() ` ] ( https://python.temporal.io/temporalio.client.Client.html#connect ) .
1341+
1342+ The purpose of the interceptor framework is that the methods you implement on your interceptor classes can perform
1343+ arbitrary side effects and/or arbitrary modifications to the data, before it is received by the SDK's "real"
1344+ implementation. The ` interceptors ` list can contain multiple interceptors. In this case they form a chain: a method
1345+ implemented on an interceptor instance in the list can perform side effects, and modify the data, before passing it on
1346+ to the corresponding method on the next interceptor in the list. Your interceptor classes need not implement every
1347+ method; the default implementation is always to pass the data on to the next method in the interceptor chain.
1348+
1349+ The remaining four categories are worker calls. To modify these, define a class inheriting from
1350+ [ ` worker.Interceptor ` ] ( https://python.temporal.io/temporalio.worker.Interceptor.html ) and implement methods on that
1351+ class to define the
1352+ [ ` ActivityInboundInterceptor ` ] ( https://python.temporal.io/temporalio.worker.ActivityInboundInterceptor.html ) ,
1353+ [ ` ActivityOutboundInterceptor ` ] ( https://python.temporal.io/temporalio.worker.ActivityOutboundInterceptor.html ) ,
1354+ [ ` WorkflowInboundInterceptor ` ] ( https://python.temporal.io/temporalio.worker.WorkflowInboundInterceptor.html ) , and
1355+ [ ` WorkflowOutboundInterceptor ` ] ( https://python.temporal.io/temporalio.worker.WorkflowOutboundInterceptor.html ) classes
1356+ that you wish to use to effect your modifications. Then, pass a list containing an instance of your ` worker.Interceptor `
1357+ class as the ` interceptors ` argument of the [ ` Worker() ` ] ( https://python.temporal.io/temporalio.worker.Worker.html )
1358+ constructor.
1359+
1360+ It often happens that your worker and client interceptors will share code because they implement closely related logic.
1361+ For convenience, you can create an interceptor class that inherits from _ both_ ` client.Interceptor ` and
1362+ ` worker.Interceptor ` (their method sets do not overlap). You can then pass this in the ` interceptors ` argument of
1363+ ` Client.connect() ` when starting your worker _ as well as_ in your client/starter code. If you do this, your worker will
1364+ automatically pick up the interceptors from its underlying client (and you should not pass them directly to the
1365+ ` Worker() ` constructor).
1366+
1367+ This is best explained by example. The [ Context Propagation Interceptor
1368+ Sample] ( https://github.com/temporalio/samples-python/tree/main/context_propagation ) is a good starting point. In
1369+ [ context_propagation/interceptor.py] ( https://github.com/temporalio/samples-python/blob/main/context_propagation/interceptor.py )
1370+ a class is defined that inherits from both ` client.Interceptor ` and ` worker.Interceptor ` . It implements the various
1371+ methods such that the outbound client and workflow calls set a certain key in the outbound ` headers ` field, and the
1372+ inbound workflow and activity calls retrieve the header value from the inbound workflow/activity input data. An instance
1373+ of this interceptor class is passed to ` Client.connect() ` when [ starting the
1374+ worker] ( https://github.com/temporalio/samples-python/blob/main/context_propagation/worker.py ) and when connecting the
1375+ client in the [ workflow starter
1376+ code] ( https://github.com/temporalio/samples-python/blob/main/context_propagation/starter.py ) .
1377+
1378+
13131379### Nexus
13141380
13151381⚠️ ** Nexus support is currently at an experimental release stage. Backwards-incompatible changes are anticipated until a stable release is announced.** ⚠️
0 commit comments