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