Skip to content

fix: races in incoming calls#318

Merged
konsalex merged 8 commits into
mainfrom
fix-races-in-incoming-calls
May 21, 2026
Merged

fix: races in incoming calls#318
konsalex merged 8 commits into
mainfrom
fix-races-in-incoming-calls

Conversation

@konsalex
Copy link
Copy Markdown
Contributor

@konsalex konsalex commented May 21, 2026

Summary by CodeRabbit

  • New Features

    • Added automatic call timeout functionality—unanswered outgoing calls will auto-end after a fixed delay.
    • Incoming calls now include timestamp data for better tracking.
  • Bug Fixes

    • Prevent initiating new calls while an incoming call is active.
    • Automatically reject stale incoming calls older than 60 seconds.
    • Improved connection stability with inactivity detection.
  • Improvements

    • Increased heartbeat ping frequency for more responsive connection monitoring.
  • Chores

    • App version bumped to 1.0.15.

Review Change Stack

@konsalex konsalex requested a review from iparaskev as a code owner May 21, 2026 09:30
@netlify
Copy link
Copy Markdown

netlify Bot commented May 21, 2026

Deploy Preview for hoppdocs ready!

Name Link
🔨 Latest commit 79302d9
🔍 Latest deploy log https://app.netlify.com/projects/hoppdocs/deploys/6a0ed0ce4216250007c15814
😎 Deploy Preview https://deploy-preview-318--hoppdocs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

This PR enhances call handling by propagating creation timestamps from the backend through incoming-call messages, centralizing caller ID state in the Tauri store, filtering stale calls on reception, improving rejection flows, adding auto-timeout for unanswered calls, and strengthening websocket reliability with inactivity deadlines and faster heartbeats. Docker task configuration and app version are also updated.

Changes

Call Handling Improvements

Layer / File(s) Summary
Incoming call message contract: Backend to frontend
backend/internal/messages/messages.go, tauri/src/payloads.ts
Backend IncomingCallPayload adds optional InitiatedAt field; call initiation passes time.Now().Unix() timestamp; frontend schema updated to accept optional initiated_at in payload.
Centralized store state for incoming call tracking
tauri/src/store/store.ts
New incomingCallCallerId state field and setIncomingCallCallerId action added to the zustand store and initialized to null.
App migration from local state to store
tauri/src/windows/main-window/app.tsx
App removes useState import and updates useStore destructuring to include setIncomingCallCallerId for centralized state management.
Incoming call reception with age validation
tauri/src/windows/main-window/app.tsx
App imports date-fns utilities, filters stale calls older than 60 seconds using initiated_at, sets/clears incomingCallCallerId in store on reception and call end.
Call rejection and banner state management
tauri/src/components/ui/call-banner.tsx, tauri/src/windows/main-window/app.tsx
App handleReject and CallBanner rejection/answer handlers pull setIncomingCallCallerId from store and clear it; dependency arrays updated accordingly.
Participant row: Incoming call blocking and auto-timeout
tauri/src/components/ui/participant-row-wo-livekit.tsx
ParticipantRow reads hasIncomingCall from store to prevent outgoing calls; adds timeoutId that auto-rejects unanswered calls after fixed delay with call_end and toast notification.
Websocket reliability: Read deadlines and heartbeat
backend/internal/handlers/websocketHandlers.go, tauri/src/services/socket.ts
Websocket handler sets and resets read deadlines to enforce inactivity timeouts and logs errors with user.ID; heartbeat frequency increased from 30s to 15s.

Deployment and Versioning

Layer / File(s) Summary
Docker Compose task updates
backend/Taskfile.yml
compose-up task now uses docker-files/docker-compose.yml; new fullstack-up task runs docker-files/fullstack-compose.yml with ENV_STACK: local.
Application version bump
tauri/src-tauri/tauri.conf.json
Tauri app version incremented from 1.0.14 to 1.0.15.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A timestamp hops through the wire so fast,
State flows through the store, no more to cast.
Old calls fade away, fresh ones stand tall,
Websockets beat stronger with hearts that call—
Rabbits now answer with grace and with might! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: races in incoming calls' directly corresponds to the main objective of this PR, which addresses race conditions in the incoming call handling logic across multiple components (socket heartbeat timing, call timeout mechanisms, stale call filtering, and state management).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-races-in-incoming-calls

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@backend/Taskfile.yml`:
- Around line 54-61: The Taskfile entry for the task fullstack-up has a
misleading desc "Build and run" while the build-image dependency is commented
out; either uncomment the commented task reference "- task: build-image" under
cmds so fullstack-up actually performs the build (restore the dependency in the
cmds list) or change the desc to remove "Build and" so it accurately reads e.g.
"Run the fullstack setup with Redis and backend"; update the single symbol
fullstack-up and the commented line "- task: build-image" accordingly.

In `@tauri/src/services/socket.ts`:
- Line 108: The comment next to the ping interval (the setInterval that sends a
ping every 15_000 ms) is stale: backend uses a 65s read timeout, so keep the 15s
heartbeat but update the comment to reflect the backend wsReadTimeout (≈65s)
instead of "2 heartbeats (30 seconds)"; e.g. note that connections will be
considered dead after the backend's ~65s read timeout (~4 heartbeats), or simply
reference the backend read-deadline, and leave the setInterval/ping logic
(sendPing / setInterval) unchanged.
🪄 Autofix (Beta)

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

Run ID: 30e3f753-dcf1-424a-b98a-638e4554bbb7

📥 Commits

Reviewing files that changed from the base of the PR and between 47074e1 and 79302d9.

📒 Files selected for processing (10)
  • backend/Taskfile.yml
  • backend/internal/handlers/websocketHandlers.go
  • backend/internal/messages/messages.go
  • tauri/src-tauri/tauri.conf.json
  • tauri/src/components/ui/call-banner.tsx
  • tauri/src/components/ui/participant-row-wo-livekit.tsx
  • tauri/src/payloads.ts
  • tauri/src/services/socket.ts
  • tauri/src/store/store.ts
  • tauri/src/windows/main-window/app.tsx

Comment thread backend/Taskfile.yml
Comment on lines +54 to +61
fullstack-up:
desc: Build and run the fullstack setup with Redis and backend
cmds:
# - task: build-image
- docker compose -f docker-files/fullstack-compose.yml up -d
env:
ENV_STACK: local

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Description doesn't match implementation.

The task description claims "Build and run" but the build-image dependency on line 57 is commented out, so no build step actually executes.

Either uncomment the build task or update the description to remove "Build and".

📝 Proposed fix options

Option 1: Update description to match current behavior

-    desc: Build and run the fullstack setup with Redis and backend
+    desc: Run the fullstack setup with Redis and backend

Option 2: Uncomment the build step to match description

     cmds:
-      # - task: build-image
+      - task: build-docker
       - docker compose -f docker-files/fullstack-compose.yml up -d
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fullstack-up:
desc: Build and run the fullstack setup with Redis and backend
cmds:
# - task: build-image
- docker compose -f docker-files/fullstack-compose.yml up -d
env:
ENV_STACK: local
fullstack-up:
desc: Run the fullstack setup with Redis and backend
cmds:
# - task: build-image
- docker compose -f docker-files/fullstack-compose.yml up -d
env:
ENV_STACK: local
🤖 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 `@backend/Taskfile.yml` around lines 54 - 61, The Taskfile entry for the task
fullstack-up has a misleading desc "Build and run" while the build-image
dependency is commented out; either uncomment the commented task reference "-
task: build-image" under cmds so fullstack-up actually performs the build
(restore the dependency in the cmds list) or change the desc to remove "Build
and" so it accurately reads e.g. "Run the fullstack setup with Redis and
backend"; update the single symbol fullstack-up and the commented line "- task:
build-image" accordingly.

});
}
}, 30_000); // Send ping every 30 seconds
}, 15_000); // Send ping every 15 seconds
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify backend websocket read deadline timeout is compatible with 15s heartbeat.
# Expected: Backend timeout should be at least 30-45 seconds to accommodate 15s heartbeat.

# Search for read deadline configuration in websocket handler
rg -n -C5 'SetReadDeadline|ReadDeadline|pongWait|readWait' backend/internal/handlers/websocketHandlers.go

# Also check for any timeout constants or configurations
rg -n 'time\.(Second|Minute|Duration).*[0-9]+' backend/internal/handlers/websocketHandlers.go

Repository: gethopp/hopp

Length of output: 932


Backend timeout already accommodates the 15s heartbeat

  • Backend sets wsReadTimeout = 65 * time.Second via ws.SetReadDeadline(...) and resets it on each incoming Ping, so 15s heartbeats are well within the read-deadline window.
  • Minor: the comment “Kill the connections after 2 heartbeats (30 seconds for old apps)” no longer matches the 65s timeout; update it.
🤖 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 `@tauri/src/services/socket.ts` at line 108, The comment next to the ping
interval (the setInterval that sends a ping every 15_000 ms) is stale: backend
uses a 65s read timeout, so keep the 15s heartbeat but update the comment to
reflect the backend wsReadTimeout (≈65s) instead of "2 heartbeats (30 seconds)";
e.g. note that connections will be considered dead after the backend's ~65s read
timeout (~4 heartbeats), or simply reference the backend read-deadline, and
leave the setInterval/ping logic (sendPing / setInterval) unchanged.

@konsalex konsalex merged commit a30da51 into main May 21, 2026
21 checks passed
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.

1 participant