1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
//! # Netidx - Real-time data sharing for distributed systems
//!
//! **High-performance pub/sub middleware without the message broker.**
//!
//! Netidx lets you publish and subscribe to live data across your network using a
//! simple, hierarchical namespace. Data flows directly between publishers and
//! subscribers over TCP—no central broker bottleneck.
//!
//! ## Why Netidx?
//!
//! - **Fast**: Direct connections, zero-copy where possible, handles tens of millions
//! of updates/sec
//! - **Discoverable**: Hierarchical namespace like a filesystem, browse and query
//! what exists
//! - **Flexible**: Optional persistence (netidx-container), event logging (netidx-archive)
//! - **Secure**: Built-in Kerberos v5 and TLS with centralized authorization
//! - **Production-tested**: Years in production in financial trading systems
//!
//! ## Quick Start
//!
//! Publishing data:
//!
//! ```no_run
//! # fn get_cpu_temp() -> f32 { 42. }
//! use netidx::{
//! publisher::{PublisherBuilder, Value, BindCfg, DesiredAuth},
//! config::Config, path::Path,
//! };
//! use tokio::time;
//! use std::time::Duration;
//! # use anyhow::Result;
//! # async fn run() -> Result<()> {
//! let cfg = Config::load_default()?;
//! let publisher = PublisherBuilder::new(cfg)
//! .desired_auth(DesiredAuth::Anonymous)
//! .bind_cfg(Some("192.168.0.0/16".parse()?))
//! .build()
//! .await?;
//!
//! let temp = publisher.publish(
//! Path::from("/hw/cpu-temp"),
//! get_cpu_temp()
//! )?;
//!
//! loop {
//! time::sleep(Duration::from_millis(500)).await;
//! let mut batch = publisher.start_batch();
//! temp.update(&mut batch, get_cpu_temp());
//! batch.commit(None).await;
//! }
//! # Ok(()) }
//! ```
//!
//! Subscribing to data:
//!
//! ```no_run
//! use netidx::{
//! subscriber::{Subscriber, UpdatesFlags, DesiredAuth},
//! config::Config, path::Path,
//! };
//! use futures::{prelude::*, channel::mpsc};
//! # use anyhow::Result;
//! # async fn run() -> Result<()> {
//! let cfg = Config::load_default()?;
//! let subscriber = Subscriber::new(cfg, DesiredAuth::Anonymous)?;
//! let temp = subscriber.subscribe(Path::from("/hw/cpu-temp"));
//! temp.wait_subscribed().await;
//!
//! println!("Current: {:?}", temp.last());
//!
//! let (tx, mut rx) = mpsc::channel(10);
//! temp.updates(UpdatesFlags::empty(), tx);
//! while let Some(mut batch) = rx.next().await {
//! for (_, value) in batch.drain(..) {
//! println!("Updated: {:?}", value);
//! }
//! }
//! # Ok(()) }
//! ```
//!
//! ## How It Works
//!
//! Netidx has three components:
//!
//! - **Resolver Server**: Directory service mapping paths to publisher addresses
//! - **Publishers**: Create values and serve subscribers directly
//! - **Subscribers**: Connect directly to publishers for live data
//!
//! Unlike traditional message brokers, the resolver only stores *addresses*, not data.
//! This eliminates the broker as a bottleneck and single point of failure.
//!
//! ## Key Features
//!
//! - **Direct TCP connections** - No broker bottleneck, connection pooling
//! - **Type-safe values** - Rich types including primitives, strings, bytes, arrays, maps
//! - **User-defined types** - Publish your own custom types by implementing a few traits
//! - **Bi-directional** - Subscribers can write values back to publishers
//! - **Durable subscriptions** - Automatic reconnection and state recovery
//! - **Authorization** - Centralized permissions with Kerberos v5 or TLS
//! - **Discovery** - Browse namespace, glob patterns, structural queries
//!
//! ## Optional Components
//!
//! - **[netidx-container](https://docs.rs/netidx-container)** - Redis-like NoSQL storage
//! for persistence and guaranteed delivery
//! - **[netidx-archive](https://docs.rs/netidx-archive)** - Event logging, replay, and
//! tiered storage for historical data
//! - **[netidx-protocols](https://docs.rs/netidx-protocols)** - RPC framework and
//! clustering primitives
//!
//! ## Documentation
//!
//! - [Netidx Book](https://netidx.github.io/netidx-book/) - Complete guide and tutorials
//! - [`Publisher`] - Publish data and accept subscriptions
//! - [`Subscriber`] - Subscribe to live data
//! - [`config::Config`] - Configuration management
//! - [`path::Path`] - Hierarchical path handling
//!
//! ## Architecture
//!
//! Values are transmitted as a reliable, ordered stream over TCP (like the connection
//! itself, but with [`publisher::Value`] as the unit instead of bytes). Published
//! values always have a current value that new subscribers receive immediately, followed
//! by live updates.
//!
//! For best discoverability, structure your data hierarchically with multiple published
//! values rather than complex nested structures. This is both efficient and makes your
//! system browsable.
extern crate serde_derive;
extern crate bitflags;
extern crate anyhow;
extern crate netidx_core;
pub use pack;
pub use path;
pub use utils;
pub use netidx_netproto as protocol;
pub use poolshark as pool;
use Result;
use ;
use ;
/// A self-contained netidx setup for testing or standalone use.
///
/// This will allow the current program to talk to itself (and child processes) over netidx.
/// This is useful for tests, as well as a fallback of last resort when
/// there is no usable netidx config, but a program could still be
/// useful without netidx.
///
/// Note, when you drop this the internal resolver server will shut
/// down and your publisher/subscriber will no longer be usable.