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
//! Rust client SDK for [Oxia](https://github.com/oxia-db/oxia), a scalable
//! metadata store and coordination system.
//!
//! The entry point is [`OxiaClient`]. Every operation returns a request builder:
//! chain options onto it and `.await` it directly.
//!
//! ```no_run
//! use oxia::{ComparisonType, OxiaClient};
//!
//! # async fn example() -> Result<(), oxia::OxiaError> {
//! let client = OxiaClient::connect("localhost:6648").await?;
//!
//! // Plain put/get.
//! let res = client.put("greeting", "hello").await?;
//! let rec = client.get("greeting").await?;
//! assert_eq!(rec.value.as_deref(), Some(b"hello".as_ref()));
//!
//! // Options chain onto the builder.
//! client
//! .put("config/a", "1")
//! .expected_version_id(res.version.version_id)
//! .await?;
//! client.put("locks/w1", "").ephemeral().await?;
//! let floor = client.get("config/z").comparison(ComparisonType::Floor).await?;
//!
//! // Range operations, as a whole result or as an ordered stream.
//! let keys = client.list("config/", "config/~").await?;
//! let mut scan = client.range_scan("config/", "config/~").stream().await?;
//! # let _ = (floor, keys, scan);
//! client.close().await?;
//! # Ok(())
//! # }
//! ```
//!
//! # Concepts
//!
//! - **Records** are key/value pairs with a [`Version`] carrying the record's
//! version id and timestamps; conditional operations
//! ([`expected_version_id`](PutBuilder::expected_version_id)) implement
//! compare-and-swap.
//! - **Ephemeral records** ([`PutBuilder::ephemeral`]) live as long as the
//! client's session and are removed automatically when it closes or expires.
//! - **Partition keys** ([`PutBuilder::partition_key`]) co-locate related
//! records on one shard, enabling atomic multi-record batches and
//! server-generated **sequential keys**
//! ([`PutBuilder::sequence_key_deltas`], [`OxiaClient::sequence_updates`]).
//! - **Secondary indexes** ([`PutBuilder::secondary_index`]) provide alternate
//! query paths for gets, lists and scans
//! ([`GetBuilder::use_index`], [`ListBuilder::use_index`]).
//! - **Notifications** ([`OxiaClient::notifications`]) stream every change
//! applied to the database.
//!
//! Keys are sorted with Oxia's slash-aware order (`/`-separated path segments),
//! not plain lexicographic order; range boundaries follow it.
//!
//! # Error handling
//!
//! Every operation returns [`OxiaError`]. Semantic outcomes callers commonly
//! match on are dedicated variants ([`OxiaError::KeyNotFound`],
//! [`OxiaError::UnexpectedVersionId`], …); transient infrastructure failures
//! answer `true` to [`OxiaError::is_retryable`] and are safe to retry —
//! idempotent operations unconditionally, non-idempotent ones (puts without a
//! version condition) with application-level judgment. Each operation on
//! [`OxiaClient`] documents the errors it can produce.
//!
//! The client retries retryable failures internally — re-routing via the
//! leader hints the server attaches to routing errors, re-hashing operations
//! onto the new shard when a shard is split or merged, with exponential
//! backoff, bounded by the request timeout — so the errors you observe are
//! post-retry. One consequence, shared with the reference clients: a write
//! whose batch failed *after* reaching the wire may be retried even though the
//! server already applied it, so unconditional writes have at-least-once
//! semantics under retries; version-conditioned writes are exactly-once.
//!
//! # Cancellation
//!
//! Dropping an operation's future stops waiting but does not recall an
//! operation already submitted to a batch; it may still execute on the
//! server. The `recv` methods on [`Notifications`] and [`SequenceUpdates`]
//! are cancel-safe.
// A panic on wire data must never take down the caller's process: forbid
// `.unwrap()` in library code so every fallible result is handled. Unit tests
// (compiled with `cfg(test)`) are exempt, where unwrapping is the idiom.
pub
pub use Bytes;
pub use OxiaClient;
pub use OxiaClientBuilder;
pub use OxiaError;
pub use ;
pub use ;
pub use ;