Skip to content

fix: dual zmq pub for sdr and bridge, sdr pythonpath - #17

Merged
yukikaze223344 merged 4 commits into
mainfrom
develop
Aug 1, 2026
Merged

yukikaze223344 merged 4 commits into
mainfrom
develop

Conversation

@yukikaze223344

@yukikaze223344 yukikaze223344 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • ZMQ PUB now publishes to both tcp://*:5557 (SDR zmq_sub, for GameState and 0x020E encryption rank -> noise grade) and tcp://*:5558 (radar_bridge TransmitGameState), so the updated SDR bridge receives match state without changing the SDR repo
  • start_sdr PYTHONPATH now includes /usr/lib/python3/dist-packages for system GNU Radio, matching the SDR repo start-sdr.sh
  • ZmqPubRuntime::start accepts multiple bind addresses; zmq_start_pub fans out to all sockets

Verification

  • cargo fmt --all --check: pass
  • cargo check: pass
  • cargo test: 94 unit tests + 7 runtime tests passed, 1 hardware-dependent test ignored

Summary by CodeRabbit

  • 新功能

    • ZMQ 发布服务现支持同时通过 :5557:5558 端口发布数据,提升连接兼容性。
  • 改进

    • 更新数据流与架构文档,补充双端口配置及连接说明。
    • 优化 SDR 启动配置,确保 Python 模块路径正确加载。
  • Bug 修复

    • 视频纹理可用时不再错误显示“等待视频”提示。
  • 测试

    • 更新相关测试以适配多端口发布配置。

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

PR 将 ZMQ PUB 从单一 :5558 扩展为 :5557:5558。运行时创建多个 PUB socket,并向所有 socket 发布消息。SDR 启动进程更新 PYTHONPATH。视频等待提示改用视频纹理状态判断。

Changes

ZMQ 多端点发布

Layer / File(s) Summary
PUB 端点启动配置
src/runtime/mod.rs, src/app/mod.rs
ZmqPubRuntime::start 接收多个绑定地址并创建多个 PUB socket。RadarApp::default() 绑定 tcp://*:5557tcp://*:5558
PUB 消息多 socket 发布
src/zmq/zmq.rs, tests/runtime/zmq.rs
zmq_start_pub 接收 socket 向量,并向所有 socket 发送游戏状态、雷达标记处理和自主决策同步消息。测试验证两个 socket 收到相同消息。
端口拓扑文档同步
AGENTS.md, docs/data-flow.md
架构图、数据流、桥接说明和默认连接配置均更新为 :5557/:5558

运行环境与视频提示

Layer / File(s) Summary
SDR PYTHONPATH 配置
src/services/script_runner.rs
start_sdr 在现有 PYTHONPATH 前追加 ./usr/lib/python3/dist-packages,并更新启动说明。
视频等待提示条件
src/app/laser_stage.rs
视频等待提示仅在没有视频纹理且未启用演示模式时显示。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RadarApp
  participant ZmqPubRuntime
  participant zmq_start_pub
  participant PUBSockets
  RadarApp->>ZmqPubRuntime: 启动并传递两个绑定地址
  ZmqPubRuntime->>PUBSockets: 创建 :5557 和 :5558 的 PUB socket
  ZmqPubRuntime->>zmq_start_pub: 传递 socket 向量
  zmq_start_pub->>PUBSockets: 向每个 socket 发布同步消息
Loading

Possibly related PRs

Suggested reviewers: harrypotter1tech

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了双 ZMQ PUB 发布和 SDR PYTHONPATH 修复,且与变更目标直接相关。
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/services/script_runner.rs (1)

244-244: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

保留继承的 PYTHONPATH

.env("PYTHONPATH", ".:/usr/lib/python3/dist-packages") 会替换父进程提供的 PYTHONPATH。如果部署环境通过现有值提供其他 SDR 模块路径,SDR 启动时可能无法导入 thread_init.py 依赖。请在现有值基础上追加仓库根目录和 /usr/lib/python3/dist-packages

🤖 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/services/script_runner.rs` at line 244, 更新 script runner 中设置 PYTHONPATH
的逻辑,保留父进程现有的 PYTHONPATH,并在其基础上追加仓库根目录和
/usr/lib/python3/dist-packages;当父进程未设置该变量时仍使用这两个路径,确保现有 SDR 模块路径不被覆盖。
tests/runtime/zmq.rs (1)

276-276: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

补充双端点 fan-out 回归测试。

Line 276 和 Line 328 都只传入 vec![pub_sock]。这些测试只能验证参数类型变化,不能验证第二个 PUB socket 是否收到同一条消息。请为 IDX_GAME_STATEIDX_RADAR_MARK_PROCESSIDX_RADAR_AUTONOMOUS_DECISION_SYNC 使用两个独立的 PUB/SUB pair,并断言两个 subscriber 都收到正确的 cmd_id 和 payload。

Also applies to: 328-328

🤖 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/runtime/zmq.rs` at line 276, 扩展 tests/runtime/zmq.rs 中由 zmq_start_pub
启动的相关测试,为 IDX_GAME_STATE、IDX_RADAR_MARK_PROCESS 和
IDX_RADAR_AUTONOMOUS_DECISION_SYNC 分别建立两个独立的 PUB/SUB pair,并将两个 PUB socket 传入
fan-out 流程;随后分别从两个 subscriber 接收消息,断言其 cmd_id 和 payload 均正确且一致,覆盖第二个端点的实际转发行为。
🤖 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 `@docs/data-flow.md`:
- Line 27: 统一 docs/data-flow.md 中所有 PUB 端口描述:将 Line 53 和 Line 194 的单一
tcp://*:5557 更新为 :5557/:5558 双端点,并明确 5557 与 5558 的消费者职责;同时核对相关端口说明保持与 Lines
27、201、249 一致,准确反映当前 ZMQ/ROS2 Radar 设计。

In `@src/zmq/zmq.rs`:
- Around line 119-121: Update each publishing loop around zmq_send so individual
socket send errors are handled instead of discarded with .ok(). On Err, log the
socket’s endpoint identity and apply an explicit policy—retry, remove the failed
socket, or terminate the publishing thread—consistently across all three publish
branches; keep Value::to_string() unchanged.
- Around line 119-121: Move the blocking zmq_send calls out of the SharedData
lock scope in the payload construction flow. Read the required SharedData fields
and build the message while holding the lock, then release the lock before
iterating over pub_sockets and sending to each endpoint; preserve the existing
per-socket send behavior and error handling.

---

Nitpick comments:
In `@src/services/script_runner.rs`:
- Line 244: 更新 script runner 中设置 PYTHONPATH 的逻辑,保留父进程现有的
PYTHONPATH,并在其基础上追加仓库根目录和
/usr/lib/python3/dist-packages;当父进程未设置该变量时仍使用这两个路径,确保现有 SDR 模块路径不被覆盖。

In `@tests/runtime/zmq.rs`:
- Line 276: 扩展 tests/runtime/zmq.rs 中由 zmq_start_pub 启动的相关测试,为
IDX_GAME_STATE、IDX_RADAR_MARK_PROCESS 和 IDX_RADAR_AUTONOMOUS_DECISION_SYNC
分别建立两个独立的 PUB/SUB pair,并将两个 PUB socket 传入 fan-out 流程;随后分别从两个 subscriber 接收消息,断言其
cmd_id 和 payload 均正确且一致,覆盖第二个端点的实际转发行为。
🪄 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: CHILL

Plan: Pro Plus

Run ID: 49cda069-14e1-434c-af74-156f29f6615b

📥 Commits

Reviewing files that changed from the base of the PR and between a1e11ce and ecb8118.

📒 Files selected for processing (7)
  • AGENTS.md
  • docs/data-flow.md
  • src/app/mod.rs
  • src/runtime/mod.rs
  • src/services/script_runner.rs
  • src/zmq/zmq.rs
  • tests/runtime/zmq.rs

Comment thread docs/data-flow.md
Comment thread src/zmq/zmq.rs Outdated

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

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/runtime/zmq.rs`:
- Around line 443-451: Update test_zmq_pub_fans_out_to_all_sockets to replace
both fixed thread::sleep waits with deterministic subscription-readiness
synchronization, using XPUB subscription events to confirm both SUB sockets are
registered before sending IDX_GAME_STATE. Preserve the existing single-send
behavior and subsequent receives from sub_a and sub_b.
🪄 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: CHILL

Plan: Pro Plus

Run ID: fc385792-f004-4957-bed3-3fa6a8758d46

📥 Commits

Reviewing files that changed from the base of the PR and between 111224a and 9b9f560.

📒 Files selected for processing (4)
  • docs/data-flow.md
  • src/services/script_runner.rs
  • src/zmq/zmq.rs
  • tests/runtime/zmq.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/services/script_runner.rs
  • src/zmq/zmq.rs
  • docs/data-flow.md

Comment thread tests/runtime/zmq.rs
Comment on lines +443 to +451
thread::sleep(Duration::from_millis(50));

tx.send(IDX_GAME_STATE).unwrap();
thread::sleep(Duration::from_millis(100));

let mut buf_a = zmq2::Message::new();
let mut buf_b = zmq2::Message::new();
sub_a.recv(&mut buf_a, 0).unwrap();
sub_b.recv(&mut buf_b, 0).unwrap();

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)zmq\.rs$|runtime' | head -200

echo "== target file outline/size =="
wc -l tests/runtime/zmq.rs
ast-grep outline tests/runtime/zmq.rs --view compact || true

echo "== relevant section =="
sed -n '380,470p' tests/runtime/zmq.rs

echo "== search zmq pub/sub start functions =="
rg -n "zmq_start_pub|zmq_start_sub|XPUB|setsockopt|subscribe|send\\(" tests/runtime/zmq.rs src runtime 2>/dev/null || true

Repository: Alliance-Algorithm/radar-egui

Length of output: 12127


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== zmq implementation =="
sed -n '1,220p' src/zmq/zmq.rs

echo "== helper functions =="
sed -n '1,80p' tests/runtime/zmq.rs
sed -n '260,310p' tests/runtime/zmq.rs
sed -n '320,375p' tests/runtime/zmq.rs

echo "== deterministic recv semantics probe =="
python3 - <<'PY'
from pathlib import Path
p = Path('src/zmq/zmq.rs')
text = p.read_text()
checks = {
    'zmq_start_pub sends once after notification': 'payloads.push(payload);\n                                    while let Some(msg) = pub_rx.try_recv() {' in text or 'pub_rx.try_recv()' in text,
    'zmq_send sends with nonblocking flag': 'pub_socket.send(msg, 0)' in text,
    'sub_socket set empty subscribe': 'sub_socket.set_subscribe(b"")?' in text,
    'fanout test publishes after 50ms sleep': 'thread::sleep(Duration::from_millis(50));' in Path('tests/runtime/zmq.rs').read_text(),
    'fanout test publishes once': 'tx.send(IDX_GAME_STATE).unwrap();' in Path('tests/runtime/zmq.rs').read_text().split('fn test_zmq_pub_fans_out_to_all_sockets')[1].split('stop.store')[0],
}
for k,v in checks.items():
    print(f'{k}: {v}')

# Check ZeroMQ PUB/SUB semantics from installed docs/pkg? Read-only best-effort local package metadata only when present.
PY

Repository: Alliance-Algorithm/radar-egui

Length of output: 15958


🌐 Web query:

ZeroMQ PUB SUB subscription propagation PUB drop messages if no subscribers documentation

💡 Result:

In ZeroMQ, the PUB socket pattern is designed for high-performance, transient event distribution rather than reliable messaging [1][2]. Regarding your specific questions about message drops and subscription propagation: Message Drops with No Subscribers If a PUB socket has no connected subscribers, it will silently drop all messages sent to it [3][4][5]. The socket does not buffer these messages internally for future subscribers [5]. Once a connection is established, the PUB socket maintains an outgoing message queue for that subscriber, but messages are only queued if the subscriber is connected (or has been connected) and falls behind [1][2][5]. Subscription Propagation and Missed Messages Even when subscribers are present, you may experience message loss during the connection phase [6][3]. This occurs because: 1. Asynchronous Connection: The connection process is asynchronous [6][7]. When a subscriber connects to a publisher, there is a delay while the subscription information (the topic filter) is exchanged [7]. If the publisher sends messages immediately after the connection is initiated but before the subscription handshake completes, those messages may be lost [6][7][3]. 2. Publisher-Side Filtering: In ZeroMQ (v3.x and later), filtering is performed on the publisher side [8][9]. For the publisher to filter correctly, it must have received the subscription command from the subscriber [8][7]. 3. Connection Order: A common issue arises when a PUB socket connects to a SUB socket (rather than the SUB connecting to the PUB) [6][7]. Because the SUB must send its subscription to the PUB, and the connection is asynchronous, the PUB may begin sending messages before it knows the SUB's subscription requirements [6][7]. Mitigation Strategies * Synchronization: To avoid missing the first messages, applications often implement a "side-channel" or use socket monitoring (e.g., ZMQ_EVENT_HANDSHAKE_SUCCEEDED) to ensure the subscriber is fully connected and the subscription has been registered before the publisher begins sending critical data [7][5]. However, even with these events, perfect synchronization can be difficult [7]. * Idempotency and Re-publishing: Because PUB/SUB is inherently unreliable, reliable messaging should be handled at the application level [3][10]. This often involves assigning IDs to messages and having subscribers request missed data or having publishers periodically re-publish state [8][4]. * Architectural Choice: If guaranteed delivery is required, PUB/SUB is generally not the appropriate pattern; consider other patterns (like PUSH/PULL) or implementing a custom reliability layer [3][10]. Top results: [1], [6], [7], [3], [5]

Citations:


使用订阅就绪同步替代固定等待。

test_zmq_pub_fans_out_to_all_sockets 第 443 行和第 446 行的固定等待不能保证两个 SUB 的订阅事件已到达 PUB。零MQ 的订阅传播是异步且可能丢失首条消息,这里发出后不再重发的 IDX_GAME_STATE 可能被丢弃,导致测试间歇失败。发送 IDX_GAME_STATE 前,请通过 XPUB 订阅事件等确定性机制等待订阅就绪。

🤖 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/runtime/zmq.rs` around lines 443 - 451, Update
test_zmq_pub_fans_out_to_all_sockets to replace both fixed thread::sleep waits
with deterministic subscription-readiness synchronization, using XPUB
subscription events to confirm both SUB sockets are registered before sending
IDX_GAME_STATE. Preserve the existing single-send behavior and subsequent
receives from sub_a and sub_b.

@yukikaze223344
yukikaze223344 merged commit 95dd2dc into main Aug 1, 2026
3 of 5 checks passed
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