Skip to content

Propagate Graph send cancellation#592

Merged
PrzemyslawKlys merged 1 commit intov2-speedygonzalesfrom
codex/graph-cancellation-propagation
Mar 10, 2026
Merged

Propagate Graph send cancellation#592
PrzemyslawKlys merged 1 commit intov2-speedygonzalesfrom
codex/graph-cancellation-propagation

Conversation

@PrzemyslawKlys
Copy link
Copy Markdown
Member

Summary: propagate explicit caller cancellation through Graph connect/send flows instead of converting it into normal failures or retries, and make canceled attachment preparation throw instead of returning partial chunks. Testing: dotnet test Sources/Mailozaurr.sln --no-restore --filter "FullyQualifiedNameSendEmailBasicTests|FullyQualifiedNameGraphDraftTests" -v minimal; dotnet test Sources/Mailozaurr.sln --no-restore -v minimal.

@PrzemyslawKlys PrzemyslawKlys merged commit 24fd332 into v2-speedygonzales Mar 10, 2026
4 checks passed
@PrzemyslawKlys PrzemyslawKlys deleted the codex/graph-cancellation-propagation branch March 10, 2026 20:18
@claude
Copy link
Copy Markdown

claude bot commented Mar 10, 2026

Claude finished @PrzemyslawKlys's task —— View job


Code Review for PR #592: Propagate Graph Send Cancellation

I've completed my analysis of the cancellation propagation changes in the Microsoft Graph functionality. Here's my comprehensive review:

Summary of Changes

This PR implements proper cancellation propagation throughout the Graph send operations, ensuring that when a caller cancels an operation (via CancellationToken), it's handled as a genuine cancellation rather than being converted to normal failures or retries.

Key Changes Analyzed:

  1. Graph.cs - Enhanced cancellation handling in multiple async methods
  2. SendEmailBasicTests.cs - Added 45 new tests including cancellation scenarios
  3. GraphDraftTests.cs - Added 20 tests for draft operations and cancellation

Strengths & Good Practices

1. Proper Exception Differentiation

} catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) {
    throw; // Correctly propagates genuine cancellation
} catch (TaskCanceledException ex) {
    // Handles timeout/other cancellations appropriately
  • Excellent distinction between explicit caller cancellation and other timeout scenarios
  • Uses exception filters to ensure only actual cancellations are propagated

2. Consistent Cancellation Token Threading

  • All new async methods properly accept and pass through CancellationToken parameters
  • Methods like CreateDraftMessageAsync, UploadAttachmentsAsync, and PrepareAttachments consistently propagate tokens
  • Good use of cancellationToken.ThrowIfCancellationRequested() in file processing loops

3. Comprehensive Test Coverage

  • Sources/Mailozaurr.Tests/SendEmailBasicTests.cs:232-273 - Tests cover connect, send, and draft scenarios
  • Tests verify that OperationCanceledException is thrown rather than returned as failed results
  • Good test structure with proper setup/teardown

4. Attachment Processing Improvements

  • Sources/Mailozaurr/MicrosoftGraph/Graph.cs:1019-1021 - Added cancellation checks in file chunk processing loops
  • Prevents long-running attachment operations from becoming unresponsive

🔍 Areas for Improvement

1. Missing Cancellation in Some Areas

  • SendMessageBatchAsync method doesn't seem to have the same comprehensive cancellation handling as other send methods
  • Some utility methods could benefit from cancellation token propagation

2. Resource Cleanup Considerations

private List<StreamContent> PrepareByteArrayContentForUpload(...) {
    // Creates StreamContent objects but cancellation could leave them uncleaned
}
  • When cancellation occurs during attachment preparation, created StreamContent objects might not be properly disposed

3. Retry Logic Complexity

  • The retry logic in SendMessageAsync and SendMessageDraftAsync is complex and could potentially mask some cancellation scenarios
  • Consider extracting retry logic to a separate method for better testability

🐛 Potential Issues

1. Minor Race Condition Risk

await WaitForConcurrencyAsync(operationStopwatch, cancellationToken);
try {
    using var response = await _client.SendAsync(request, cancellationToken);
    // ... processing
} finally {
    MicrosoftGraphUtils.ConcurrencySemaphore.Release();
}
  • If cancellation occurs between semaphore acquisition and the try block, the semaphore might not be released
  • Current code is actually correct, but could be made more explicit

2. Test Coverage Gap

  • Tests focus on immediate cancellation but don't test cancellation during long-running operations
  • No tests for cancellation during file chunk uploads

Performance Considerations

1. Positive Impact

  • Cancellation prevents unnecessary work and resource consumption
  • Proper cleanup when operations are cancelled early

2. No Significant Performance Concerns

  • The changes are well-implemented without introducing performance bottlenecks
  • Cancellation checks are appropriately placed and lightweight

🔒 Security Assessment

1. No Security Concerns Identified

  • Cancellation handling doesn't introduce attack vectors
  • Proper exception handling prevents information leakage
  • Resource cleanup is handled appropriately

🧪 Test Quality

1. Excellent Test Additions

  • Tests are focused and verify the specific behavior change
  • Good use of CancellationTokenSource in tests
  • Tests verify both direct cancellation and timeout scenarios

2. Suggestion for Additional Tests

// Consider adding tests for:
// - Cancellation during file upload chunks
// - Cancellation during large attachment processing
// - Verification that resources are cleaned up properly

Overall Assessment

This is a high-quality implementation that significantly improves the cancellation handling in Microsoft Graph operations. The changes are:

  • Well-architected - Proper separation of concerns between cancellation and failure
  • Thoroughly tested - Good coverage of cancellation scenarios
  • Backward compatible - Default parameters maintain existing API compatibility
  • Performance conscious - No unnecessary overhead introduced
  • Security sound - No security implications

🎯 Recommendations

  1. Consider adding cancellation tests for file operations to ensure large uploads can be cancelled cleanly
  2. Document the cancellation behavior in method XML comments to clarify the distinction between cancellation and failures
  3. Extract retry logic into helper methods to improve maintainability

The PR successfully achieves its goal of properly propagating caller cancellation through Graph operations while maintaining excellent code quality standards.


@codecov
Copy link
Copy Markdown

codecov bot commented Mar 10, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.11%. Comparing base (217b09a) to head (615c3b7).
⚠️ Report is 6 commits behind head on v2-speedygonzales.

Files with missing lines Patch % Lines
Sources/Mailozaurr/MicrosoftGraph/Graph.cs 50.00% 6 Missing ⚠️
Additional details and impacted files
@@                  Coverage Diff                  @@
##           v2-speedygonzales     #592      +/-   ##
=====================================================
+ Coverage              44.59%   45.11%   +0.52%     
=====================================================
  Files                    335      335              
  Lines                  22222    22232      +10     
  Branches                3950     3949       -1     
=====================================================
+ Hits                    9909    10030     +121     
+ Misses                 11078    10960     -118     
- Partials                1235     1242       +7     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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