Skip to content

Commit 8232d0d

Browse files
committed
Add documentation of interceptors to README
1 parent f4ca16d commit 8232d0d

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
@@ -1310,6 +1311,68 @@ affect calls activity code might make to functions on the `temporalio.activity`
13101311
* `worker_shutdown()` can be invoked to simulate a worker shutdown during execution of the activity
13111312

13121313

1314+
### Interceptors
1315+
1316+
The behavior of the SDK can be customized in many useful ways by modifying inbound and outbound calls using
1317+
interceptors. This is similar to the use of middleware in other frameworks.
1318+
1319+
There are five categories of inbound and outbound calls that you can modify in this way:
1320+
1321+
1. Outbound client calls, such as `start_workflow()`, `signal_workflow()`, `list_workflows()`, `update_schedule()`, etc.
1322+
1323+
2. Inbound workflow calls: `execute_workflow()`, `handle_signal()`, `handle_update_handler()`, etc
1324+
1325+
3. Outbound workflow calls: `start_activity()`, `start_child_workflow()`, `start_nexus_operation()`, etc
1326+
1327+
4. Inbound call to execute an activity: `execute_activity()`
1328+
1329+
5. Outbound activity calls: `info()` and `hearbeat()`
1330+
1331+
1332+
To modify outbound client calls, define a class inheriting from
1333+
[`client.Interceptor`](https://python.temporal.io/temporalio.client.Interceptor.html), and implement the method
1334+
`intercept_client()` to return an instance of
1335+
[`OutboundInterceptor`](https://python.temporal.io/temporalio.client.OutboundInterceptor.html) that implements the
1336+
subset of outbound client calls that you wish to modify.
1337+
1338+
Then, pass a list containing an instance of your `client.Interceptor` class as the
1339+
`interceptors` argument of [`Client.connect()`](https://python.temporal.io/temporalio.client.Client.html#connect).
1340+
1341+
The purpose of the interceptor framework is that the methods you implement on your interceptor classes can perform
1342+
arbitrary side effects and/or arbitrary modifications to the data, before it is received by the SDK's "real"
1343+
implementation. The `interceptors` list can contain multiple interceptors. In this case they form a chain: a method
1344+
implemented on an interceptor instance in the list can perform side effects, and modify the data, before passing it on
1345+
to the corresponding method on the next interceptor in the list. Your interceptor classes need not implement every
1346+
method; the default implementation is always to pass the data on to the next method in the interceptor chain.
1347+
1348+
The remaining four categories are worker calls. To modify these, define a class inheriting from
1349+
[`worker.Interceptor`](https://python.temporal.io/temporalio.worker.Interceptor.html) and implement methods on that
1350+
class to define the
1351+
[`ActivityInboundInterceptor`](https://python.temporal.io/temporalio.worker.ActivityInboundInterceptor.html),
1352+
[`ActivityOutboundInterceptor`](https://python.temporal.io/temporalio.worker.ActivityOutboundInterceptor.html),
1353+
[`WorkflowInboundInterceptor`](https://python.temporal.io/temporalio.worker.WorkflowInboundInterceptor.html), and
1354+
[`WorkflowOutboundInterceptor`](https://python.temporal.io/temporalio.worker.WorkflowOutboundInterceptor.html) classes
1355+
that you wish to use to effect your modifications. Then, pass a list containing an instance of your `worker.Interceptor`
1356+
class as the `interceptors` argument of `Client.connect()`.
1357+
1358+
You can also pass worker interceptors as the `interceptor` argument to the
1359+
[`Worker()`](https://python.temporal.io/temporalio.worker.Worker.html) constructor but, if you do, do not pass the same
1360+
ones to `Client.connect()`. Finally, for convenience, it's common to define a class inheriting from _both_
1361+
`client.Interceptor` and `worker.Interceptor` (their method sets do not overlap), and define all your interceptor
1362+
customizations in the methods of that class.
1363+
1364+
This is best explained by example. The [Context Propagation Interceptor
1365+
Sample](https://github.com/temporalio/samples-python/tree/main/context_propagation) is a good starting point. In
1366+
[context_propagation/interceptor.py](https://github.com/temporalio/samples-python/blob/main/context_propagation/interceptor.py)
1367+
a class is defined that inherits from both `client.Interceptor` and `worker.Interceptor`. It implements the various
1368+
methods such that the outbound client and workflow calls set a certain key in the outbound `headers` field, and the
1369+
inbound workflow and activity calls retrieve the header value from the inbound workflow/activity input data. An instance
1370+
of this interceptor class is passed to `Client.connect` when [starting the
1371+
worker](https://github.com/temporalio/samples-python/blob/main/context_propagation/worker.py) and when connecting the
1372+
client in the [workflow starter
1373+
code](https://github.com/temporalio/samples-python/blob/main/context_propagation/starter.py).
1374+
1375+
13131376
### Nexus
13141377

13151378
⚠️ **Nexus support is currently at an experimental release stage. Backwards-incompatible changes are anticipated until a stable release is announced.** ⚠️

0 commit comments

Comments
 (0)