fix: smooth blind spot monitor - #685
Conversation
📝 WalkthroughWalkthroughChangesThe PR adds a versioned Blind-spot snapshot flow
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Telemetry
participant BlindSpotProcessor
participant SnapshotChannel
participant BlindSpotMonitor
Telemetry->>BlindSpotProcessor: telemetry frame
BlindSpotProcessor->>SnapshotChannel: publish blind-spot.snapshot at 25 Hz
SnapshotChannel->>BlindSpotMonitor: provide selected snapshot
BlindSpotMonitor->>BlindSpotMonitor: calculate blind-spot percentages
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f5b39751c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| export class BlindSpotProcessor implements TelemetryProcessor<BlindSpotSnapshot> { | ||
| readonly channel = 'blind-spot.snapshot'; | ||
| readonly tickRateHz = 60; |
There was a problem hiding this comment.
Keep the positional blind-spot processor at 25 Hz
When the blind-spot widget is enabled, every full-precision CarIdxLapDistPct change increments the snapshot version, so this setting serializes and delivers the complete position array at 60 Hz. This is a positional channel rather than an input-style channel, and the repository's hard architecture rules cap positional processors at 25 Hz; use the existing 40 ms indicator transition to smooth those samples instead of doubling the processor and IPC workload.
AGENTS.md reference: AGENTS.md:L12-L18
Useful? React with 👍 / 👎.
| 1, | ||
| (now - startedAt) / POSITION_UPDATE_INTERVAL_MS | ||
| ); | ||
| const nextDrivers = driversTrackData.map((entry) => { |
There was a problem hiding this comment.
Avoid allocating driver snapshots inside each animation frame
Whenever map positions update, each animation frame maps the entire field into a new array and clones every existing driver entry, then stores that array in React state; both map variants consequently rerender and recalculate/redraw their canvases multiple times per 25 Hz telemetry tick. This violates the repository's hard prohibition on unbenchmarked per-frame allocations in hot paths and scales poorly with driver count or multiple map widgets; keep interpolation state in reusable refs/buffers and drive only the canvas draw instead.
AGENTS.md reference: AGENTS.md:L12-L18
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2734d93ba1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }); | ||
|
|
||
| displayedDriversRef.current = nextDrivers; | ||
| setSmoothedDrivers(nextDrivers); |
There was a problem hiding this comment.
Memoize the qualifying fallback before animation
When QualifyResultsInfo.Results is empty but QualifyPositions exists (the heat-race fallback), its inline .map() creates a new qualifyingResults array on every render. Each animation frame calls setSmoothedDrivers here, causing another render, which recreates driverIdentities and driversTrackData, restarts this effect, and schedules another frame even after the position sample has settled. Consequently both track-map canvases redraw indefinitely at display refresh rate; memoize the fallback so driversTrackData changes only when its actual inputs change.
AGENTS.md reference: AGENTS.md:L153-L157
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad9f666332
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }: ProcessorRegistryOptions): readonly AnyProcessorDefinition[] => [ | ||
| defineProcessor({ | ||
| channel: 'blind-spot.snapshot', | ||
| metricsPrefix: 'blindSpot', |
There was a problem hiding this comment.
Add blind-spot to processor execution metrics
When performance metrics are enabled for this 60 Hz processor, ProcessorHost records the blindSpotProcessing section, but perfMetrics.ts does not map that label in PROCESSOR_CHANNELS. As a result, generated channelMetrics.processorExecutions reports no executions for blind-spot.snapshot, so the performance analyzer shows a zero processor rate and cannot accurately evaluate this new hot path; add the corresponding section-to-channel mapping.
AGENTS.md reference: AGENTS.md:L12-L18
Useful? React with 👍 / 👎.
| export const useBlindSpotMonitor = (): BlindSpotMonitorState => { | ||
| const [carLeftRight, lapDistPcts, isOnTrack] = | ||
| useTrackStateSelector(selectBlindSpotTelemetry, { | ||
| const [carLeftRight, lapDistPcts, isOnTrack] = useBlindSpotSelector( |
There was a problem hiding this comment.
Stop retaining the track-state subscription
When Blind Spot Monitor is the only positional widget, adding this selector activates the new blind-spot processor while BlindSpotMonitor.tsx still calls useTrackStateSelector(trackStateSelectors.isOnTrack) for its visibility check. Runtime channel metadata does not suppress hook subscriptions, so both the 60 Hz blind-spot processor and the 25 Hz track-state processor remain active and isOnTrack is delivered twice, negating the intended replacement of the general positional channel; use the dedicated snapshot's on-track value for that visibility decision as well.
Useful? React with 👍 / 👎.
|
@codex rereview |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aad9047a37
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| channels: ['track-state.snapshot'], | ||
| channels: ['blind-spot.snapshot'], | ||
| ratePreset: 'driverFocused', | ||
| channelRates: { 'blind-spot.snapshot': 60 }, |
There was a problem hiding this comment.
Align the requested rate with the 25 Hz source
In the live iRacing path, publishIRacingSDKEvents sleeps for 1000 / 25 after every telemetry frame (src/app/bridge/iracingSdk/iracingSdkBridge.ts:295-297), so BlindSpotProcessor.onFrame cannot receive 60 frames per second and this request cannot provide the claimed 60 Hz overlap or movement updates. Fresh evidence beyond the earlier processor-rate comment is this fixed upstream 40 ms throttle: advertising 60 Hz here creates a false runtime/performance contract without increasing data cadence; keep the positional channel at 25 Hz and smooth those samples in presentation instead.
AGENTS.md reference: AGENTS.md:L12-L18
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/frontend/components/BlindSpotMonitor/widgetRuntimeDefinition.ts`:
- Line 8: Update the blind-spot.snapshot channel definition’s maxRateHz in the
channel configuration to 60 before changing the related processor, runtime
definition, or test values; then align those consumers with the updated maximum
while preserving the existing channel-rate behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3202bca8-4195-434c-ad16-7d6123e9cfe5
📒 Files selected for processing (9)
src/app/perfMetrics.tssrc/app/processors/BlindSpotProcessor.spec.tssrc/app/processors/BlindSpotProcessor.tssrc/frontend/components/BlindSpotMonitor/BlindSpotMonitor.tsxsrc/frontend/components/BlindSpotMonitor/hooks/useBlindSpotMonitor.spec.tsxsrc/frontend/components/BlindSpotMonitor/hooks/useBlindSpotMonitor.tsxsrc/frontend/components/BlindSpotMonitor/widgetRuntimeDefinition.tssrc/frontend/widgetRuntime.spec.tsxsrc/types/channels/channel.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- src/types/channels/channel.ts
- src/app/processors/BlindSpotProcessor.ts
- src/frontend/components/BlindSpotMonitor/hooks/useBlindSpotMonitor.spec.tsx
- src/frontend/components/BlindSpotMonitor/hooks/useBlindSpotMonitor.tsx
| channels: ['track-state.snapshot'], | ||
| channels: ['blind-spot.snapshot'], | ||
| ratePreset: 'driverFocused', | ||
| channelRates: { 'blind-spot.snapshot': 25 }, |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 2 'blind-spot\.snapshot|tickRateHz|channelRates' srcRepository: tariknz/irdashies
Length of output: 18133
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- BlindSpotProcessor ---\n'
sed -n '1,80p' src/app/processors/BlindSpotProcessor.ts
printf '\n--- BlindSpotMonitor runtime definition ---\n'
sed -n '1,40p' src/frontend/components/BlindSpotMonitor/widgetRuntimeDefinition.ts
printf '\n--- Widget runtime handling ---\n'
sed -n '90,120p' src/frontend/widgetRuntime.tsx
sed -n '155,175p' src/frontend/widgetRuntime.tsx
printf '\n--- Channel default rate ---\n'
sed -n '295,310p' src/types/channels/channel.tsRepository: tariknz/irdashies
Length of output: 246
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- BlindSpotProcessor ---'
sed -n '1,80p' src/app/processors/BlindSpotProcessor.ts
printf '%s\n' ''
printf '%s\n' '--- BlindSpotMonitor runtime definition ---'
sed -n '1,40p' src/frontend/components/BlindSpotMonitor/widgetRuntimeDefinition.ts
printf '%s\n' ''
printf '%s\n' '--- Widget runtime handling ---'
sed -n '90,120p' src/frontend/widgetRuntime.tsx
sed -n '155,175p' src/frontend/widgetRuntime.tsx
printf '%s\n' ''
printf '%s\n' '--- Channel default rate ---'
sed -n '295,310p' src/types/channels/channel.tsRepository: tariknz/irdashies
Length of output: 3958
Align the blind-spot rate with the max channel rate.
src/types/channels/channel.ts sets maxRateHz for blind-spot.snapshot to 25 Hz. If 60 Hz is required, increase maxRateHz in the channel definition before changing the processor, runtime definition, and test.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/frontend/components/BlindSpotMonitor/widgetRuntimeDefinition.ts` at line
8, Update the blind-spot.snapshot channel definition’s maxRateHz in the channel
configuration to 60 before changing the related processor, runtime definition,
or test values; then align those consumers with the updated maximum while
preserving the existing channel-rate behavior.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3ffdce295
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const processor = new BlindSpotProcessor(); | ||
| processor.onFrame(frame(2, [0.123456, 0.123789])); |
There was a problem hiding this comment.
Drive the processor test through the required lifecycle
The new processor coverage constructs BlindSpotProcessor and calls onFrame directly with a hand-built object; none of these tests calls init(session) or drives a recorded frame sequence. This leaves activation/session initialization and compatibility with recorded telemetry shapes untested, contrary to the mandatory fixture-backed init → onFrame* → snapshot sequence in docs/ARCHITECTURE_RULES.md R14.1; add coverage that exercises the complete lifecycle.
AGENTS.md reference: AGENTS.md:L12-L18
Useful? React with 👍 / 👎.
Description
Fixes two positional-widget regressions observed after the Phase 4 performance profile:
CarLeftRight, full-precisionCarIdxLapDistPct, andIsOnTrackfrom the same telemetry frame. This restores prompt overlap detection and smooth movement without raising the general track-state channel rate.This follows the Phase 4 channel-snapshot topology while restoring the presentation smoothness lost during the channel migration.
Tested live in iRacing by reproducing the original flashing blind-spot monitor and confirming the dedicated high-frequency path substantially improves its behavior.
Screenshots
Before
Blind-spot indicators flashed/repeatedly remounted while a car overlapped, and track-map markers moved in visible 25 Hz steps.
After
Blind-spot overlap and distance telemetry update coherently at 60 Hz, and track-map markers interpolate smoothly between positional snapshots.
Type of Change
Checklist
npm testnpm run lintand fixed any issuesSummary by CodeRabbit
New Features
Bug Fixes
Tests