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
|
||||
|
||||
Phase: 19 of 21 (Agent Inbox) - COMPLETE
|
||||
Plan: 4 of 4 in current phase
|
||||
Status: Phase 19 complete
|
||||
Last activity: 2026-02-04 - Completed 19-04-PLAN.md (Inbox Page Assembly)
|
||||
Phase: 20 of 21 (Real-Time Subscriptions) - IN PROGRESS
|
||||
Plan: 1 of 2 in current phase
|
||||
Status: Completed 20-01 (SSE Streaming & Subscription Procedures)
|
||||
Last activity: 2026-02-04 - Completed 20-01-PLAN.md (SSE backend)
|
||||
|
||||
Progress: █████████░ 98%
|
||||
Progress: █████████░ 99%
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
**Velocity:**
|
||||
- Total plans completed: 70
|
||||
- Total plans completed: 71
|
||||
- Average duration: 3 min
|
||||
- Total execution time: 197 min
|
||||
- Total execution time: 201 min
|
||||
|
||||
**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: 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)
|
||||
- 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
|
||||
|
||||
@@ -247,5 +251,5 @@ None.
|
||||
## Session Continuity
|
||||
|
||||
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
|
||||
|
||||
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