docs(20): complete plan 20-01 SSE streaming summary and state update
This commit is contained in:
@@ -9,19 +9,19 @@ See: .planning/PROJECT.md (updated 2026-02-04)
|
|||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 19 of 21 (Agent Inbox) - COMPLETE
|
Phase: 20 of 21 (Real-Time Subscriptions) - IN PROGRESS
|
||||||
Plan: 4 of 4 in current phase
|
Plan: 1 of 2 in current phase
|
||||||
Status: Phase 19 complete
|
Status: Completed 20-01 (SSE Streaming & Subscription Procedures)
|
||||||
Last activity: 2026-02-04 - Completed 19-04-PLAN.md (Inbox Page Assembly)
|
Last activity: 2026-02-04 - Completed 20-01-PLAN.md (SSE backend)
|
||||||
|
|
||||||
Progress: █████████░ 98%
|
Progress: █████████░ 99%
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
**Velocity:**
|
**Velocity:**
|
||||||
- Total plans completed: 70
|
- Total plans completed: 71
|
||||||
- Average duration: 3 min
|
- Average duration: 3 min
|
||||||
- Total execution time: 197 min
|
- Total execution time: 201 min
|
||||||
|
|
||||||
**By Phase (v1.0):**
|
**By Phase (v1.0):**
|
||||||
|
|
||||||
@@ -225,6 +225,10 @@ Recent decisions affecting current work:
|
|||||||
- 19-04: Detail panel inline in page file (not a separate component) — page-specific layout
|
- 19-04: Detail panel inline in page file (not a separate component) — page-specific layout
|
||||||
- 19-04: useUtils() for query invalidation on mutation success (same pattern as initiative detail)
|
- 19-04: useUtils() for query invalidation on mutation success (same pattern as initiative detail)
|
||||||
- 19-04: Serialize agent/message data to string dates for InboxList props (wire format consistency)
|
- 19-04: Serialize agent/message data to string dates for InboxList props (wire format consistency)
|
||||||
|
- 20-01: Queue + deferred promise pattern for bridging push (EventBus) to pull (async generator)
|
||||||
|
- 20-01: tracked() wrapper on each event for client-side reconnection via lastEventId
|
||||||
|
- 20-01: Fallback AbortSignal (new AbortController().signal) when opts.signal is undefined
|
||||||
|
- 20-01: Vite proxy works for SSE without changes (http-proxy streams chunked responses by default)
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -247,5 +251,5 @@ None.
|
|||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-02-04
|
Last session: 2026-02-04
|
||||||
Stopped at: Completed 19-04 (Inbox Page Assembly) — Phase 19 complete
|
Stopped at: Completed 20-01 (SSE Streaming & Subscription Procedures)
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
124
.planning/phases/20-real-time-subscriptions/20-01-SUMMARY.md
Normal file
124
.planning/phases/20-real-time-subscriptions/20-01-SUMMARY.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
phase: 20-real-time-subscriptions
|
||||||
|
plan: 01
|
||||||
|
subsystem: api
|
||||||
|
tags: [trpc, sse, subscriptions, async-generators, streaming, event-bus]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 01.1-hexagonal-events
|
||||||
|
provides: EventBus port interface and EventEmitterBus adapter
|
||||||
|
- phase: 16-frontend-scaffold
|
||||||
|
provides: tRPC HTTP adapter and Vite proxy configuration
|
||||||
|
|
||||||
|
provides:
|
||||||
|
- SSE streaming support in tRPC HTTP adapter
|
||||||
|
- Three subscription procedures (onEvent, onAgentUpdate, onTaskUpdate)
|
||||||
|
- EventBus-to-async-generator bridge (eventBusIterable helper)
|
||||||
|
- SubscriptionEvent type in shared package for frontend consumption
|
||||||
|
|
||||||
|
affects: [20-02-frontend-subscriptions, 21-frontend-polish]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: [queue-based async generator for event bridge, tracked SSE for reconnection]
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- src/trpc/subscriptions.ts
|
||||||
|
modified:
|
||||||
|
- src/server/trpc-adapter.ts
|
||||||
|
- src/trpc/router.ts
|
||||||
|
- packages/shared/src/types.ts
|
||||||
|
- packages/shared/src/index.ts
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Queue + deferred promise pattern for bridging push (EventBus) to pull (async generator)"
|
||||||
|
- "tracked() wrapper on each event for client-side reconnection via lastEventId"
|
||||||
|
- "Fallback AbortSignal when opts.signal is undefined (AbortController().signal)"
|
||||||
|
- "Vite proxy works for SSE without changes (http-proxy streams by default)"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "eventBusIterable: Reusable async generator factory for any subset of EventBus events"
|
||||||
|
- "Subscription procedure pattern: input with optional lastEventId, yield* from eventBusIterable"
|
||||||
|
|
||||||
|
duration: 4min
|
||||||
|
completed: 2026-02-04
|
||||||
|
---
|
||||||
|
|
||||||
|
# Plan 20-01: SSE Streaming & Subscription Procedures Summary
|
||||||
|
|
||||||
|
**tRPC SSE streaming via async generators bridging EventBus domain events to three subscription endpoints**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 4 min
|
||||||
|
- **Started:** 2026-02-04
|
||||||
|
- **Completed:** 2026-02-04
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 5
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
- Fixed tRPC HTTP adapter to stream ReadableStream responses instead of buffering (required for SSE)
|
||||||
|
- Created subscriptions module with queue-based async generator bridging EventBus to tRPC subscriptions
|
||||||
|
- Added onEvent, onAgentUpdate, and onTaskUpdate subscription procedures to the router
|
||||||
|
- Exported SubscriptionEvent type from shared package for frontend consumption
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Fix HTTP adapter for SSE streaming and add subscription procedures** - `e5d8dbb` (feat)
|
||||||
|
2. **Task 2: Update shared types and verify SSE integration** - `42154d6` (feat)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
- `src/trpc/subscriptions.ts` - EventBus-to-async-generator bridge with tracked SSE events
|
||||||
|
- `src/server/trpc-adapter.ts` - Stream ReadableStream responses instead of buffering
|
||||||
|
- `src/trpc/router.ts` - Three subscription procedures (onEvent, onAgentUpdate, onTaskUpdate)
|
||||||
|
- `packages/shared/src/types.ts` - SubscriptionEvent interface for frontend
|
||||||
|
- `packages/shared/src/index.ts` - Re-export SubscriptionEvent
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
- 20-01: Queue + deferred promise pattern for bridging push (EventBus) to pull (async generator)
|
||||||
|
- 20-01: tracked() wrapper on each event for client-side reconnection via lastEventId
|
||||||
|
- 20-01: Fallback AbortSignal (new AbortController().signal) when opts.signal is undefined
|
||||||
|
- 20-01: Vite proxy works for SSE without changes (http-proxy streams chunked responses by default)
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 3 - Blocking] TrackedEnvelope type annotation**
|
||||||
|
- **Found during:** Task 1 (subscriptions module)
|
||||||
|
- **Issue:** `ReturnType<typeof tracked<string, SubscriptionEventData>>` is invalid TS — generic type inference on `typeof` of a generic function doesn't work
|
||||||
|
- **Fix:** Import `TrackedEnvelope` type directly from `@trpc/server` and use `TrackedEnvelope<SubscriptionEventData>` as return type
|
||||||
|
- **Files modified:** src/trpc/subscriptions.ts
|
||||||
|
- **Verification:** `npm run build` succeeds
|
||||||
|
- **Committed in:** e5d8dbb (Task 1 commit)
|
||||||
|
|
||||||
|
**2. [Rule 3 - Blocking] opts.signal potentially undefined**
|
||||||
|
- **Found during:** Task 1 (subscription procedures)
|
||||||
|
- **Issue:** `opts.signal` has type `AbortSignal | undefined` in tRPC subscription context, but eventBusIterable requires `AbortSignal`
|
||||||
|
- **Fix:** Fallback to `new AbortController().signal` when opts.signal is undefined
|
||||||
|
- **Files modified:** src/trpc/router.ts
|
||||||
|
- **Verification:** `npm run build` succeeds
|
||||||
|
- **Committed in:** e5d8dbb (Task 1 commit)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 2 auto-fixed (2 blocking)
|
||||||
|
**Impact on plan:** Both auto-fixes necessary for type safety. No scope creep.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
None
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
None - no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
- Backend SSE streaming ready for frontend consumption
|
||||||
|
- Plan 20-02 can add httpSubscriptionLink to the tRPC client and wire subscription hooks
|
||||||
|
- All existing queries/mutations verified working (452 tests pass)
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 20-real-time-subscriptions*
|
||||||
|
*Completed: 2026-02-04*
|
||||||
Reference in New Issue
Block a user