4.0 KiB
Capability Spec Delta: api-ws-broker-in-memory (api-ws-broker-in-memory)
Package: @suaveplan/api-ws-broker-in-memory
Status: PROPOSED
ADDED Requirements
Requirement: Fan-out to every subscriber on publish
The broker SHALL deliver publish(topic, message) to every connection currently subscribed to topic. Delivery order across subscribers is unspecified; per-subscriber message order is FIFO.
Scenario: every subscriber receives every message
- WHEN three connections subscribe to
"orders.created"AND two messages are published - THEN each connection receives both messages in publish order
Verified by: src/factory/create-in-memory-ws-broker.test.ts::"every subscriber receives every published message in FIFO order"
Requirement: Subscription lifecycle
The broker SHALL expose subscribe(connectionId, topic), unsubscribe(connectionId, topic), and cleanupConnection(connectionId). cleanupConnection removes the connection from every topic it was subscribed to.
Scenario: unsubscribe stops delivery
- WHEN a connection subscribes, then unsubscribes, then a message is published
- THEN the connection does NOT receive the message
Scenario: cleanupConnection removes from every topic
- WHEN a connection is subscribed to
["a", "b", "c"]ANDcleanupConnection(id)is called - THEN
subscribersOf("a"),subscribersOf("b"),subscribersOf("c")no longer includeid
Scenario: cleanup is idempotent
- WHEN
cleanupConnection(id)is called twice - THEN the second call is a no-op AND no error is thrown
Verified by: src/factory/create-in-memory-ws-broker.test.ts::"unsubscribe stops delivery" AND src/factory/create-in-memory-ws-broker.test.ts::"cleanupConnection removes from every topic" AND src/factory/create-in-memory-ws-broker.test.ts::"cleanupConnection is idempotent"
Requirement: maxSubscribersPerTopic enforced when set
When options.maxSubscribersPerTopic is set AND a new subscribe would exceed it, the broker SHALL throw WS_BROKER_IN_MEMORY_MAX_SUBSCRIBERS_EXCEEDED.
Scenario: subscribe rejected at cap
- WHEN
maxSubscribersPerTopic: 2AND two connections subscribe AND a third tries to subscribe - THEN the third call throws
WS_BROKER_IN_MEMORY_MAX_SUBSCRIBERS_EXCEEDED
Verified by: src/factory/create-in-memory-ws-broker.test.ts::"subscribe throws when maxSubscribersPerTopic is exceeded"
Requirement: Delivery mode semantics
deliveryMode: "await-all" SHALL await every subscriber's handler before publish resolves. "fire-and-forget" SHALL return immediately after dispatch.
Scenario: await-all awaits every handler
- WHEN
deliveryMode: "await-all"AND two subscribers each return a 50ms-delayed promise - THEN
publishresolves only after both promises settle (measurable timing)
Scenario: fire-and-forget returns synchronously
- WHEN
deliveryMode: "fire-and-forget" - THEN
publishresolves before any subscriber's delayed promise has settled
Verified by: src/delivery/delivery-mode.test.ts::"await-all blocks publish until every handler settles" AND src/delivery/delivery-mode.test.ts::"fire-and-forget resolves publish synchronously"
Requirement: Conforms to WsBroker contract
Scenario: conformance suite passes
- WHEN
runWsBrokerConformance("in-memory-direct", () => createInMemoryWsBroker(...))runs - THEN every invariant passes
Verified by: src/factory/create-in-memory-ws-broker.spec-conformance.test.ts::"in-memory-direct conforms to WsBroker contract"
Requirement: Registered in api-host/testing adapter table
Scenario: createTestHost resolves the sentinel
- WHEN
createTestHost({ adapters: { "ws.broker": "in-memory" } }) - THEN the resulting
host.ws.brokeris an instance produced by this factory
Verified by: tests/integration/integration.test.ts::"createTestHost resolves ws.broker:\"in-memory\" to this adapter"