Skip to content

feat(ipc): poll agent snapshots#300

Merged
AprilNEA merged 2 commits into
masterfrom
feat/agent-snapshot-rpc
Jun 21, 2026
Merged

feat(ipc): poll agent snapshots#300
AprilNEA merged 2 commits into
masterfrom
feat/agent-snapshot-rpc

Conversation

@AprilNEA

Copy link
Copy Markdown
Owner

Summary

  • add AgentSnapshot and append a v4 snapshot RPC to the tarpc Agent service
  • return inventory health and inventory from one orchestrator-state read on the agent
  • update the GUI IPC poll loop to use snapshot() instead of separate status()+inventory() RPCs
  • pin the new protocol version and request variant in wire-format tests

Validation

  • cargo fmt --check
  • cargo test -p openlogi-agent-core -p openlogi-agent -p openlogi-gui
  • cargo clippy -p openlogi-agent-core -p openlogi-agent -p openlogi-gui --all-targets -- -D warnings
  • pre-push cargo clippy --workspace --all-targets -- -D warnings

Stacked on #299.

@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR consolidates the two-round GUI poll (status() + inventory()) into a single atomic snapshot() RPC, eliminating the race where an inventory-ready event could land between the two calls and pair a stale inventory with a newer health flag.

  • ipc.rs: Adds AgentSnapshot { status, inventory }, appends snapshot() to the Agent tarpc trait, and bumps PROTOCOL_VERSION to 4.
  • server.rs: Implements snapshot() by taking one orchestrator lock and reading launch_at_login, inventory_health, and inventory in the same critical section — the atomicity the old two-RPC pattern couldn't provide.
  • ipc_client.rs: Replaces the sequential status()/inventory() calls in poll() with a single client.snapshot() call; the pacing and reconnect logic is unchanged.
  • wire_format.rs: Pins the new PROTOCOL_VERSION = 4, asserts AgentRequest::Snapshot {} encodes as variant 0x0e, and adds a golden-bytes test for AgentSnapshot.

Confidence Score: 5/5

Safe to merge — the change is a straightforward consolidation of two RPCs into one, with no removal of existing methods and the protocol version bump correctly guarded by wire-format golden tests.

The atomicity fix is correct: launch_at_login, inventory_health, and inventory are all read under a single orchestrator lock. Fields outside the orchestrator (accessibility_granted, hook_installed) are handled the same way as the pre-existing status() method. The wire format is fully pinned by golden-byte tests, and snapshot() is properly appended as variant 0x0e without disturbing any existing variant indices. The old status() and inventory() methods remain in the trait, preserving compatibility.

No files require special attention.

Important Files Changed

Filename Overview
crates/openlogi-agent-core/src/ipc.rs Adds AgentSnapshot struct and snapshot() trait method; bumps PROTOCOL_VERSION to 4; method is correctly appended at the end preserving wire-format order.
crates/openlogi-agent/src/server.rs Implements snapshot() under a single orchestrator lock; correctly matches the existing status() pattern for fields outside orchestrator state (accessibility, hook_installed).
crates/openlogi-gui/src/ipc_client.rs Replaces the two-step status()+inventory() poll with a single snapshot() call; pacing, reconnect, and error handling logic is unchanged and correct.
crates/openlogi-agent-core/tests/wire_format.rs Pins PROTOCOL_VERSION=4, verifies Snapshot variant index 0x0e, and adds a golden-bytes test for AgentSnapshot; golden bytes are consistent with the AgentStatus golden plus a varint-0 empty vec.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant GUI as GUI (ipc_client.rs)
    participant Agent as Agent (server.rs)
    participant Orch as Orchestrator

    Note over GUI,Agent: Before (v3) - two separate RPCs
    GUI->>Agent: status()
    Agent->>Orch: lock - launch_at_login, inventory_health
    Orch-->>Agent: values
    Agent-->>GUI: AgentStatus
    Note over Orch: enumeration can land here
    GUI->>Agent: inventory()
    Agent->>Orch: lock - inventory list
    Orch-->>Agent: list
    Agent-->>GUI: DeviceInventory list
    Note over GUI: may pair stale health with fresh list

    Note over GUI,Agent: After (v4) - single atomic RPC
    GUI->>Agent: snapshot()
    Agent->>Orch: lock - launch_at_login + inventory_health + inventory
    Orch-->>Agent: all three from same lock
    Agent-->>GUI: AgentSnapshot
    Note over GUI: health and list always consistent
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant GUI as GUI (ipc_client.rs)
    participant Agent as Agent (server.rs)
    participant Orch as Orchestrator

    Note over GUI,Agent: Before (v3) - two separate RPCs
    GUI->>Agent: status()
    Agent->>Orch: lock - launch_at_login, inventory_health
    Orch-->>Agent: values
    Agent-->>GUI: AgentStatus
    Note over Orch: enumeration can land here
    GUI->>Agent: inventory()
    Agent->>Orch: lock - inventory list
    Orch-->>Agent: list
    Agent-->>GUI: DeviceInventory list
    Note over GUI: may pair stale health with fresh list

    Note over GUI,Agent: After (v4) - single atomic RPC
    GUI->>Agent: snapshot()
    Agent->>Orch: lock - launch_at_login + inventory_health + inventory
    Orch-->>Agent: all three from same lock
    Agent-->>GUI: AgentSnapshot
    Note over GUI: health and list always consistent
Loading

Reviews (3): Last reviewed commit: "docs(gui): wrap IPC client module commen..." | Re-trigger Greptile

Comment thread crates/openlogi-agent-core/src/ipc.rs
Comment thread crates/openlogi-gui/src/ipc_client.rs Outdated
@AprilNEA AprilNEA force-pushed the fix/hidpp-listener-lifecycle branch from f5e0d10 to 23daf93 Compare June 21, 2026 07:39
@AprilNEA AprilNEA force-pushed the feat/agent-snapshot-rpc branch from d2677a7 to 6692194 Compare June 21, 2026 07:40
@AprilNEA

AprilNEA commented Jun 21, 2026

Copy link
Copy Markdown
Owner Author

Review follow-up: wrapped the IPC client module comment. I checked the suggested PartialEq/Eq derive for AgentSnapshot, but it does not compile because DeviceInventory intentionally does not currently implement equality; adding equality across the full device model would be a broader API change, so I left the snapshot derives unchanged.

Base automatically changed from fix/hidpp-listener-lifecycle to master June 21, 2026 08:05
@AprilNEA AprilNEA force-pushed the feat/agent-snapshot-rpc branch from 6692194 to 2844f55 Compare June 21, 2026 08:07
@AprilNEA AprilNEA merged commit 90e7326 into master Jun 21, 2026
7 of 8 checks passed
@AprilNEA AprilNEA deleted the feat/agent-snapshot-rpc branch June 21, 2026 08:10
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