Skip to main content

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}