Skip to content

Core/FFI: MonitorClient for MONITOR command#5977

Open
affonsov wants to merge 2 commits into
mainfrom
affonsov/monitor-core
Open

Core/FFI: MonitorClient for MONITOR command#5977
affonsov wants to merge 2 commits into
mainfrom
affonsov/monitor-core

Conversation

@affonsov
Copy link
Copy Markdown
Collaborator

@affonsov affonsov commented May 19, 2026

Summary

Adds a dedicated MonitorClient to glide-core and exposes it via FFI for language client bindings.

Issue link

This Pull Request is linked to issue: Implement MONITOR command: MonitorClient, FFI bindings, and language client wrappers
Closes #5978

Features / Behaviour Changes

  • MonitorClient in glide-core/src/client/monitor_client.rs: dedicated non-pooled connection using redis::aio::Monitor, forces RESP2, streams parsed MonitorLine structs via callback
  • MonitorLine { timestamp, db, client_addr, command, args } with parse() from raw monitor line strings
  • MonitorLineCallback = Arc<dyn Fn(MonitorLine) + Send + Sync> for Rust consumers
  • FFI exports: create_monitor_client() and close_monitor_client() in ffi/src/lib.rs
  • FFI MonitorCallback passes individual parsed fields + args_json (JSON array) to C callers
  • Clean shutdown: stop_async(self) awaits background task exit; ManuallyDrop + Runtime::block_on in FFI Drop ensures no use-after-free

Implementation

  • glide-core/src/client/monitor_client.rs (new): MonitorClient, MonitorLine, MonitorLineCallback
  • glide-core/src/client/mod.rs: pub mod monitor_client; pub use monitor_client::MonitorClient;
  • ffi/src/lib.rs: create_monitor_client, close_monitor_client, MonitorAdapter
  • glide-core/tests/test_monitor.rs (new): 3 integration tests

Limitations

  • MONITOR is standalone-only (cluster mode not supported)
  • No auto-reconnect on connection drop (stream ends, caller must restart)
  • Uses deprecated get_async_monitor() — only available path for a dedicated non-pooled connection

Testing

  • test_monitor_start_and_receive_line: connects monitor, issues SET, asserts all 5 parsed fields
  • test_monitor_stop_no_lines_after_stop: calls stop_async().await, issues post-stop command, asserts no new lines
  • test_monitor_stop_idempotent: verifies double-stop doesn't panic

Checklist

  • This Pull Request is related to one issue.
  • Commit message has a detailed description of what changed and why.
  • Tests are added or updated.
  • CHANGELOG.md and documentation files are updated.
  • Linters have been run.
  • Destination branch is correct - main or release
  • Create merge commit if merging release branch into main, squash otherwise.

- glide-core/src/client/monitor_client.rs: dedicated non-pooled MonitorClient
  using redis::aio::Monitor, streams lines via mpsc channel, stop() via oneshot
- glide-core/src/client/mod.rs: pub mod monitor_client + re-export MonitorClient
- ffi/src/lib.rs: create_monitor_client() and close_monitor_client() C exports
- glide-core/tests/test_monitor.rs: integration tests for start, receive, stop

Signed-off-by: affonsov <67347924+affonsov@users.noreply.github.com>
@affonsov affonsov force-pushed the affonsov/monitor-core branch from e165aff to 50f6844 Compare May 20, 2026 01:05
@affonsov affonsov changed the title glide-core + FFI: MonitorClient for MONITOR command Core/FFI: MonitorClient for MONITOR command May 20, 2026
- create_monitor_client now reads address/tls/auth directly from the
  protobuf ConnectionRequest before .into() conversion, avoiding
  access to fields absent in the mock-glide-core stub
- adds MonitorClient, MonitorLine, MonitorLineCallback stubs to
  mock-glide-core/src/client.rs for miri-test compilation
- adds NodeAddress/TlsMode internal-type stubs to mock client module
- adds ProtocolVersion and RedisConnectionInfo stubs to mock-redis

Signed-off-by: affonsov <67347924+affonsov@users.noreply.github.com>
@affonsov affonsov marked this pull request as ready for review May 23, 2026 02:16
@affonsov affonsov requested a review from a team as a code owner May 23, 2026 02:16
@yipin-chen yipin-chen requested a review from jduo May 25, 2026 23:41
.expect("MonitorClient::new failed");

monitor.stop();
monitor.stop(); // must not panic
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

duplicate stop?

assert!(!set_line.client_addr.is_empty());
assert!(set_line.timestamp > 0.0);

monitor.stop();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should this be stop_async()?

Comment thread ffi/src/lib.rs
// Convert to internal ConnectionRequest (needed for the runtime type alias only).
let _connection_request: ConnectionRequest = connection_request.into();

let runtime = match Builder::new_multi_thread().enable_all().build() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we truly need a new multi-thread runtime for each monitor? I only see it used with block_on. Could we get away with using new_current_thread()?

Should this depend on if the client is sync or async (or does that even have meaning for a monitor?)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I see, it's callback based so new_current_thread() wouldn't work here. Is there any relationship between the MonitorClient and GlideClient or GlideClusterClient? The Glide clients already have a background runtime that this work can be done on, but it doesn't seem like you have to create one to use a monitor.

In practice, is someone using a monitor going to need a Glide client too though?

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.

Implement MONITOR command: MonitorClient, FFI bindings, and language client wrappers

3 participants