Follow-up from #51 / PR #60. ConcurrencyConfig.max_concurrent is now enforced for the concurrent strategy in process_message, but other dispatch paths each spawn tasks independently:
process_reaction → _dispatch_to_handlers(self._reaction_handlers, ...)
process_action
process_slash_command
process_modal_submit / process_modal_close
A burst of webhook traffic across event types can still exceed a single resource budget even with max_concurrent=N set. Options:
- Promote
_concurrent_semaphore to a shared bound across every dispatch path (not just message). Simple; breaks the current per-path isolation.
- Add separate
ConcurrencyConfig.max_concurrent_by_event_type knobs.
- Expose the semaphore on the
Chat so consumers can wrap custom handlers themselves.
No upstream parity signal — TS doesn't enforce max_concurrent at all. Revisit only if a real consumer hits unbounded concurrency under cross-event load.
Severity: low (no reported incidents; queue / drop strategies already have other backpressure; most adapters rate-limit at the webhook ingress).
Follow-up from #51 / PR #60.
ConcurrencyConfig.max_concurrentis now enforced for theconcurrentstrategy inprocess_message, but other dispatch paths each spawn tasks independently:process_reaction→_dispatch_to_handlers(self._reaction_handlers, ...)process_actionprocess_slash_commandprocess_modal_submit/process_modal_closeA burst of webhook traffic across event types can still exceed a single resource budget even with
max_concurrent=Nset. Options:_concurrent_semaphoreto a shared bound across every dispatch path (not just message). Simple; breaks the current per-path isolation.ConcurrencyConfig.max_concurrent_by_event_typeknobs.Chatso consumers can wrap custom handlers themselves.No upstream parity signal — TS doesn't enforce
max_concurrentat all. Revisit only if a real consumer hits unbounded concurrency under cross-event load.Severity: low (no reported incidents;
queue/dropstrategies already have other backpressure; most adapters rate-limit at the webhook ingress).