Skip to content

refactor(tui): extract _dispatch_notification, use time.time_ns() for rid - #27711

Open
Ade5954 wants to merge 1 commit into
NousResearch:mainfrom
Ade5954:refactor/tui-dedup-notification-loop
Open

refactor(tui): extract _dispatch_notification, use time.time_ns() for rid#27711
Ade5954 wants to merge 1 commit into
NousResearch:mainfrom
Ade5954:refactor/tui-dedup-notification-loop

Conversation

@Ade5954

@Ade5954 Ade5954 commented May 18, 2026

Copy link
Copy Markdown
Contributor
  1. Extract _dispatch_notification() to eliminate duplicated code between the main poller loop and shutdown drain in _notification_poller_loop(). The shared helper handles consumed-skip, formatting, status.update emission, busy guard, and turn dispatch. The caller picks continue vs break based on 'busy' return status.

  2. Replace int(time.time() * 1000) with time.time_ns() for notification rid generation to avoid potential collisions when two events arrive in the same millisecond.

All 3 notification_poller tests pass.

What does this PR do?

simplify the code and replace int(time.time() * 1000) with time.time_ns() for notification rid generation to avoid potential collisions when two events arrive in the same millisecond

Related Issue

#26327

… rid

1. Extract _dispatch_notification() to eliminate duplicated code between the main poller loop and shutdown drain in _notification_poller_loop(). The shared helper handles consumed-skip, formatting, status.update emission, busy guard, and turn dispatch. The caller picks continue vs break based on 'busy' return status.

2. Replace int(time.time() * 1000) with time.time_ns() for notification rid generation to avoid potential collisions when two events arrive in the same millisecond.

All 3 notification_poller tests pass.
@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P3 Low — cosmetic, nice to have comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels May 18, 2026
@teknium1

teknium1 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Thanks for the cleanup. The time.time_ns() part still addresses real code on current main, but the extraction needs to preserve notification-poller behavior added after this PR’s base.

Problems

  • The PR diff (gh pr diff 27711 --repo NousResearch/hermes-agent) moves dispatch into _dispatch_notification, but that helper emits status.update unconditionally. Current main deduplicates requeued notifications with _notification_event_dedup_key/_emitted at tui_gateway/server.py:5519 and tui_gateway/server.py:5562; losing that would bring back repeated status updates while the session is busy.
  • The PR diff also predates current main’s multi-session ownership guard. Current main requeues foreign live-session events at tui_gateway/server.py:5502 and defers/requeues them during shutdown drain at tui_gateway/server.py:5552 and tui_gateway/server.py:5587; the extracted helper needs to keep that behavior.

Suggested changes

  • Keep the rid improvement: current main still uses int(time.time() * 1000) at tui_gateway/server.py:5530 and tui_gateway/server.py:5573.
  • When extracting the helper, pass through the _emitted set or otherwise retain the dedup guard for both loop paths, and keep the session-ownership filtering/deferred requeue semantics intact.

This is an automated hermes-sweeper review.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the cleanup. The time.time_ns() RID improvement still applies on current main (tui_gateway/server.py:8775, :8827), but the extraction needs to retain notification-poller behavior added after this branch.

Problems

  • PR tui_gateway/server.py:3057 emits status.update unconditionally. Current main deduplicates requeued notifications at tui_gateway/server.py:8752-8759 (e7a7872a874837ca36105ca3e90db464cf7c125a); otherwise a busy session receives repeated process-status lines.
  • The current live and drain paths preserve cross-session ownership and fail closed for unowned async-delegation payloads (tui_gateway/server.py:8708-8742, :8797-8808). The proposed helper/callers omit those gates.
  • PR tui_gateway/server.py:3104 immediately retries a busy requeue, removing current main's required 0.25-second backoff at tui_gateway/server.py:8769-8772 (98804dbeef91c5f1ef517817c8f81dd2aeec523e).

Suggested changes

  • Extract only after preserving the live/drain ownership rules, pass through the emitted-dedup state, and retain live-loop backoff versus drain break semantics.
  • Add coverage for those current guarantees alongside the RID change.

This is an automated hermes-sweeper review.

Comment thread tui_gateway/server.py
if not text:
return "empty"

_emit("status.update", sid, {"kind": "process", "text": text})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Current main emits this only when _notification_event_dedup_key(evt) is absent from the poller's _emitted set (tui_gateway/server.py:8752-8759). Keeping this unconditional reintroduces duplicate process-status updates every time a busy session requeues the same event.

Comment thread tui_gateway/server.py

text = format_process_notification(evt)
if not text:
status = _dispatch_notification(evt, sid, session)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Before dispatching, current main must preserve the foreign-live-session requeue and fail-closed async-delegation ownership checks (tui_gateway/server.py:8708-8742). Dispatching every dequeued event here can route a notification or delegation payload to the wrong session.

Comment thread tui_gateway/server.py
text = format_process_notification(evt)
if not text:
status = _dispatch_notification(evt, sid, session)
if status == "busy":

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please retain the live-loop time.sleep(0.25) backoff after a busy requeue (tui_gateway/server.py:8769-8772; 98804dbeef91c5f1ef517817c8f81dd2aeec523e). An immediate continue restores the busy-poller CPU spin this fix addressed.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants