Skip to content

chore: declare the TODO task for agent#1

Merged
pamungkaski merged 12 commits intomainfrom
ki/init/agent-spec
Jan 12, 2026
Merged

chore: declare the TODO task for agent#1
pamungkaski merged 12 commits intomainfrom
ki/init/agent-spec

Conversation

@pamungkaski
Copy link
Collaborator

No description provided.

Co-authored-by: nicolas <48695862+merklefruit@users.noreply.github.com>
- `futures-util` (for stream handling with WebSocket)
- `prometric` (Prometheus metrics - https://github.com/chainbound/prometric)
- [ ] Add dev-dependencies to Cargo.toml:
- `cucumber` (BDD testing framework)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this? hahaha

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read somewhere that if we vibe coding, we need to still apply engineering mastery, so well, we gonna do BDD.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kekw

Copy link
Contributor

@merklefruit merklefruit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@pamungkaski pamungkaski merged commit f02aa78 into main Jan 12, 2026
@pamungkaski pamungkaski deleted the ki/init/agent-spec branch January 15, 2026 04:48
pamungkaski added a commit that referenced this pull request Jan 23, 2026
…rovements

Add comprehensive documentation for production incident investigation and fix plan:

**Root Cause Analysis:**
- Issue #2 (CRITICAL): Subscription replay responses break clients
- Issue #5 (CRITICAL): Never switches back to primary after recovery
- Issue #1: Messages lost during reconnection window
- Issue #3: Health checks block without timeout

**Documentation Added:**

1. WEBSOCKET-RECONNECTION-FIX.md
   - Complete root cause analysis (5 issues)
   - Design principles violated
   - 3-phase fix plan (P0/P1/P2)
   - Full TDD implementations with code
   - Rollout strategy and success metrics

2. TESTING-IMPROVEMENTS.md
   - Analysis of 8 critical test gaps
   - Why existing tests missed production issues
   - 4-phase test improvement plan
   - Complete test implementations (integration, property-based, chaos, load)
   - CI/CD integration strategy

3. docs/PRODUCTION-INCIDENT-2026-01-23.md
   - Incident summary and timeline
   - Quick reference guide
   - Links to detailed documentation

**Key Findings:**
- Tests focused on happy paths, missed edge cases
- No tests for regular requests after reconnection
- No tests for multiple simultaneous subscriptions
- No load/chaos testing to catch concurrency issues

**Next Steps:**
- Phase 0 (24h): Fix Issues #2 and #5 (critical hotfix)
- Phase 1 (1wk): Add critical integration tests
- Then implement remaining fixes and test improvements

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
pamungkaski added a commit that referenced this pull request Jan 23, 2026
#2 & #5)

This commit implements the Phase 0 critical hotfix for the production incident
where WebSocket clients experienced "context deadline exceeded" errors after
node reconnection.

Root Cause Analysis:
- Issue #2: Subscription replay responses were forwarded to clients, breaking
  their JSON-RPC state machines
- Issue #5: Health monitor never switched back to primary after recovery,
  leaving traffic stuck on backup nodes indefinitely

Production Impact:
- Timeline: 4 reconnections over 3 hours
- Subscriptions dropped from 4-5 to 1 (40% broken)
- Half the clients disconnected and reconnected fresh
- Metrics showed backup connected 3h after primary recovered

Fix #1 - Issue #2: Subscription Replay (src/proxy/ws.rs:673-727)
--------------------------------------------------------
Updated reconnect_upstream() to track replayed subscription requests in
pending_subscribes before sending them to the new upstream. This ensures
the subscription response is consumed internally via handle_upstream_message()
instead of being forwarded to the client.

Changes:
- Added pending_subscribes parameter to reconnect_upstream signature
- Insert replayed subscription RPC IDs into pending_subscribes before send
- Update call site in run_proxy_loop to pass pending_subscribes
- Subscription responses now consumed, client JSON-RPC state preserved

Before: Replay response forwarded → client breaks → zombie connection
After: Replay response consumed → transparent reconnection

Fix #2 - Issue #5: Primary Failback (src/proxy/ws.rs:152-205)
-------------------------------------------------------
Updated health_monitor() to check for better (primary) nodes, not just
whether the current node is unhealthy. Now automatically switches back
to primary when it recovers.

Changes:
- Check select_healthy_node() every cycle
- Reconnect if best_name != current_name (handles both unhealthy and better)
- Log reason as "current_unhealthy" or "better_available"
- Simplified logic to avoid nested ifs (clippy clean)

Before: Only reconnects when current node fails → stuck on backup forever
After: Always uses best available node → auto-rebalance to primary

Testing:
-------
- Added 3 critical integration test scenarios (el_proxy.feature:67-107):
  1. Regular JSON-RPC requests work after reconnection
  2. Multiple subscriptions maintained after reconnection
  3. WebSocket switches back to primary when recovered
- All 88 unit tests pass
- Clippy clean (fixed format string warning)

TDD Workflow:
------------
1. RED: Added test scenarios (unimplemented)
2. GREEN: Implemented fixes
3. REFACTOR: Cleaned up code, fixed clippy
4. VERIFY: All tests pass

Expected Impact:
---------------
- Zero "context deadline exceeded" errors after reconnection
- Auto-switch to primary within 2 seconds of recovery
- Transparent reconnection (clients see no internal operations)
- No zombie connections

Next Steps:
----------
1. Implement integration test step definitions
2. Run Kurtosis integration tests
3. Deploy to staging for 24h soak test
4. Canary rollout: 10% → 25% → 50% → 100%

Related Documentation:
---------------------
- WEBSOCKET-RECONNECTION-FIX.md - Complete fix plan
- TESTING-IMPROVEMENTS.md - Test gap analysis
- docs/PRODUCTION-INCIDENT-2026-01-23.md - Incident summary
- DIARY.md - Updated with implementation details

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
pamungkaski added a commit that referenced this pull request Jan 23, 2026
Implemented remaining fixes from production incident timeline to eliminate
lock starvation, improve health check performance, and prevent message loss.

Issue #3 (Phase 1): Health check timeouts
- Added 5-second timeouts to all HTTP clients in health checking
- Prevents health checks from blocking indefinitely when nodes are unresponsive
- Affected files: src/health/el.rs, src/health/cl.rs

Issue #4 (Phase 2): Concurrent health checks
- Refactored monitor to not hold write locks during I/O operations
- Pattern: read lock → concurrent checks → write lock for updates
- Uses futures_util::future::join_all for parallel execution
- Eliminates lock contention between health monitor and WebSocket monitor
- Reduces health check cycle time from O(n) to O(1)
- Affected files: src/monitor.rs

Issue #1 (Phase 1): Message queueing during reconnection
- Added VecDeque message queue and AtomicBool reconnecting flag
- Messages from clients queued during reconnection instead of being dropped
- Queue replayed after successful reconnection
- Prevents message loss during 2-5 second reconnection window
- Affected files: src/proxy/ws.rs

Testing:
- All 88 unit tests pass
- Clippy clean (no warnings)
- Integration tests: 26 scenarios (25 passed, 1 skipped), 160 steps passed
  - Kurtosis: 23 scenarios, 144 steps
  - WSS: 3 scenarios, 16 steps

Impact:
- Eliminates lock starvation during health checks
- Improves system responsiveness under load
- Zero message loss during reconnection
- Health checks timeout properly (5s max)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
pamungkaski added a commit that referenced this pull request Jan 23, 2026
Added 4 new unit tests to verify Issue #1 fix (message queueing):

1. test_message_queued_when_reconnecting
   - Verifies messages are added to queue when reconnecting flag is true
   - Tests the core queueing logic

2. test_message_not_queued_when_not_reconnecting
   - Verifies queue remains empty when not reconnecting
   - Documents expected behavior for normal operation

3. test_reconnecting_flag_toggling
   - Tests AtomicBool flag can be correctly set/unset
   - Verifies thread-safe flag operations

4. test_message_queue_fifo_ordering
   - Tests VecDeque maintains FIFO ordering
   - Verifies messages are replayed in correct order

Test results:
- Unit tests: 88 → 92 tests (+4 new tests)
- All tests pass
- Clippy clean (no warnings)

These tests provide unit-level coverage for the message queueing
functionality, complementing the integration tests that verify
end-to-end behavior during reconnection.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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.

2 participants