Skip to content

fix(OMN-11319): track Pattern B terminal topics - #1682

Merged
jonahgabriel merged 2 commits into
mainfrom
jonah/omn-11319-pattern-b-topic-tracking
May 21, 2026
Merged

jonahgabriel merged 2 commits into
mainfrom
jonah/omn-11319-pattern-b-topic-tracking

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented May 21, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence-Source: OCC#1245
Evidence-Ticket: OMN-11319

Summary

  • track terminal topics on the direct aiokafka consumer client before assigning partitions
  • keep the fallback all-topic metadata refresh for non-aiokafka fakes/transports
  • add regression coverage for the real metadata behavior observed on .201
  • simplify metadata refresh to match synchronous aiokafka client methods and resolve CodeQL no-effect review threads

Verification

  • uv run pytest tests/unit/runtime/test_service_pattern_b_broker.py tests/integration/test_pattern_b_broker_terminal_waiter.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 tests/integration/test_pattern_b_broker_terminal_waiter.py
  • uv run ruff check src/omnibase_infra/runtime/service_pattern_b_broker.py tests/unit/runtime/test_service_pattern_b_broker.py tests/integration/test_pattern_b_broker_terminal_waiter.py
  • uv run validate-yaml contracts/OMN-11319.yaml
  • uv run mypy src/ --strict
  • git diff --check

OCC Evidence

  • onex_change_control#1245 merged with refreshed central OMN-11319 contract receipts for the current PR head.

Runtime Evidence

  • .201 rebuilt from omnibase_infra main b8a2347 and both runtime services were healthy.
  • /skill smoke correlation a50a826c-89c3-40c0-8295-4b3f4ba8b163 returned dispatch_timeout after 30s.
  • command group stayed Stable with MEMBERS=1 and TOTAL-LAG=0, but no command or terminal event existed for the correlation.
  • In the runtime container, AIOKafkaConsumer.topics() included onex.evt.omnimarket.delegate-skill-completed.v1 while partitions_for_topic() remained None until the consumer client tracked the topic.

Post-merge deploy proof still required: rebuild/restart the .201 stability runtime from this merged change, rerun /skill smoke, and verify the worker command plus terminal event for the smoke correlation.

@coderabbitai

coderabbitai Bot commented May 21, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Refreshes Kafka terminal topic metadata via a new helper that prefers consumer._client.set_topics/add_topic (fallback to consumer.topics()), updates RuntimePatternBBroker to call it during retries, and adjusts unit/integration test fakes and assertions to track and assert set_topics usage. Adds a contract file OMN-11319.

Changes

Pattern B terminal topic tracking fix

Layer / File(s) Summary
Kafka metadata refresh helper and integration point
src/omnibase_infra/runtime/service_pattern_b_broker.py
_refresh_terminal_topic_metadata helper prefers consumer._client.set_topics/add_topic (awaiting if needed) and falls back to consumer.topics(). _assign_terminal_topic_partitions now calls this helper during retry loops.
Unit test Kafka consumer fake with metadata tracking
tests/unit/runtime/test_service_pattern_b_broker.py
Adds _FakeAIOKafkaClient to maintain tracked_topics and implement set_topics(). _FakeAIOKafkaConsumer instantiates the fake client, records set_topics_calls, and only returns partitions during metadata-refresh when the topic is tracked. Test assertions updated to verify set_topics_calls.
Integration test consumer mock with topic tracking
tests/integration/test_pattern_b_broker_terminal_waiter.py
Introduces _TerminalConsumerClient with async set_topics() and tracked_topics. _TerminalConsumer uses the client and records set_topics_calls. partitions_for_topic only returns partitions once started and topic is tracked. Final assertion checks exact set_topics_calls.
Contract specification for Pattern B terminal tracking fix
contracts/OMN-11319.yaml
Adds OMN-11319 contract with schema/ticket metadata, required evidence (unit/integration tests, ruff/lint, manual stability deploy proof), emergency_bypass.enabled: false, and DOD evidence entries.

Sequence Diagram(s)

sequenceDiagram
  participant AssignPartitions as _assign_terminal_topic_partitions
  participant RefreshHelper as _refresh_terminal_topic_metadata
  participant ConsumerClient as consumer._client
  participant ConsumerType as consumer.topics()
  
  AssignPartitions->>RefreshHelper: refresh_terminal_topic_metadata(consumer, topics)
  RefreshHelper->>ConsumerClient: check for set_topics
  alt set_topics exists
    RefreshHelper->>ConsumerClient: set_topics(topics)
    ConsumerClient-->>RefreshHelper: awaitable/result
  else check add_topic
    RefreshHelper->>ConsumerClient: check add_topic
    RefreshHelper->>ConsumerClient: add_topic(topics)
    ConsumerClient-->>RefreshHelper: awaitable/result
  else fallback
    RefreshHelper->>ConsumerType: topics()
    ConsumerType-->>RefreshHelper: list/awaitable
  end
  RefreshHelper-->>AssignPartitions: metadata refreshed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • OmniNode-ai/omnibase_infra#1681: Related changes to RuntimePatternBBroker terminal partition-assignment flow and Pattern B terminal broker tests concerning topic metadata refresh.

Poem

🐰 I hop through topics, soft and spry,

set_topics called beneath the sky,
Helpers probe, fallbacks sing,
Partitions found — the broker's spring. 🥕

🚥 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-11319): track Pattern B terminal topics' directly and clearly summarizes the main change—implementing terminal topic tracking for Pattern B broker. It uses specific terminology matching the changeset's core objective and is concise and actionable.
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-11319-pattern-b-topic-tracking

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

Comment thread src/omnibase_infra/runtime/service_pattern_b_broker.py Fixed
Comment thread src/omnibase_infra/runtime/service_pattern_b_broker.py Fixed
@jonahgabriel
jonahgabriel enabled auto-merge (squash) May 21, 2026 01:53

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

♻️ Duplicate comments (1)
src/omnibase_infra/runtime/service_pattern_b_broker.py (1)

334-343: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep awaitable topic-refresh hooks supported.

If a consumer client exposes async set_topics() or async add_topic(), these calls now create a coroutine and return immediately, so metadata never refreshes and the waiter can spin until timeout. Restoring the old “await if awaitable” behavior keeps the sync AIOKafka path while preserving compatibility with async fakes/transports.

Suggested fix
         set_topics = getattr(client, "set_topics", None)
         if callable(set_topics):
-            set_topics(list(topics))
+            result = set_topics(list(topics))
+            if isinstance(result, Awaitable):
+                await result
             return
 
         add_topic = getattr(client, "add_topic", None)
         if callable(add_topic):
             for topic in topics:
-                add_topic(topic)
+                result = add_topic(topic)
+                if isinstance(result, Awaitable):
+                    await result
             return
#!/bin/bash
set -euo pipefail

printf '\n== async set_topics/add_topic implementations ==\n'
rg -n -C2 --type=py 'async def (set_topics|add_topic)\(' || true

printf '\n== sync set_topics/add_topic implementations ==\n'
rg -n -C2 --type=py 'def (set_topics|add_topic)\(' || true

printf '\n== metadata refresh helper and nearby call sites ==\n'
rg -n -C2 --type=py '_refresh_terminal_topic_metadata|set_topics\(|add_topic\(' || true

If the first section shows any reachable async implementation, the current helper is dropping that refresh path.

🤖 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 `@src/omnibase_infra/runtime/service_pattern_b_broker.py` around lines 334 -
343, The current helper calls client.set_topics(...) and client.add_topic(...)
but drops the coroutine if those methods are async; change the calls to capture
the return value and await it when awaitable so async implementations are
supported: for set_topics call result = set_topics(list(topics)) and if
inspect.isawaitable(result) (or asyncio.iscoroutine(result)) await result; for
add_topic call result = add_topic(topic) inside the loop and await each result
when awaitable (or collect and await them sequentially). Ensure you import
inspect or asyncio and preserve the existing sync behavior in the branches that
use set_topics, add_topic, and the surrounding metadata
refresh/_refresh_terminal_topic_metadata logic.
🤖 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.

Duplicate comments:
In `@src/omnibase_infra/runtime/service_pattern_b_broker.py`:
- Around line 334-343: The current helper calls client.set_topics(...) and
client.add_topic(...) but drops the coroutine if those methods are async; change
the calls to capture the return value and await it when awaitable so async
implementations are supported: for set_topics call result =
set_topics(list(topics)) and if inspect.isawaitable(result) (or
asyncio.iscoroutine(result)) await result; for add_topic call result =
add_topic(topic) inside the loop and await each result when awaitable (or
collect and await them sequentially). Ensure you import inspect or asyncio and
preserve the existing sync behavior in the branches that use set_topics,
add_topic, and the surrounding metadata refresh/_refresh_terminal_topic_metadata
logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5f79cfca-2922-47f3-b7f4-21a0ce7f465a

📥 Commits

Reviewing files that changed from the base of the PR and between ee0b4d2 and 28a5b7e.

📒 Files selected for processing (3)
  • src/omnibase_infra/runtime/service_pattern_b_broker.py
  • tests/integration/test_pattern_b_broker_terminal_waiter.py
  • tests/unit/runtime/test_service_pattern_b_broker.py

@jonahgabriel
jonahgabriel merged commit cbdab8f into main May 21, 2026
75 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-11319-pattern-b-topic-tracking branch May 21, 2026 02:18
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.

2 participants