laser_wire/clients.rs
1use serde::{Deserialize, Serialize};
2
3/// The discovery read request (`AGDX_GET_CLIENTS_METADATA`). Filtered and
4/// paginated, because a busy server may hold thousands of connections and a
5/// caller must not have to pull them all at once. The server orders connections
6/// by `client_id`, applies the filters, skips past `after_client_id`, and returns
7/// up to `limit` entries plus a cursor when more remain.
8#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
9pub struct ClientMetadataQuery {
10 pub v: u32,
11 /// Only return connections that advertised metadata. The common case for
12 /// discovery, where unannounced connections are noise.
13 #[serde(default, skip_serializing_if = "is_false")]
14 pub with_metadata_only: bool,
15 /// Only return connections authenticated as this principal.
16 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub user_id: Option<u32>,
18 /// Pagination cursor: return only connections whose `client_id` is strictly
19 /// greater than this. `None` starts from the beginning.
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub after_client_id: Option<u32>,
22 /// Max entries to return. Clamped server-side to the page cap.
23 pub limit: u32,
24}
25
26fn is_false(value: &bool) -> bool {
27 !*value
28}
29
30/// One connection's discovery record: the connection identity the streaming
31/// server holds plus the opaque metadata the client advertised. A LaserData-owned
32/// type, deliberately distinct from the upstream Apache Iggy `ClientInfo` (which
33/// stays byte-identical so an Apache Iggy SDK keeps working against LaserData
34/// Cloud). The metadata is opaque: an agent advertises its card, a regular app
35/// sets any blob the consumer interprets.
36#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
37pub struct ClientMetadata {
38 pub client_id: u32,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub user_id: Option<u32>,
41 /// Transport code (1 Tcp, 2 Quic, 3 Http, 4 WebSocket), the same dictionary
42 /// the upstream binding uses.
43 pub transport: u8,
44 pub address: String,
45 pub consumer_groups_count: u32,
46 #[serde(
47 default,
48 skip_serializing_if = "Option::is_none",
49 with = "crate::encoding::opt_bin_bytes"
50 )]
51 pub metadata: Option<Vec<u8>>,
52}
53
54/// The reply to `AGDX_GET_CLIENTS_METADATA`: one page of connections with their
55/// advertised metadata, plus `next_cursor` (the last `client_id` in the page) when
56/// more connections remain, so the caller pages by passing it as the next
57/// `after_client_id`. `None` means the last page.
58#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
59pub struct ClientMetadataList {
60 pub clients: Vec<ClientMetadata>,
61 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub next_cursor: Option<u32>,
63}