feat(stability): manual Resync action for Passive Mode sources (#3122)#3126
Conversation
…3122) Follow-up to #3125. Adds an operator-initiated full config refresh for Meshtastic TCP sources, useful for Passive Mode where the automatic reconnect path skips want_config_id while the cached config is fresh. * MeshtasticManager.requestManualResync(): forces a single want_config_id regardless of staleness; single-flight latch; 30s cooldown; 120s watchdog so a stuck "in progress" never disables the button forever. * Recovery latch: if the forced sync triggers a node-side socket close, the next connect re-uses the cached config and skips another full sync — prevents the forced-sync-becomes-loop failure mode the reporter called out in the issue. * HTTP routes: POST /api/sources/:id/resync to start, GET to read state. Returns {inFlight, cooldownExpiresAt, reason?} so the UI can render. * UI: new "Resync" kebab item on connected meshtastic_tcp source cards. Refetches source status after the request so the dot updates. Tests: 11 new tests covering happy path, single-flight rejection, cooldown rejection, post-cooldown allow, not-connected rejection, send-failed cleanup, watchdog timeout, and state-query getter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job PR Review for Manual Resync FeatureCompleted comprehensive review of the manual resync implementation for Passive Mode sources. Overall, this is a well-designed and thoroughly implemented feature with excellent safety guards. Todo List
✅ StrengthsRobust Safety Architecture
Excellent Test CoverageThe test suite in
Clean API Design
UI Integration
🔍 Areas for ImprovementMinor Code Quality Issues
Security Considerations✅ Positive: Permission checks are properly implemented with ✅ Positive: The feature is scoped to Performance Considerations✅ Positive: The implementation is efficient with minimal overhead when not in use. ✅ Positive: Single-flight protection prevents resource exhaustion. Observation: The watchdog timer could theoretically accumulate if many manual resyncs are initiated across different sources, but this is unlikely to be an issue in practice. Potential Edge Cases
🏆 Overall AssessmentThis is a high-quality implementation that demonstrates:
Code Quality: A-
Security: A
Test Coverage: A+
Performance: A
✅ RecommendationAPPROVE - This PR successfully addresses the requirements from issue #3122 with a well-designed, safe, and thoroughly tested implementation. The minor suggestions above are optional improvements rather than blocking issues. The implementation strikes an excellent balance between functionality and safety, which is crucial for a feature that directly interacts with hardware devices. |
#3128) Follow-up to #3125 / #3126. Closes the third item from the reporter's feedback on #3122. On large/fragile TCP nodes the *first* config-sync session frequently closes mid-stream but the second attempt works cleanly. Under normal exponential backoff that recovery would wait 8–16s before retrying; this short startup-grace window cuts that gap. * TcpTransport.setStartupGraceReconnect(graceMs, fastDelayMs): for the next graceMs after the call, scheduleReconnect uses fastDelayMs instead of the exponential backoff. After the window expires, normal backoff resumes automatically. Disabled by default (graceMs=0). * MeshtasticManager opt-in: passive-mode sources get a 2-minute grace window with a 3-second reconnect delay during initial startup. Other sources keep the legacy backoff. Tests: 6 new tcpTransport tests cover default-disabled, in-window fast delay regardless of attempt count, post-window exponential fallback, explicit disable, sanity, and that the reconnect fires after the configured delay. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#3122) (#3129) Follow-up to #3125 / #3126 / #3128. Closes item 2 of the reporter's feedback on #3122 (advanced per-source setting for the staleness window). * SourceConfig gains optional passiveResyncStaleMs (ms). Falls back to the 4h class default when absent. * MeshtasticManager.effectivePassiveResyncStaleMs() resolves the active threshold, clamping out-of-range overrides ([1 min, 7 days]) so a 0 or astronomical value can't disable the safeguard. * Plumbed through all 5 MeshtasticManager construction sites in sourceRoutes; a change in the value triggers a transport restart alongside the existing passiveMode toggle. * UI: numeric "Resync staleness window (hours)" input appears under the Passive Mode toggle when enabled. Blank = use 4h default. Tests: 9 new tests cover default, constructor override, configureSource override + clear, below-floor / above-ceiling rejection, exact boundary acceptance, and NaN rejection. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follow-up to #3125. Implements the Manual Resync action the reporter called out as item 1 in their feedback on the issue.
Why
With Passive Mode enabled, automatic reconnects skip `want_config_id` while the cached config is "fresh" (< 4 h). That's the right default for stability, but it leaves the operator without a way to force a refresh when they know the device config changed (remote channel rekey, hwModel swap, role change). This adds a per-source action that forces exactly one full sync, with guards so the forced sync can't accidentally become a new failure loop.
What
What's not in this PR
Test plan
Fixes the manual-Resync follow-up from #3122.
🤖 Generated with Claude Code