¶ IPSC3 Transport and Runtime Refactor Roadmap
This roadmap is intended to stabilize IPSC3 before adding more protocol surface such as OpenBridge or YSF/Fusion access paths.
- reduce regressions from small routing fixes
- separate transport, runtime state, and dashboard projection concerns
- make scan/sandbag behavior explicit rather than inferred
- improve multi-core behavior and packet stability
- create a foundation for later buffering, load testing, and new protocols
¶ Phase 1: Baseline and Instrumentation
Add enough instrumentation to measure instability before changing architecture.
Track:
- Motorola ingress packet rate
- MMDVM trunk ingress packet rate
- hotspot ingress packet rate
- active streams by protocol
- bridge target misses
- stale target rejections
- queue depth once queues exist
- scan/sandbag retarget events
- mirrored-activity versus source-activity decisions
Primary goal:
Likely files:
crates/ipsc-server/src/main.rs
crates/ipsc-store/src/lib.rs
crates/ipsc-store/src/mysql.rs
Introduce one in-memory stream/session model that becomes the source of truth for live routing.
Per stream/session, track:
- source protocol
- source peer ID
- source radio ID
- original destination talkgroup/timeslot
- translated destination talkgroup/timeslot
- stream start and last activity
- current bridge targets
- simplex/duplex state
- scan/sandbag state
Primary goal:
- stop inferring live behavior from multiple database tables
Refactor listeners so they:
- receive packets
- parse packets
- normalize them into internal events
- enqueue them
They should stop mutating deep routing state inline.
Primary goal:
- make listeners simple and deterministic
Likely code areas:
- Motorola listener in
crates/ipsc-server/src/main.rs
run_mmdvm_peer_loop() in crates/ipsc-server/src/main.rs
- hotspot listener and
handle_hotspot_packet() in crates/ipsc-server/src/main.rs
¶ Phase 4: Add Bounded Queues and Workers
Introduce bounded queues between:
- ingress normalization
- routing
- Motorola egress
- MMDVM trunk egress
- hotspot egress
- prompt/signal playback
Primary goal:
- one bursty path should not destabilize unrelated paths
This is the first meaningful multi-threading improvement.
Move runtime tables into the role of projections instead of routing inputs wherever possible.
Especially:
active_calls
active_talkgroups
peer_runtime_state
radio_last_seen
Primary goal:
- stop state feedback loops between transport behavior and UI/runtime projection
¶ Phase 6: Rebuild Scan/Sandbag on Canonical State
Model scan/sandbag explicitly, with:
- who armed scan
- what talkgroup/timeslot is currently followed
- whether the current source is trunk, repeater, or hotspot
- source peer ID
- pre-scan camp
- return-to-camp target
Primary goal:
- remove guesswork from
777
- make talk-back and return behavior explicit
All egress targets should be:
- connected
- fresh
- protocol-correct
- explicitly selected
Do not route from stale cached state alone.
Primary goal:
- eliminate ghost targets and stale target leakage
¶ Phase 8: Isolate Prompts and Signal Requests
Prompts, parrot, radio-check experiments, SMS experiments, and similar control traffic should not share fragile live-call routing state.
Primary goal:
- feature work should not destabilize core voice routing
¶ Phase 9: Add Micro-Buffering and Reorder Logic
Add small per-stream buffering only where justified.
Start with MMDVM voice paths:
- use
DMRD stream ID plus the 8-bit packet sequence for per-stream ordering
- handle sequence wraparound with a deliberately small reorder window
- duplicate suppression
- late packet counters
- short reorder windows
- missing-sequence counters
- jitter / reorder telemetry per peer and stream
Primary goal:
- improve stability under bursty or jittery transport conditions
Route first, publish later.
Database writes for events and dashboard state should become downstream effects rather than inline dependencies of live transport.
Primary goal:
- MySQL timing should not influence live audio behavior
Create an MMDVM-oriented load tool that can simulate:
- many hotspots
- simultaneous calls
- optional jitter
- packet loss
- packet reordering
- duplicate packets
Primary goal:
- catch regressions before on-air testing
Only after the earlier phases are stable:
- add OpenBridge
- later add YSF/Fusion as a separate access protocol
Primary goal:
- new protocol work should inherit a stable core rather than multiply instability
- instrumentation
- canonical stream model
- ingress/routing split
- bounded queues and workers
- state publication split
- sandbag/scan rewrite
- target resolution hardening
- prompt/signal isolation
- micro-buffering
- DB decoupling
- stress harness
- OpenBridge / YSF
- do phases 1 to 5 on a dedicated refactor branch
- keep milestones individually testable
- use feature flags where practical
- do not mix protocol expansion with core runtime refactor work
By the end of this roadmap, IPSC3 should have:
- a canonical runtime model for live streams
- cleaner separation between transport and UI/runtime projection
- more deterministic scan/sandbag behavior
- better packet stability under load
- safer ground for future features and protocol additions