Skip to content

Remove redundant chat cancellation handlers#1944

Merged
chernistry merged 1 commit into
mainfrom
fix/1785-chat-driver-s2737
May 22, 2026
Merged

Remove redundant chat cancellation handlers#1944
chernistry merged 1 commit into
mainfrom
fix/1785-chat-driver-s2737

Conversation

@chernistry

@chernistry chernistry commented May 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • remove redundant CancelledError catch-and-rethrow blocks from chat edit throttles
  • leave cancellation propagation to asyncio
  • add a regression test for the redundant handler pattern in chat drivers

Tests

  • uv run pytest tests/unit/core/chat/test_driver_cancellation_handlers.py tests/unit/core/chat/test_discord_driver.py tests/unit/core/chat/test_slack_driver.py tests/unit/test_chat_drivers.py -q --tb=short
  • uv run ruff check src/bernstein/core/chat/drivers/discord.py src/bernstein/core/chat/drivers/slack.py src/bernstein/core/chat/drivers/telegram.py tests/unit/core/chat/test_driver_cancellation_handlers.py
  • uv run ruff format --check src/bernstein/core/chat/drivers/discord.py src/bernstein/core/chat/drivers/slack.py src/bernstein/core/chat/drivers/telegram.py tests/unit/core/chat/test_driver_cancellation_handlers.py
  • uv run pyright --project pyrightconfig.strict.json
  • git diff --check

Refs #1785

Summary by CodeRabbit

  • Refactor

    • Streamlined asynchronous error handling across chat drivers by removing redundant cancellation exception wrapper patterns for cleaner, more efficient error propagation.
  • Tests

    • Added comprehensive test suite validating that task cancellation properly propagates without unnecessary intermediate exception handling in chat driver implementations.

Review Change Stack

@sourcery-ai sourcery-ai Bot 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.

Sorry @chernistry, you have reached your weekly rate limit of 2500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@chernistry chernistry enabled auto-merge (squash) May 22, 2026 18:45
@github-actions

Copy link
Copy Markdown
Contributor

Sonar insights (advisory, no merge-block)

Snapshot of bernstein on the configured Sonar instance:

Metric Value
Coverage 13.5
Code smells 140
Bugs 11
Vulnerabilities 2
Security hotspots 91

Run bernstein doctor sonar locally for the full surface.

This comment is a soft signal. The Sonar scan runs on push to main; the PR check itself never fails on smells.

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR removes redundant try/except asyncio.CancelledError blocks from deferred flush methods in three chat drivers (Discord, Slack, Telegram). Cancellation exceptions now propagate directly from asyncio.sleep(delay) instead of being caught and re-raised. A new regression test using AST inspection ensures the pattern does not reappear.

Changes

Cancellation handling simplification and regression test

Layer / File(s) Summary
Simplify cancellation propagation in three drivers
src/bernstein/core/chat/drivers/discord.py, src/bernstein/core/chat/drivers/slack.py, src/bernstein/core/chat/drivers/telegram.py
Three _deferred_flush methods remove explicit try/except asyncio.CancelledError wrappers around asyncio.sleep(delay) (line 714 in discord.py, line 659 in slack.py, line 273 in telegram.py), allowing cancellation to propagate naturally without catch-and-rethrow.
Regression test for CancelledError propagation
tests/unit/core/chat/test_driver_cancellation_handlers.py
New test module (lines 1–32) uses Python AST to scan chat driver source files and verify that no redundant except CancelledError handlers that only re-raise are present, preventing accidental reintroduction of the removed pattern.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • sipyourdrink-ltd/bernstein#1809: Both PRs touch src/bernstein/core/chat/drivers/discord.py's deferred flush path; this PR removes redundant CancelledError catch/rethrow in _deferred_flush.
  • sipyourdrink-ltd/bernstein#1804: Directly overlaps with Slack driver deferred edit-flush logic that this PR simplifies in src/bernstein/core/chat/drivers/slack.py.

Suggested labels

core, tests, size/s

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description covers what was changed, why it matters, and provides specific test commands, but does not follow the repository's template structure with required sections. Restructure the description to match the template: use 'What', 'Why', and 'How' sections, and complete the checklist items including documentation duty assessment.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: removing redundant CancelledError handlers from chat drivers.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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/1785-chat-driver-s2737

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

@github-actions

github-actions Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Review-bot acknowledgement summary

  • Must-address findings: 0 (0 acknowledged, 0 open)
  • Informational findings: 1

All must-address findings are resolved or acknowledged.

@github-actions

Copy link
Copy Markdown
Contributor

bernstein doctor observe for PR #1944 (fix/1785-chat-driver-s2737): ok=1, warn=1, fail=0, error=0, skipped=2

sonar -- WARN (project bernstein)

metric value delta threshold status
coverage_pct 13.5% new 80.0% fail
code_smells 140 new 50 warn
bugs 11 new 0 fail
vulnerabilities 2 new 0 warn
security_hotspots 91 new 0 fail

code-scanning -- OK (23 open alert(s))

metric value delta threshold status
open_alerts 23 new 0 fail
critical_alerts 0 new 0 ok
high_alerts 0 new 0 ok
medium_alerts 0 new - ok
low_alerts 0 new - ok
Skipped backends (credentials not configured)
  • glitchtip: BERNSTEIN_GLITCHTIP_TOKEN not set
  • dt: DTRACK_URL/TOKEN/PROJECT not set

See docs/observability/unified-doctor.md for backend setup notes.

@coderabbitai coderabbitai Bot 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.

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 `@tests/unit/core/chat/test_driver_cancellation_handlers.py`:
- Around line 22-29: The current conditional in the test only detects
CancelledError when written as an attribute (e.g., asyncio.CancelledError);
update the boolean check to accept either an ast.Attribute whose .attr ==
"CancelledError" OR an ast.Name whose .id == "CancelledError" so both
"asyncio.CancelledError" and "from asyncio import CancelledError" are matched;
modify the condition around handler.type (used in the if that tests
isinstance(handler, ast.ExceptHandler) and handler.type.attr ==
"CancelledError") to allow (isinstance(handler.type, ast.Attribute) and
handler.type.attr == "CancelledError") or (isinstance(handler.type, ast.Name)
and handler.type.id == "CancelledError").
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f46d4086-5c07-4c63-abb7-94507a018edb

📥 Commits

Reviewing files that changed from the base of the PR and between 9b0a0f3 and 70549c1.

📒 Files selected for processing (4)
  • src/bernstein/core/chat/drivers/discord.py
  • src/bernstein/core/chat/drivers/slack.py
  • src/bernstein/core/chat/drivers/telegram.py
  • tests/unit/core/chat/test_driver_cancellation_handlers.py

Comment on lines +22 to +29
if (
isinstance(handler, ast.ExceptHandler)
and isinstance(handler.type, ast.Attribute)
and handler.type.attr == "CancelledError"
and len(handler.body) == 1
and isinstance(handler.body[0], ast.Raise)
and handler.body[0].exc is None
):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Handle both asyncio.CancelledError and direct CancelledError imports.

Line 24 checks isinstance(handler.type, ast.Attribute), which matches asyncio.CancelledError but would miss from asyncio import CancelledError. All three drivers currently import asyncio as a module, so the test works. For robustness against future changes, consider:

🔍 Proposed enhancement to handle both import patterns
         for handler in ast.walk(tree):
+            # Match both asyncio.CancelledError (ast.Attribute) and CancelledError (ast.Name)
+            is_cancelled_error = False
+            if isinstance(handler.type, ast.Attribute) and handler.type.attr == "CancelledError":
+                is_cancelled_error = True
+            elif isinstance(handler.type, ast.Name) and handler.type.id == "CancelledError":
+                is_cancelled_error = True
+            
             if (
                 isinstance(handler, ast.ExceptHandler)
-                and isinstance(handler.type, ast.Attribute)
-                and handler.type.attr == "CancelledError"
+                and is_cancelled_error
                 and len(handler.body) == 1
                 and isinstance(handler.body[0], ast.Raise)
                 and handler.body[0].exc is None
             ):
🤖 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 `@tests/unit/core/chat/test_driver_cancellation_handlers.py` around lines 22 -
29, The current conditional in the test only detects CancelledError when written
as an attribute (e.g., asyncio.CancelledError); update the boolean check to
accept either an ast.Attribute whose .attr == "CancelledError" OR an ast.Name
whose .id == "CancelledError" so both "asyncio.CancelledError" and "from asyncio
import CancelledError" are matched; modify the condition around handler.type
(used in the if that tests isinstance(handler, ast.ExceptHandler) and
handler.type.attr == "CancelledError") to allow (isinstance(handler.type,
ast.Attribute) and handler.type.attr == "CancelledError") or
(isinstance(handler.type, ast.Name) and handler.type.id == "CancelledError").

@chernistry chernistry merged commit 329fa8e into main May 22, 2026
79 of 81 checks passed
@chernistry chernistry deleted the fix/1785-chat-driver-s2737 branch May 22, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant