Skip to content

fix(WT-1083): use processingStatus to guard outgoing call reconciliation#1054

Closed
SERDUN wants to merge 4 commits into
developfrom
fix/WT-1083-outgoing-call-reconciliation
Closed

fix(WT-1083): use processingStatus to guard outgoing call reconciliation#1054
SERDUN wants to merge 4 commits into
developfrom
fix/WT-1083-outgoing-call-reconciliation

Conversation

@SERDUN

@SERDUN SERDUN commented Apr 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes a bug where outgoing calls with a failed OutgoingCallRequest would get permanently stuck during StateHandshake reconciliation
  • Replaces the broad acceptedTime == null && hungUpTime == null skip with a precise check against processingStatus
  • No new fields added — CallProcessingStatus.outgoingOfferSent already reliably indicates the request reached the server

Details

During handshake reconciliation, the BLoC previously skipped all unacknowledged outgoing calls, even those whose OutgoingCallRequest had silently failed. Such calls were never in the server's line list, so they would be skipped on every subsequent handshake and remain stuck forever.

The fix: skip only calls where processingStatus is earlier than outgoingOfferSent (i.e. the request was never sent). If the status is outgoingOfferSent or outgoingRinging but the server has no record of the call → force-terminate it as dead.

@SERDUN SERDUN requested a review from Copilot April 2, 2026 09:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot wasn't able to review any files in this pull request.


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

@SERDUN SERDUN force-pushed the fix/WT-1083-outgoing-call-reconciliation branch 2 times, most recently from be8862b to 13bd7ff Compare April 2, 2026 09:35
@SERDUN SERDUN requested a review from Copilot April 2, 2026 09:36
@SERDUN SERDUN marked this pull request as ready for review April 2, 2026 09:36
@SERDUN SERDUN requested a review from digiboridev April 2, 2026 09:37

This comment was marked as resolved.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

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


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

Comment on lines +2456 to +2465
final activeLineCallIds = [
...stateHandshake.lines,
stateHandshake.guestLine,
].whereType<Line>().map((line) => line.callId).toList();

for (final callId in state.callsToTerminate(activeLineCallIds)) {
final activeCall = state.retrieveActiveCall(callId);
if (activeCall == null) continue;
_peerConnectionManager.conditionalCompleteError(callId, 'Active call Request Terminated');
add(_CallSignalingEvent.hangup(line: activeCall.line, callId: callId, code: 487, reason: 'Request Terminated'));

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

activeLineCallIds is built as a List<String> and then used only for membership checks (contains) inside CallState.callsToTerminate, which makes the reconciliation O(activeCalls * lineCount). Consider using a Set<String> here (e.g., toSet()) and updating callsToTerminate to accept a Set (or convert once inside the method) so lookups are O(1).

Copilot uses AI. Check for mistakes.
Comment thread lib/features/call/bloc/call_state.dart Outdated
Comment on lines +95 to +104
List<String> callsToTerminate(List<String> activeLineCallIds) {
final result = <String>[];
activeCallsLoop:
for (final activeCall in activeCalls) {
if (activeLineCallIds.contains(activeCall.callId)) continue activeCallsLoop;
if (activeCall.direction == CallDirection.outgoing &&
activeCall.acceptedTime == null &&
activeCall.hungUpTime == null &&
activeCall.processingStatus.isPreOfferSent) {
continue activeCallsLoop;

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

callsToTerminate performs activeLineCallIds.contains(...) for every active call. If activeLineCallIds can be larger than a handful of entries, consider switching the parameter (or an internal local) to a Set<String> to make membership checks O(1) and avoid repeated linear scans.

Copilot uses AI. Check for mistakes.
@SERDUN SERDUN added the draft Not ready but can be start to review label Apr 2, 2026
SERDUN added 4 commits April 6, 2026 17:43
Instead of skipping all unacknowledged outgoing calls during StateHandshake
reconciliation, skip only those where OutgoingCallRequest was not yet sent.
CallProcessingStatus.outgoingOfferSent is set immediately after a successful
execute(OutgoingCallRequest), so it reliably indicates the server has received
the call. Calls that reached outgoingOfferSent or outgoingRinging but are absent
from the handshake are now correctly treated as dead and force-terminated.
Instead of skipping all unacknowledged outgoing calls during StateHandshake
reconciliation, skip only those where OutgoingCallRequest was not yet sent.
Adds isPreOfferSent getter to CallProcessingStatus enum with an explicit
allowlist of pre-send statuses. Calls that have passed outgoingOfferSent
but are absent from the handshake are treated as dead and force-terminated.
Extract callsToTerminate(List<String> activeLineCallIds) into CallState so
the logic is testable without BLoC dependencies. CallBloc converts signaling
Line objects to callId strings before delegating to the method.

Add unit tests covering: skip in-flight outgoing, terminate post-offer
outgoing, keep calls present in handshake lines.
…rminate

Reduces membership checks from O(n) to O(1) per active call.
@SERDUN SERDUN force-pushed the fix/WT-1083-outgoing-call-reconciliation branch from dc3f3dc to 07610c6 Compare April 6, 2026 15:09
@SERDUN

SERDUN commented Apr 10, 2026

Copy link
Copy Markdown
Member Author

Closing in favour of a fresh branch rebased on current develop.

@SERDUN SERDUN closed this Apr 10, 2026
@SERDUN SERDUN deleted the fix/WT-1083-outgoing-call-reconciliation branch May 22, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

draft Not ready but can be start to review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants