Skip to content

fix(OMN-11318): avoid grouped Pattern B terminal waits - #1680

Merged
jonahgabriel merged 3 commits into
mainfrom
jonah/omn-11318-pattern-b-terminal-waiter
May 21, 2026
Merged

jonahgabriel merged 3 commits into
mainfrom
jonah/omn-11318-pattern-b-terminal-waiter

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented May 21, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence-Ticket: OMN-11318

Summary

  • switch the Pattern B one-shot terminal waiter to an ungrouped, manually assigned Kafka consumer
  • keep the waiter seeking terminal partitions before dispatching the worker command
  • add OMN-11318 deploy-gate contract and regression coverage

Verification

  • uv run validate-yaml contracts/OMN-11318.yaml
  • uv run pytest tests/unit/runtime/test_service_pattern_b_broker.py -q
  • uv run ruff format --check src/omnibase_infra/runtime/service_pattern_b_broker.py tests/unit/runtime/test_service_pattern_b_broker.py
  • uv run ruff check src/omnibase_infra/runtime/service_pattern_b_broker.py tests/unit/runtime/test_service_pattern_b_broker.py
  • pre-commit hooks passed
  • pre-push hooks passed

Runtime Evidence

  • .201 runtime rebuilt from merged infra 363b05b2 was healthy, and delegate-skill command consumer group was stable with 1 member and 0 lag.
  • /skill smoke correlation 86622b02-46b5-4339-ab13-2758b2851255 emitted onex.evt.omnimarket.delegate-skill-completed.v1, but the HTTP request did not return, proving this terminal waiter boundary.

Post-merge deploy proof still required: rebuild/restart the .201 stability runtime from this merged change, then rerun the /skill smoke and verify it returns after the terminal event.

Summary by CodeRabbit

  • Bug Fixes

    • Pattern B terminal waiter now uses an ungrouped, manually assigned consumer for more reliable request-correlated terminal event handling.
  • Tests

    • Enhanced unit and new integration tests to validate the updated terminal-wait behavior and consumer lifecycle.
  • Documentation

    • Added a contract/spec file documenting the change and defining done-of-delivery checks and verification steps.

Review Change Stack

Evidence-Source: OCC#1242

@coderabbitai

coderabbitai Bot commented May 21, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR fixes a local ingress hang in Pattern B terminal waiter by switching from a grouped subscription-based Kafka consumer to an ungrouped consumer with explicit partition discovery and assignment. The implementation adds a helper that discovers partitions and assigns them with retry timeout before publishing the worker command.

Changes

Pattern B Kafka consumer ungrouped partition assignment

Layer / File(s) Summary
Contract definition and DOD evidence
contracts/OMN-11318.yaml
Contract OMN-11318 documents the terminal-waiter local ingress hang fix, specifying unit test and linting evidence requirements plus manual post-deploy stability verification.
Ungrouped consumer creation and explicit partition assignment
src/omnibase_infra/runtime/service_pattern_b_broker.py
RuntimePatternBBroker's direct consumer now starts without a group_id and explicitly discovers then assigns terminal-topic partitions via a new helper function with retry logic, replacing the prior subscription-then-wait pattern.
Unit test fake and assertion updates
tests/unit/runtime/test_service_pattern_b_broker.py
FakeAIOKafkaConsumer now captures constructor kwargs, tracks assigned partitions, implements partitions_for_topic() and assign()/assignment(), and unit tests assert group_id=None, partition assignment, and terminal topic assignments.
Integration test for one-shot terminal waiter
tests/integration/test_pattern_b_broker_terminal_waiter.py
Adds an integration test that stubs AIOKafkaConsumer and transport to synthesize a terminal event mapped to the dispatched command correlation id, asserting the resolved route, result payload, and that the consumer was stopped.

Sequence Diagram(s)

sequenceDiagram
  participant RuntimePatternBBroker
  participant AIOKafkaConsumer
  participant KafkaCluster
  RuntimePatternBBroker->>AIOKafkaConsumer: create(bootstrap_servers, group_id=None)
  RuntimePatternBBroker->>AIOKafkaConsumer: partitions_for_topic(terminal_topic)
  AIOKafkaConsumer->>KafkaCluster: metadata request for topic partitions
  KafkaCluster-->>AIOKafkaConsumer: partition list
  RuntimePatternBBroker->>AIOKafkaConsumer: assign(TopicPartition set)
  AIOKafkaConsumer->>KafkaCluster: assign partitions
  RuntimePatternBBroker->>AIOKafkaConsumer: assignment() with retry until timeout
  AIOKafkaConsumer-->>RuntimePatternBBroker: assigned partitions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A broker once waited in vain,
For partitions assigned by the main,
Now ungrouped and free,
Assignments agree,
Local ingress hops off the chain. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(OMN-11318): avoid grouped Pattern B terminal waits' directly and specifically summarizes the main change: switching from a grouped to an ungrouped Kafka consumer for Pattern B terminal waits.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 jonah/omn-11318-pattern-b-terminal-waiter

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

@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

🧹 Nitpick comments (1)
tests/unit/runtime/test_service_pattern_b_broker.py (1)

114-121: ⚡ Quick win

Make partition discovery configurable per topic in the fake consumer.

Current fake behavior always resolves every topic once started, so it can’t catch regressions where assignment happens before all terminal topics are discoverable.

Suggested refactor sketch
 class _FakeAIOKafkaConsumer:
@@
-    def __init__(self, *topics: object, **kwargs: object) -> None:
+    def __init__(self, *topics: object, **kwargs: object) -> None:
         self.topics = topics
         self.kwargs = kwargs
         self.messages: asyncio.Queue[SimpleNamespace] = asyncio.Queue()
         self.assigned_partitions: set[object] = set()
+        self.topic_partitions: dict[str, set[int]] = {}
@@
     def partitions_for_topic(self, topic: str) -> set[int]:
-        return {0} if self.started and topic else set()
+        if not self.started or not topic:
+            return set()
+        return set(self.topic_partitions.get(topic, {0}))
🤖 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/runtime/test_service_pattern_b_broker.py` around lines 114 - 121,
The fake consumer currently resolves every topic once started via
partitions_for_topic, causing tests to miss cases where some topics aren't yet
discoverable; modify the fake consumer to accept a configurable mapping or
callback (e.g., a constructor arg like discoverable_partitions: dict[str,
set[int]] or partitions_resolver: Callable[[str], set[int]]) and change
partitions_for_topic(self, topic: str) to return
discoverable_partitions.get(topic, set()) or call the resolver, leaving
assign(self, partitions: set[object]) and assignment(self) untouched so tests
can control which topics are discoverable and simulate
assignment-before-discovery regressions.
🤖 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 `@src/omnibase_infra/runtime/service_pattern_b_broker.py`:
- Around line 309-320: The loop currently returns as soon as any partition is
found, which lets multi-terminal routes assign only a subset of topics; change
the condition so it waits until every topic in topics has at least one partition
before calling consumer.assign(partitions) and returning. Use
consumer.partitions_for_topic(topic) to detect per-topic partitions, build the
TopicPartition set as shown, then verify that all topics are represented (e.g.,
every topic has non-empty topic_partitions) before assigning; keep the same
timeout check using asyncio.get_running_loop().time() >= deadline and raise
TimeoutError if the deadline is exceeded.

---

Nitpick comments:
In `@tests/unit/runtime/test_service_pattern_b_broker.py`:
- Around line 114-121: The fake consumer currently resolves every topic once
started via partitions_for_topic, causing tests to miss cases where some topics
aren't yet discoverable; modify the fake consumer to accept a configurable
mapping or callback (e.g., a constructor arg like discoverable_partitions:
dict[str, set[int]] or partitions_resolver: Callable[[str], set[int]]) and
change partitions_for_topic(self, topic: str) to return
discoverable_partitions.get(topic, set()) or call the resolver, leaving
assign(self, partitions: set[object]) and assignment(self) untouched so tests
can control which topics are discoverable and simulate
assignment-before-discovery regressions.
🪄 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: 7631286d-09f8-427b-8457-c1580c9b09c5

📥 Commits

Reviewing files that changed from the base of the PR and between 363b05b and 76255e1.

📒 Files selected for processing (3)
  • contracts/OMN-11318.yaml
  • src/omnibase_infra/runtime/service_pattern_b_broker.py
  • tests/unit/runtime/test_service_pattern_b_broker.py

Comment thread src/omnibase_infra/runtime/service_pattern_b_broker.py

@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/integration/test_pattern_b_broker_terminal_waiter.py`:
- Line 79: Replace the hardcoded broker endpoint assigned to _bootstrap_servers
("redpanda:9092") with a value read from an environment variable (e.g.,
KAFKA_BOOTSTRAP_SERVERS), falling back to the current literal as a default;
update the assignment where _bootstrap_servers is defined so tests pick the
broker from os.environ (or equivalent env API) rather than a hardcoded string.
🪄 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: fcb9fd9d-e351-4da0-aeff-692d0f784bed

📥 Commits

Reviewing files that changed from the base of the PR and between 76255e1 and 5ce83bd.

📒 Files selected for processing (2)
  • contracts/OMN-11318.yaml
  • tests/integration/test_pattern_b_broker_terminal_waiter.py

Comment thread tests/integration/test_pattern_b_broker_terminal_waiter.py Outdated
@jonahgabriel
jonahgabriel merged commit e09eab8 into main May 21, 2026
100 of 107 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-11318-pattern-b-terminal-waiter branch May 21, 2026 00:58
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