Skip to content

feat(event-dispatcher): add async in-process event bus#12

Merged
pedro-fs-garcia merged 1 commit into
developfrom
feat/event-dispatcher
Apr 18, 2026
Merged

feat(event-dispatcher): add async in-process event bus#12
pedro-fs-garcia merged 1 commit into
developfrom
feat/event-dispatcher

Conversation

@pedro-fs-garcia
Copy link
Copy Markdown
Contributor

@pedro-fs-garcia pedro-fs-garcia commented Apr 18, 2026

Implement EventDispatcher core module to decouple domain emitters from consumers, avoiding circular dependencies and growing coupling between domains (chatbot, ticket, live_chat).

Summary

  • Introduce an async in-process EventDispatcher in app/core/event_dispatcher/ to decouple cross-domain side effects (e.g. triage completion triggering ticket creation and conversation opening) without external infrastructure (Kafka, Redis, etc.)
  • Define typed Pydantic payload schemas and an AppEvent enum catalog for 6 domain events: triage.finished, ticket.created, ticket.assignee_updated, ticket.status_updated, ticket.escalated, ticket.closed
  • Enforce handler correctness at startup via @event_handler decorator validation and EVENT_PAYLOAD_MAP wiring — schema mismatches raise InvalidHandlerError before the app serves traffic
  • Handlers run as independent asyncio.Task (fire-and-forget) with structured exception logging, so a failing listener never blocks the emitter or other listeners
  • Wire dispatcher singleton into FastAPI lifespan (main.py) with a register_app_events_listeners hook ready for domain listeners

Motivation

As business flows grow (triage → ticket → conversation → notification), injecting services across domains creates circular dependencies and violates domain boundaries. The dispatcher inverts this: emitters publish events without knowing who reacts, and new side effects are added by subscribing listeners — no changes to the originating service.

See docs/event_dispatcher.md for the architectural decision, event catalog, chained event flow, and usage guidelines.

Test plan

  • Unit tests for EventDispatcher.subscribe and publish — valid handlers, duplicate subscription idempotency, payload type mismatch rejection
  • Unit tests for @event_handler decorator — payload validation, error logging on handler failure, schema error propagation
  • Verify app starts without errors and logs Registering event listeners to EventDispatcher.
  • Confirm no regressions on existing endpoints

🤖 Generated with Claude Code

…in communication

Implement EventDispatcher core module to decouple domain emitters from
consumers, avoiding circular dependencies and growing coupling between
domains (chatbot, ticket, live_chat).

- EventDispatcher class with subscribe/publish using asyncio fire-and-forget tasks
- @event_handler decorator with payload type validation and structured error logging
- Typed Pydantic schemas for domain events
- EVENT_PAYLOAD_MAP for compile-time wiring validation at startup
- Custom exceptions: EventSchemaError, InvalidHandlerError
- Singleton access via get_event_dispatcher (lru_cache)
- Integration in app lifespan (main.py) with listener registration hook
- Unit tests for dispatcher logic and decorator behavior
- Module README and architectural docs (docs/event_dispatcher.md)
@pedro-fs-garcia pedro-fs-garcia changed the title feat(event-dispatcher): add async in-process event bus for inter-doma… feat(event-dispatcher): add async in-process event bus Apr 18, 2026
@pedro-fs-garcia pedro-fs-garcia self-assigned this Apr 18, 2026
@pedro-fs-garcia pedro-fs-garcia merged commit f643152 into develop Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

US04-T01: Definir contrato do Event Dispatcher

1 participant