API
Follow-ups
Atomic child jobs declared on the parent Task and returned with Complete.
A handler declares its finite child graph in the registry and returns typed children with its successful result. The parent settlement and every child insert commit together; the worker never receives a generic producer client.
from taskq import Complete, Followup, FollowupTarget, Task, TaskRegistry
child = Task(
name="listing.enrich",
queue="enrichment",
input_model=EnrichInput,
output_model=EnrichOutput,
handler=enrich,
)
async def discover(payload: DiscoverInput) -> Complete:
return Complete(
result={"accepted": True},
followups=(
Followup(
step="enrich",
job_type=child.name,
queue=child.queue,
payload={"listing_id": payload.listing_id},
),
),
)
parent = Task(
name="listing.discover",
queue="discovery",
input_model=DiscoverInput,
output_model=DiscoverOutput,
followup_targets=(FollowupTarget(queue=child.queue, job_type=child.name),),
handler=discover,
)
registry = TaskRegistry((parent, child))
Rules
- Declare every child
(queue, job_type)onfollowup_targetsbefore the worker starts. - Worker construction rejects missing or queue-mismatched targets.
- HTTP completion authorizes the parent queue, then every distinct child queue, before SQL.
- Direct SQL retains the trusted runner-role boundary.
Shipped in migrations 0008_followups.sql (ADR-024 / ADR-025).