Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ client = Redis.from_url("redis://localhost:6379")
broker = TimersBroker(client)
app = FastStream(broker)


@broker.subscriber("invoices")
async def handle_invoice(invoice_id: str) -> None:
print(f"Invoice {invoice_id} is due!")


@app.after_startup
async def schedule() -> None:
await broker.publish(
Expand Down Expand Up @@ -107,13 +109,13 @@ Inside the handler:
```python
from faststream import Context


@broker.subscriber("orders")
async def handle(
body: dict,
correlation_id: str = Context("message.correlation_id"),
tenant: str = Context("message.headers.x-tenant"),
) -> None:
...
) -> None: ...
```

## Connection ownership
Expand Down
4 changes: 3 additions & 1 deletion docs/usage/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Use `broker.publish()` with `activate_in` (relative delay) or `activate_at` (abs
```python
from datetime import UTC, datetime, timedelta


@app.after_startup
async def schedule_reminder() -> None:
# Relative — fire 24 hours from now
Expand Down Expand Up @@ -143,7 +144,8 @@ pending = await broker.get_pending_timers("invoices")

# Only those due in the next hour
soon = await broker.get_pending_timers(
"invoices", before=datetime.now(tz=UTC) + timedelta(hours=1),
"invoices",
before=datetime.now(tz=UTC) + timedelta(hours=1),
)

# Wipe a topic's queue (e.g., during a maintenance reset)
Expand Down
5 changes: 3 additions & 2 deletions docs/usage/publisher.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,14 @@ from faststream.message import StreamMessage

pub = broker.publisher("orders")


@broker.subscriber("orders")
async def handle(
body: dict,
correlation_id: str = Context("message.correlation_id"),
tenant: str = Context("message.headers.x-tenant"),
) -> None:
...
) -> None: ...


await pub.publish(
{"order_id": 42},
Expand Down
8 changes: 4 additions & 4 deletions docs/usage/router.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ You can configure polling behaviour per subscriber:
```python
@router.subscriber(
"high-priority",
polling_interval=0.01, # poll every 10ms when the queue has work
max_polling_interval=0.5, # cap idle-backoff at 500ms (default 5s)
max_concurrent=20, # up to 20 handlers may run in parallel
lease_ttl=60, # hold lease for up to 60 seconds
polling_interval=0.01, # poll every 10ms when the queue has work
max_polling_interval=0.5, # cap idle-backoff at 500ms (default 5s)
max_concurrent=20, # up to 20 handlers may run in parallel
lease_ttl=60, # hold lease for up to 60 seconds
)
async def handle_urgent(message: str) -> None: ...
```
Expand Down
12 changes: 6 additions & 6 deletions docs/usage/subscriber.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ Configure polling behaviour per subscriber:
```python
@broker.subscriber(
"high-priority",
polling_interval=0.01, # poll every 10ms when busy
max_polling_interval=0.5, # never sleep longer than 500ms when idle
max_concurrent=20, # up to 20 handlers may run in parallel
lease_ttl=60, # hold lease for up to 60 seconds
polling_interval=0.01, # poll every 10ms when busy
max_polling_interval=0.5, # never sleep longer than 500ms when idle
max_concurrent=20, # up to 20 handlers may run in parallel
lease_ttl=60, # hold lease for up to 60 seconds
)
async def handle_urgent(body: str) -> None: ...
```
Expand Down Expand Up @@ -113,7 +113,7 @@ async def handle_invoice(
process(body)
await msg.ack()
except TransientError:
await msg.nack() # retry later
await msg.nack() # retry later
except PermanentError:
await msg.reject() # discard permanently
await msg.reject() # discard permanently
```
2 changes: 2 additions & 0 deletions planning/changes/2026-06-03.01-faststream-0.7-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ _parser: AsyncCallable
_decoder: AsyncCallable
codec: CodecProto # NEW in 0.7


# faststream/_internal/endpoint/subscriber/usecase.py — add_call signature
def add_call(
self,
Expand All @@ -217,6 +218,7 @@ def add_call(
codec_: Optional[CodecProto] = None, # NEW; timers passes nothing
) -> Self: ...


# faststream/_internal/testing/broker.py — create_publisher_fake_subscriber
@abstractmethod
def create_publisher_fake_subscriber(
Expand Down
1 change: 1 addition & 0 deletions planning/changes/2026-06-29.01-python-3.11-3.12-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Alternatives rejected:
becomes
```python
from typing_extensions import TypeAlias

RedisClient: TypeAlias = "Redis[bytes] | Redis[str]"
```
(Comment block above the alias is preserved.)
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ ignore = [
"ISC001", # flake8-implicit-str-concat
"G004", # Logging statement uses f-string
"ANN",
"CPY001", # no per-file copyright header
]
isort.lines-after-imports = 2
isort.no-lines-before = ["standard-library", "local-folder"]
Expand Down