From 39ce21875dbb444e4c83088107aeaff313d421a1 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 3 Dec 2025 01:12:26 +0300 Subject: [PATCH 1/8] feat: add merge_global method for ContextRepo --- faststream/_internal/context/repository.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/faststream/_internal/context/repository.py b/faststream/_internal/context/repository.py index 8a3a57516f..c0418bdeca 100644 --- a/faststream/_internal/context/repository.py +++ b/faststream/_internal/context/repository.py @@ -17,7 +17,7 @@ def __init__(self, initial: dict[str, Any] | None = None, /) -> None: _global_context : a dictionary representing the global context _scope_context : a dictionary representing the scope context """ - self._global_context: dict[str, Any] = {"context": self} | (initial or {}) + self._global_context: dict[str, Any] = (initial or {}) | {"context": self} self._scope_context: dict[str, ContextVar[Any]] = {} @property @@ -164,5 +164,21 @@ def resolve(self, argument: str) -> Any: return v def clear(self) -> None: + """Reset global and scope contexts. + + Returns: + None + """ self._global_context = {"context": self} self._scope_context.clear() + + def merge_global(self, other: "ContextRepo") -> None: + """Merge the global context of another repository into the current one. + + Args: + other: Another ContextRepo instance. + + Returns: + None + """ + self._global_context |= other._global_context | {"context": self} From 6ee61ea51fc4fbd5036eb4bd8d92461a367a2015 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 3 Dec 2025 01:14:39 +0300 Subject: [PATCH 2/8] test: add tests for ContextRepo --- tests/utils/context/test_main.py | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/utils/context/test_main.py b/tests/utils/context/test_main.py index 6f0f783738..206d17241b 100644 --- a/tests/utils/context/test_main.py +++ b/tests/utils/context/test_main.py @@ -1,10 +1,45 @@ +from typing import Any + import pytest from fast_depends import ValidationError -from faststream import Context, ContextRepo +from faststream import Context +from faststream._internal.context import ContextRepo from faststream._internal.utils import apply_types +@pytest.mark.parametrize( + ("initial", "expected_context"), + ( + pytest.param(None, {}, id="without initial"), + pytest.param({"value": 42}, {"value": 42}, id="basic value"), + pytest.param({"context": "sus"}, {}, id="sus context"), + ), +) +def test_context_repo_constructor( + initial: dict[str, Any] | None, + expected_context: dict[str, Any], +) -> None: + repo = ContextRepo(initial) + repo_context = repo.context + + assert repo_context.get("context") is repo + repo_context.pop("context") + assert repo_context == expected_context + + +def test_context_repo_merge_global(): + repo_1 = ContextRepo({"value_1": 1, "value_2": 2}) + repo_2 = ContextRepo({"value_2": 3, "value_3": 4}) + + repo_1.merge_global(repo_2) + + assert repo_1.get("value_1") == 1 + assert repo_1.get("value_2") == 3 + assert repo_1.get("value_3") == 4 + assert repo_1.get("context") is repo_1 + + def test_context_getattr(context: ContextRepo) -> None: a = 1000 context.set_global("key", a) From e8b73f6b0e48612b92c25ec87e5ddd6bf5664c70 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 3 Dec 2025 01:16:23 +0300 Subject: [PATCH 3/8] feat: merge ContextRepos in FastDependsConfig --- faststream/_internal/di/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/faststream/_internal/di/config.py b/faststream/_internal/di/config.py index 6a841fc023..1e7f49cd6c 100644 --- a/faststream/_internal/di/config.py +++ b/faststream/_internal/di/config.py @@ -50,6 +50,7 @@ def _serializer(self) -> Optional["SerializerProto"]: def __or__(self, value: "FastDependsConfig", /) -> "FastDependsConfig": use_fd = False if not value.use_fastdepends else self.use_fastdepends + self.context.merge_global(value.context) return FastDependsConfig( use_fastdepends=use_fd, From cfc501ca30ba2b703cd8ef2d0b33cf51f585b504 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 3 Dec 2025 01:17:34 +0300 Subject: [PATCH 4/8] test: FastDependsConfig merging --- tests/application/test_delayed_broker.py | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/application/test_delayed_broker.py b/tests/application/test_delayed_broker.py index 2f5596f317..b507368324 100644 --- a/tests/application/test_delayed_broker.py +++ b/tests/application/test_delayed_broker.py @@ -1,6 +1,8 @@ import pytest from faststream._internal.application import StartAbleApplication +from faststream._internal.context import ContextRepo +from faststream._internal.di import FastDependsConfig from faststream.exceptions import SetupError from faststream.rabbit import RabbitBroker @@ -45,3 +47,32 @@ async def test_di_reconfigured() -> None: app.set_broker(broker) assert broker.context.get("app") is app + + +def test_broker_and_app_contexts_merge() -> None: + broker = RabbitBroker( + context=ContextRepo({ + "broker_dependency": 1, + "override_dependency": 2, + }) + ) + + config = FastDependsConfig( + context=ContextRepo({ + "application_dependency": 3, + "override_dependency": 4, + }) + ) + app = StartAbleApplication(config=config) + application_context = app.context + + # if the broker binds to the application, + # the broker modifies the application context and uses it as its own. + app.set_broker(broker) + + assert app.context is application_context + assert broker.context is application_context + assert app.context.get("broker_dependency") == 1 + assert app.context.get("application_dependency") == 3 + # the broker context overwrites the application context + assert app.context.get("override_dependency") == 2 From def58dc5132a14058cd15117a6a22ec4843ff3b6 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 17 Dec 2025 23:18:33 +0300 Subject: [PATCH 5/8] refactor(docs): move sections on the context page --- docs/docs/en/getting-started/context.md | 191 ++++++++++++------------ 1 file changed, 95 insertions(+), 96 deletions(-) diff --git a/docs/docs/en/getting-started/context.md b/docs/docs/en/getting-started/context.md index 2ba504084e..c7e4049ff1 100644 --- a/docs/docs/en/getting-started/context.md +++ b/docs/docs/en/getting-started/context.md @@ -8,37 +8,81 @@ search: boost: 10 --- -# Context Fields Declaration +# Context -You can also store your own objects in the `Context`. +**FastStreams** has its own Dependency Injection container - **Context**, used to store application runtime objects and variables. + +With this container, you can access both application scope and message processing scope objects. This functionality is similar to [`Depends`](./dependencies/index.md){.internal-link} usage. + +=== "AIOKafka" + ```python linenums="1" hl_lines="2 4 12" + {!> docs_src/getting_started/context/kafka/annotated.py !} + ``` + +=== "Confluent" + ```python linenums="1" hl_lines="2 4 12" + {!> docs_src/getting_started/context/confluent/annotated.py !} + ``` + +=== "RabbitMQ" + ```python linenums="1" hl_lines="2 4 12" + {!> docs_src/getting_started/context/rabbit/annotated.py !} + ``` + +=== "NATS" + ```python linenums="1" hl_lines="2 4 12" + {!> docs_src/getting_started/context/nats/annotated.py !} + ``` + +=== "Redis" + ```python linenums="1" hl_lines="2 4 12" + {!> docs_src/getting_started/context/redis/annotated.py !} + ``` + +By default, the context is available in the same place as `Depends`: + +* at lifespan hooks +* message subscribers +* nested dependencies + +!!! tip + You can also get access to the **Context**: -## Global + * in [Middlewares](../middlewares/#context-access){.internal-link} as `#!python self.context` + * through the application property `#!python app.context` + * through the broker property `#!python broker.context` + +## Fields Declaration + +You can store your own objects in the `Context`. + +### Global To declare an application-level context field, you need to call the `context.set_global` method with a key to indicate where the object will be placed in the context. === "AIOKafka" ```python linenums="1" hl_lines="8-9" - {!> docs_src/getting_started/context/kafka/custom_global_context.py [ln:1-5,13-16] !} + {!> docs_src/getting_started/context/kafka/custom_global_context.py [ln:1-6,13-16] !} ``` === "Confluent" ```python linenums="1" hl_lines="8-9" - {!> docs_src/getting_started/context/confluent/custom_global_context.py [ln:1-5,13-16] !} + {!> docs_src/getting_started/context/confluent/custom_global_context.py [ln:1-6,13-16] !} ``` === "RabbitMQ" ```python linenums="1" hl_lines="8-9" - {!> docs_src/getting_started/context/rabbit/custom_global_context.py [ln:1-5,13-16] !} + {!> docs_src/getting_started/context/rabbit/custom_global_context.py [ln:1-6,13-16] !} ``` === "NATS" ```python linenums="1" hl_lines="8-9" - {!> docs_src/getting_started/context/nats/custom_global_context.py [ln:1-5,13-16] !} + {!> docs_src/getting_started/context/nats/custom_global_context.py [ln:1-6,13-16] !} ``` === "Redis" ```python linenums="1" hl_lines="8-9" - {!> docs_src/getting_started/context/redis/custom_global_context.py [ln:1-5,13-16] !} + {!> docs_src/getting_started/context/redis/custom_global_context.py [ln:1-6,13-16] !} ``` Afterward, you can access your `secret` field in the usual way: @@ -68,7 +112,7 @@ Afterward, you can access your `secret` field in the usual way: {!> docs_src/getting_started/context/redis/custom_global_context.py [ln:8-13] !} ``` -In this case, the field becomes a global context field: it does not depend on the current message handler (unlike `message`) +In this case, the field becomes a global context field: it does not depend on the current message handler (unlike `message`). !!! tip Alternatively you can setup global context objects in `FastStream` object constructor: @@ -88,7 +132,7 @@ To remove a field from the context use the `reset_global` method: context.reset_global("my_key") ``` -## Local +### Local To set a local context (available only within the message processing scope), use the context manager `scope`. It could me extremely uselful to fill context with additional options in [Middlewares](../middlewares/){.internal-link} @@ -157,6 +201,47 @@ By default, the context searches for an object based on the argument name. {!> docs_src/getting_started/context/redis/existed_context.py [ln:1-2,9-12,14-23] !} ``` +### Access by Name + +Sometimes, you may need to use a different name for the argument (not the one under which it is stored in the context) or get access to specific parts of the object. To do this, simply specify the name of what you want to access, and the context will provide you with the object. + +=== "AIOKafka" + ```python linenums="1" hl_lines="11-12" + {!> docs_src/getting_started/context/kafka/fields_access.py !} + ``` + +=== "Confluent" + ```python linenums="1" hl_lines="11-12" + {!> docs_src/getting_started/context/confluent/fields_access.py !} + ``` + +=== "RabbitMQ" + ```python linenums="1" hl_lines="11-12" + {!> docs_src/getting_started/context/rabbit/fields_access.py !} + ``` + +=== "NATS" + ```python linenums="1" hl_lines="11-12" + {!> docs_src/getting_started/context/nats/fields_access.py !} + ``` + +=== "Redis" + ```python linenums="1" hl_lines="11-12" + {!> docs_src/getting_started/context/redis/fields_access.py !} + ``` + +This way you can get access to context object specific field + +```python +{! docs_src/getting_started/context/kafka/fields_access.py [ln:11] !} +``` + +Or even to a dict key + +```python +{! docs_src/getting_started/context/kafka/fields_access.py [ln:12] !} +``` + ### Annotated Aliases Also, **FastStream** has already created `Annotated` aliases to provide you with comfortable access to existing objects. You can import them directly from `faststream` or your broker-specific modules: @@ -390,89 +475,3 @@ Also, `Context` provides you with a `initial` option to setup base context value ```python linenums="1" hl_lines="4 6" {!> docs_src/getting_started/context/redis/initial.py [ln:7-12] !} ``` - -## Access by Name - -Sometimes, you may need to use a different name for the argument (not the one under which it is stored in the context) or get access to specific parts of the object. To do this, simply specify the name of what you want to access, and the context will provide you with the object. - -=== "AIOKafka" - ```python linenums="1" hl_lines="11-12" - {!> docs_src/getting_started/context/kafka/fields_access.py !} - ``` - -=== "Confluent" - ```python linenums="1" hl_lines="11-12" - {!> docs_src/getting_started/context/confluent/fields_access.py !} - ``` - -=== "RabbitMQ" - ```python linenums="1" hl_lines="11-12" - {!> docs_src/getting_started/context/rabbit/fields_access.py !} - ``` - -=== "NATS" - ```python linenums="1" hl_lines="11-12" - {!> docs_src/getting_started/context/nats/fields_access.py !} - ``` - - -=== "Redis" - ```python linenums="1" hl_lines="11-12" - {!> docs_src/getting_started/context/redis/fields_access.py !} - ``` - -This way you can get access to context object specific field - - -```python -{! docs_src/getting_started/context/kafka/fields_access.py [ln:11] !} -``` - -Or even to a dict key - - -```python -{! docs_src/getting_started/context/kafka/fields_access.py [ln:12] !} -``` - -## Application Context - -**FastStreams** has its own Dependency Injection container - **Context**, used to store application runtime objects and variables. - -With this container, you can access both application scope and message processing scope objects. This functionality is similar to [`Depends`](../dependencies/index.md){.internal-link} usage. - -=== "AIOKafka" - ```python linenums="1" hl_lines="2 4 12" - {!> docs_src/getting_started/context/kafka/annotated.py !} - ``` - -=== "Confluent" - ```python linenums="1" hl_lines="2 4 12" - {!> docs_src/getting_started/context/confluent/annotated.py !} - ``` - -=== "RabbitMQ" - ```python linenums="1" hl_lines="2 4 12" - {!> docs_src/getting_started/context/rabbit/annotated.py !} - ``` - -=== "NATS" - ```python linenums="1" hl_lines="2 4 12" - {!> docs_src/getting_started/context/nats/annotated.py !} - ``` - -=== "Redis" - ```python linenums="1" hl_lines="2 4 12" - {!> docs_src/getting_started/context/redis/annotated.py !} - ``` - -### Usages - -By default, the context is available in the same place as `Depends`: - -* at lifespan hooks -* message subscribers -* nested dependencies - -!!! tip - You can get access to the **Context** in [Middlewares](../middlewares/#context-access){.internal-link} as `#!python self.context` From c618c66960210ca0c22b67e5c824c92eb246ed73 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 17 Dec 2025 23:23:18 +0300 Subject: [PATCH 6/8] docs: add examples for broker-level context declaration --- .../context/confluent/custom_broker_context.py | 14 ++++++++++++++ .../context/kafka/custom_broker_context.py | 14 ++++++++++++++ .../context/nats/custom_broker_context.py | 14 ++++++++++++++ .../context/rabbit/custom_broker_context.py | 14 ++++++++++++++ .../context/redis/custom_broker_context.py | 14 ++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 docs/docs_src/getting_started/context/confluent/custom_broker_context.py create mode 100644 docs/docs_src/getting_started/context/kafka/custom_broker_context.py create mode 100644 docs/docs_src/getting_started/context/nats/custom_broker_context.py create mode 100644 docs/docs_src/getting_started/context/rabbit/custom_broker_context.py create mode 100644 docs/docs_src/getting_started/context/redis/custom_broker_context.py diff --git a/docs/docs_src/getting_started/context/confluent/custom_broker_context.py b/docs/docs_src/getting_started/context/confluent/custom_broker_context.py new file mode 100644 index 0000000000..a8fa75576a --- /dev/null +++ b/docs/docs_src/getting_started/context/confluent/custom_broker_context.py @@ -0,0 +1,14 @@ +from typing import Annotated +from faststream import Context, ContextRepo +from faststream.confluent import KafkaBroker + +broker = KafkaBroker( + "localhost:9092", + context=ContextRepo({"secret_str": "my-perfect-secret"}), +) + +@broker.subscriber("test-topic") +async def handle( + secret_str: Annotated[str, Context()], +): + assert secret_str == "my-perfect-secret" diff --git a/docs/docs_src/getting_started/context/kafka/custom_broker_context.py b/docs/docs_src/getting_started/context/kafka/custom_broker_context.py new file mode 100644 index 0000000000..59c7a1a977 --- /dev/null +++ b/docs/docs_src/getting_started/context/kafka/custom_broker_context.py @@ -0,0 +1,14 @@ +from typing import Annotated +from faststream import Context, ContextRepo +from faststream.kafka import KafkaBroker + +broker = KafkaBroker( + "localhost:9092", + context=ContextRepo({"secret_str": "my-perfect-secret"}), +) + +@broker.subscriber("test-topic") +async def handle( + secret_str: Annotated[str, Context()], +): + assert secret_str == "my-perfect-secret" diff --git a/docs/docs_src/getting_started/context/nats/custom_broker_context.py b/docs/docs_src/getting_started/context/nats/custom_broker_context.py new file mode 100644 index 0000000000..3a4ce8d1e4 --- /dev/null +++ b/docs/docs_src/getting_started/context/nats/custom_broker_context.py @@ -0,0 +1,14 @@ +from typing import Annotated +from faststream import Context, ContextRepo +from faststream.nats import NatsBroker + +broker = NatsBroker( + "nats://localhost:4222", + context=ContextRepo({"secret_str": "my-perfect-secret"}), +) + +@broker.subscriber("test-subject") +async def handle( + secret_str: Annotated[str, Context()], +): + assert secret_str == "my-perfect-secret" diff --git a/docs/docs_src/getting_started/context/rabbit/custom_broker_context.py b/docs/docs_src/getting_started/context/rabbit/custom_broker_context.py new file mode 100644 index 0000000000..235de18aef --- /dev/null +++ b/docs/docs_src/getting_started/context/rabbit/custom_broker_context.py @@ -0,0 +1,14 @@ +from typing import Annotated +from faststream import Context, ContextRepo +from faststream.rabbit import RabbitBroker + +broker = RabbitBroker( + "amqp://guest:guest@localhost:5672/", + context=ContextRepo({"secret_str": "my-perfect-secret"}), +) + +@broker.subscriber("test-queue") +async def handle( + secret_str: Annotated[str, Context()], +): + assert secret_str == "my-perfect-secret" diff --git a/docs/docs_src/getting_started/context/redis/custom_broker_context.py b/docs/docs_src/getting_started/context/redis/custom_broker_context.py new file mode 100644 index 0000000000..523e09463f --- /dev/null +++ b/docs/docs_src/getting_started/context/redis/custom_broker_context.py @@ -0,0 +1,14 @@ +from typing import Annotated +from faststream import Context, ContextRepo +from faststream.redis import RedisBroker + +broker = RedisBroker( + "redis://localhost:6379", + context=ContextRepo({"secret_str": "my-perfect-secret"}), +) + +@broker.subscriber("test-channel") +async def handle( + secret_str: Annotated[str, Context()], +): + assert secret_str == "my-perfect-secret" From 9347f83e4a5e1a7ba2cb5e3ef8e7d9d6ccb93232 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 17 Dec 2025 23:24:15 +0300 Subject: [PATCH 7/8] test: broker-level context declaration examples --- .../context/test_custom_broker.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/docs/getting_started/context/test_custom_broker.py diff --git a/tests/docs/getting_started/context/test_custom_broker.py b/tests/docs/getting_started/context/test_custom_broker.py new file mode 100644 index 0000000000..b0c996c27f --- /dev/null +++ b/tests/docs/getting_started/context/test_custom_broker.py @@ -0,0 +1,84 @@ +import pytest + +from tests.marks import ( + require_aiokafka, + require_aiopika, + require_confluent, + require_nats, + require_redis, +) + + +@pytest.mark.asyncio() +@require_aiokafka +async def test_custom_broker_context_kafka() -> None: + from docs.docs_src.getting_started.context.kafka.custom_broker_context import ( + broker, + handle, + ) + from faststream.kafka import TestKafkaBroker + + async with TestKafkaBroker(broker) as br: + await br.publish("Hi!", "test-topic") + + handle.mock.assert_called_once_with("Hi!") + + +@pytest.mark.asyncio() +@require_confluent +async def test_custom_broker_context_confluent() -> None: + from docs.docs_src.getting_started.context.confluent.custom_broker_context import ( + broker, + handle, + ) + from faststream.confluent import TestKafkaBroker as TestConfluentKafkaBroker + + async with TestConfluentKafkaBroker(broker) as br: + await br.publish("Hi!", "test-topic") + + handle.mock.assert_called_once_with("Hi!") + + +@pytest.mark.asyncio() +@require_aiopika +async def test_custom_broker_context_rabbit() -> None: + from docs.docs_src.getting_started.context.rabbit.custom_broker_context import ( + broker, + handle, + ) + from faststream.rabbit import TestRabbitBroker + + async with TestRabbitBroker(broker) as br: + await br.publish("Hi!", "test-queue") + + handle.mock.assert_called_once_with("Hi!") + + +@pytest.mark.asyncio() +@require_nats +async def test_custom_broker_context_nats() -> None: + from docs.docs_src.getting_started.context.nats.custom_broker_context import ( + broker, + handle, + ) + from faststream.nats import TestNatsBroker + + async with TestNatsBroker(broker) as br: + await br.publish("Hi!", "test-subject") + + handle.mock.assert_called_once_with("Hi!") + + +@pytest.mark.asyncio() +@require_redis +async def test_custom_broker_context_redis() -> None: + from docs.docs_src.getting_started.context.redis.custom_broker_context import ( + broker, + handle, + ) + from faststream.redis import TestRedisBroker + + async with TestRedisBroker(broker) as br: + await br.publish("Hi!", "test-channel") + + handle.mock.assert_called_once_with("Hi!") From 7350ef9ea0242417d228216b271a029dbadc0505 Mon Sep 17 00:00:00 2001 From: Nectarin Date: Wed, 17 Dec 2025 23:26:13 +0300 Subject: [PATCH 8/8] docs: add broker-level context declaration section on page --- docs/docs/en/getting-started/context.md | 61 +++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/docs/docs/en/getting-started/context.md b/docs/docs/en/getting-started/context.md index c7e4049ff1..cb6eb4ae94 100644 --- a/docs/docs/en/getting-started/context.md +++ b/docs/docs/en/getting-started/context.md @@ -58,6 +58,10 @@ You can store your own objects in the `Context`. ### Global +Global context fields can be set at both the application-level and the broker-level. + +#### Application-level + To declare an application-level context field, you need to call the `context.set_global` method with a key to indicate where the object will be placed in the context. === "AIOKafka" @@ -132,6 +136,63 @@ To remove a field from the context use the `reset_global` method: context.reset_global("my_key") ``` +#### Broker-level + +There are cases when you may need to use broker without using the `FastStream` application class. +In such cases, the context can be set separately for the broker by passing it through the constructor. + +=== "AIOKafka" + ```python linenums="1" hl_lines="7" + {!> docs_src/getting_started/context/kafka/custom_broker_context.py [ln:1-8] !} + ``` + +=== "Confluent" + ```python linenums="1" hl_lines="7" + {!> docs_src/getting_started/context/confluent/custom_broker_context.py [ln:1-8] !} + ``` + +=== "RabbitMQ" + ```python linenums="1" hl_lines="7" + {!> docs_src/getting_started/context/rabbit/custom_broker_context.py [ln:1-8] !} + ``` + +=== "NATS" + ```python linenums="1" hl_lines="7" + {!> docs_src/getting_started/context/nats/custom_broker_context.py [ln:1-8] !} + ``` + +=== "Redis" + ```python linenums="1" hl_lines="7" + {!> docs_src/getting_started/context/redis/custom_broker_context.py [ln:1-8] !} + ``` + +At the same time, access to the context remains unchanged. + +=== "AIOKafka" + ```python linenums="1" hl_lines="3" + {!> docs_src/getting_started/context/kafka/custom_broker_context.py [ln:10-14] !} + ``` + +=== "Confluent" + ```python linenums="1" hl_lines="3" + {!> docs_src/getting_started/context/confluent/custom_broker_context.py [ln:10-14] !} + ``` + +=== "RabbitMQ" + ```python linenums="1" hl_lines="3" + {!> docs_src/getting_started/context/rabbit/custom_broker_context.py [ln:10-14] !} + ``` + +=== "NATS" + ```python linenums="1" hl_lines="3" + {!> docs_src/getting_started/context/nats/custom_broker_context.py [ln:10-14] !} + ``` + +=== "Redis" + ```python linenums="1" hl_lines="3" + {!> docs_src/getting_started/context/redis/custom_broker_context.py [ln:10-14] !} + ``` + ### Local To set a local context (available only within the message processing scope), use the context manager `scope`. It could me extremely uselful to fill context with additional options in [Middlewares](../middlewares/){.internal-link}