Skip to content

[management] check stream start time for connecting peer#5267

Merged
crn4 merged 1 commit intomainfrom
fix/stream-start-time
Feb 6, 2026
Merged

[management] check stream start time for connecting peer#5267
crn4 merged 1 commit intomainfrom
fix/stream-start-time

Conversation

@crn4
Copy link
Copy Markdown
Contributor

@crn4 crn4 commented Feb 5, 2026

Describe your changes

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

bug fix

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Summary by CodeRabbit

  • Refactor
    • Enhanced peer connection tracking with improved timestamp synchronization across the system.
    • Optimized redundant peer state updates to reduce unnecessary processing.

Copilot AI review requested due to automatic review settings February 5, 2026 16:22
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 5, 2026

📝 Walkthrough

Walkthrough

This PR threads a synchronization timestamp parameter (syncTime) through peer connection management in the account manager, gRPC server, and peer handler. The timestamp replaces local variable initialization and is propagated from the gRPC server entry point through to individual peer status updates and connection tracking.

Changes

Cohort / File(s) Summary
Interface Definitions
management/server/account/manager.go
Updated interface signatures for MarkPeerConnected and SyncAndMarkPeer to include new syncTime time.Time parameter.
Core Implementation
management/server/account.go, management/server/peer.go
Implemented syncTime parameter handling in SyncAndMarkPeer and MarkPeerConnected methods; added skip logic in peer.go when peer is newer than syncTime; propagated timestamp to updatePeerStatusAndLocation for LastSeen updates.
gRPC Server Integration
management/internals/shared/grpc/server.go
Replaced local streamStartTime variable with reqStart parameter; updated call to SyncAndMarkPeer to pass reqStart as synchronization timestamp.
Test and Mock Updates
management/server/account_test.go, management/server/mock_server/account_mock.go
Updated test cases and mock implementations to provide syncTime argument in all calls to MarkPeerConnected and SyncAndMarkPeer.

Sequence Diagram(s)

sequenceDiagram
    participant GRPCServer as gRPC Server
    participant AccountMgr as Account Manager
    participant Peer as Peer Handler
    participant Store as Store/Transaction

    GRPCServer->>GRPCServer: Capture reqStart timestamp
    GRPCServer->>AccountMgr: SyncAndMarkPeer(ctx, ..., reqStart)
    
    AccountMgr->>Peer: MarkPeerConnected(ctx, ..., reqStart)
    
    Peer->>Store: Begin transaction
    Store-->>Peer: Transaction handle
    
    Peer->>Peer: Check if peer.lastSeen >= syncTime
    
    alt Peer is newer than syncTime
        Peer->>Peer: Skip update, log trace
        Peer-->>AccountMgr: Return early
    else Peer needs update
        Peer->>Peer: updatePeerStatusAndLocation(...)
        Peer->>Store: Update peer with LastSeen=syncTime
        Store-->>Peer: Updated
        Peer->>Store: Commit transaction
        Store-->>Peer: Success
        Peer-->>AccountMgr: Return updated peer
    end
    
    AccountMgr-->>GRPCServer: Return peer, netMap, etc.
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • pascal-fischer
  • pappz

Poem

🐰 A timestamp hops through the sync, so neat,
From gRPC's greeting to the peer's heartbeat,
No more guessing when a connection came,
The reqStart carries truth—precision's the game! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description follows the template structure but lacks critical implementation details: no issue ticket number, no stack information, and minimal explanation of the bug fix beyond the checklist marking. Add issue ticket number/link, provide clear explanation of what the bug was and why the syncTime parameter propagation fixes it, and populate stack/commit details.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: checking stream start time for connecting peers through the addition of a syncTime parameter propagated across multiple method signatures.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/stream-start-time

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.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Feb 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
1 New issue
1 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug related to checking stream start time for connecting peers. It adds a syncTime parameter to track when sync requests start, preventing stale connection updates from overwriting newer peer activity. This addresses race conditions where delayed or blocked goroutines could incorrectly update peer connection states.

Changes:

  • Added syncTime parameter to MarkPeerConnected and SyncAndMarkPeer functions to enable stale request detection
  • Implemented logic to skip connection updates when the provided syncTime is not after the peer's current LastSeen timestamp
  • Updated gRPC server to use request start time (reqStart) consistently as the sync time throughout the request lifecycle

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
management/server/peer.go Added syncTime parameter to MarkPeerConnected and updatePeerStatusAndLocation; implemented stale request detection logic
management/server/account/manager.go Updated interface signatures to include syncTime parameter
management/server/account.go Updated SyncAndMarkPeer to pass syncTime; OnPeerDisconnected uses time.Now().UTC()
management/internals/shared/grpc/server.go Changed to use reqStart consistently as syncTime instead of creating new timestamps
management/server/account_test.go Updated existing tests and added new test case for stale connect protection
management/server/mock_server/account_mock.go Updated mock signatures (with critical bugs in implementation)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

func (am *MockAccountManager) MarkPeerConnected(ctx context.Context, peerKey string, connected bool, realIP net.IP, accountID string, syncTime time.Time) error {
if am.MarkPeerConnectedFunc != nil {
return am.MarkPeerConnectedFunc(ctx, peerKey, connected, realIP)
return am.MarkPeerConnectedFunc(ctx, peerKey, connected, realIP, syncTime)
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The call to MarkPeerConnectedFunc is missing the accountID parameter. The function signature requires (ctx, peerKey, connected, realIP, accountID, syncTime) but only (ctx, peerKey, connected, realIP, syncTime) is being passed. This will cause a compilation error or runtime panic if this mock function is used.

Suggested change
return am.MarkPeerConnectedFunc(ctx, peerKey, connected, realIP, syncTime)
return am.MarkPeerConnectedFunc(ctx, peerKey, connected, realIP, accountID, syncTime)

Copilot uses AI. Check for mistakes.
Comment thread management/server/mock_server/account_mock.go
Copy link
Copy Markdown
Contributor

@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: 1

🤖 Fix all issues with AI agents
In `@management/server/peer.go`:
- Around line 120-132: The disconnect path can regress peer state because
updatePeerStatusAndLocation always sets LastSeen to syncTime; change the guard
so when handling a disconnect (connected==false) you skip the update if syncTime
is older than the current peer.Status.LastSeen (i.e. if
syncTime.Before(peer.Status.LastSeen) do not call updatePeerStatusAndLocation),
but still allow updates when syncTime.Equal(peer.Status.LastSeen) for the same
stream; apply the same check wherever the symmetric disconnect block exists (the
other occurrence around lines referenced in the review) to ensure LastSeen and
Connected are not overwritten by stale disconnect events.
🧹 Nitpick comments (1)
management/server/mock_server/account_mock.go (1)

40-41: Expose accountID in MarkPeerConnectedFunc to mirror the interface.

MockAccountManager.MarkPeerConnected receives accountID but drops it when delegating, which limits test assertions. Since the signature changed here, consider passing it through.

♻️ Suggested change
-	MarkPeerConnectedFunc                 func(ctx context.Context, peerKey string, connected bool, realIP net.IP, syncTime time.Time) error
+	MarkPeerConnectedFunc                 func(ctx context.Context, peerKey string, connected bool, realIP net.IP, accountID string, syncTime time.Time) error
-		return am.MarkPeerConnectedFunc(ctx, peerKey, connected, realIP, syncTime)
+		return am.MarkPeerConnectedFunc(ctx, peerKey, connected, realIP, accountID, syncTime)

Also applies to: 325-328

Comment thread management/server/peer.go
@crn4 crn4 merged commit af8f730 into main Feb 6, 2026
45 of 47 checks passed
@crn4 crn4 deleted the fix/stream-start-time branch February 6, 2026 17:00
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.

3 participants