Skip to content

Commit 387fd7d

Browse files
committed
RSCBC-243: Add API docs for the couchbase crate
1 parent 318ff2c commit 387fd7d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+3678
-57
lines changed

sdk/couchbase-core/src/retry.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,28 +38,53 @@ lazy_static! {
3838
Arc::new(FailFastRetryStrategy::default());
3939
}
4040

41+
/// The reason an operation is being retried.
42+
///
43+
/// Each variant identifies a specific transient failure condition that triggered
44+
/// a retry. The SDK passes this to [`RetryStrategy::retry_after`] so the strategy
45+
/// can decide whether (and how long) to wait before retrying.
4146
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4247
#[non_exhaustive]
4348
pub enum RetryReason {
49+
/// The server indicated the vBucket is not owned by this node.
4450
KvNotMyVbucket,
51+
/// The vBucket map is invalid and must be refreshed.
4552
KvInvalidVbucketMap,
53+
/// A temporary failure occurred on the KV engine.
4654
KvTemporaryFailure,
55+
/// The collection ID is outdated and must be re-resolved.
4756
KvCollectionOutdated,
57+
/// The server error map indicated the operation should be retried.
4858
KvErrorMapRetryIndicated,
59+
/// The document is locked by another operation.
4960
KvLocked,
61+
/// A sync-write (durable operation) is already in progress on this key.
5062
KvSyncWriteInProgress,
63+
/// A sync-write recommit is in progress on this key.
5164
KvSyncWriteRecommitInProgress,
65+
/// The required service is temporarily unavailable.
5266
ServiceNotAvailable,
67+
/// The connection was closed while the request was in flight.
5368
SocketClosedWhileInFlight,
69+
/// No connection is currently available.
5470
SocketNotAvailable,
71+
/// A prepared statement for the query was invalidated.
5572
QueryPreparedStatementFailure,
73+
/// The query index was not found (may still be building).
5674
QueryIndexNotFound,
75+
/// The search service is rejecting requests due to rate limiting.
5776
SearchTooManyRequests,
77+
/// An HTTP request failed to send.
5878
HttpSendRequestFailed,
79+
/// The SDK is not yet ready to perform the operation.
5980
NotReady,
6081
}
6182

6283
impl RetryReason {
84+
/// Returns `true` if this reason allows retrying non-idempotent operations.
85+
///
86+
/// Most retry reasons are safe for non-idempotent retries because the
87+
/// server never processed the original request.
6388
pub fn allows_non_idempotent_retry(&self) -> bool {
6489
matches!(
6590
self,
@@ -81,6 +106,8 @@ impl RetryReason {
81106
)
82107
}
83108

109+
/// Returns `true` if the SDK should always retry for this reason,
110+
/// regardless of the retry strategy's decision.
84111
pub fn always_retry(&self) -> bool {
85112
matches!(
86113
self,
@@ -118,26 +145,70 @@ impl Display for RetryReason {
118145
}
119146
}
120147

148+
/// The action a [`RetryStrategy`] returns to indicate when to retry.
149+
///
150+
/// Contains the [`Duration`] to wait before the next retry attempt.
121151
#[derive(Clone, Debug)]
122152
pub struct RetryAction {
153+
/// How long to wait before retrying.
123154
pub duration: Duration,
124155
}
125156

126157
impl RetryAction {
158+
/// Creates a new `RetryAction` with the given backoff duration.
127159
pub fn new(duration: Duration) -> Self {
128160
Self { duration }
129161
}
130162
}
131163

164+
/// A strategy that decides whether and when to retry a failed operation.
165+
///
166+
/// Implement this trait to provide custom retry behavior. The SDK calls
167+
/// [`retry_after`](RetryStrategy::retry_after) each time a retryable failure
168+
/// occurs, passing the request metadata and the reason for the failure.
169+
///
170+
/// Return `Some(RetryAction)` to retry after the specified duration,
171+
/// or `None` to stop retrying and propagate the error.
172+
///
173+
/// # Example
174+
///
175+
/// ```rust
176+
/// use couchbase_core::retry::{RetryStrategy, RetryAction, RetryRequest, RetryReason};
177+
/// use std::fmt::Debug;
178+
/// use std::time::Duration;
179+
///
180+
/// #[derive(Debug)]
181+
/// struct FixedDelayRetry(Duration);
182+
///
183+
/// impl RetryStrategy for FixedDelayRetry {
184+
/// fn retry_after(&self, request: &RetryRequest, reason: &RetryReason) -> Option<RetryAction> {
185+
/// if request.retry_attempts < 3 {
186+
/// Some(RetryAction::new(self.0))
187+
/// } else {
188+
/// None // give up after 3 attempts
189+
/// }
190+
/// }
191+
/// }
192+
/// ```
132193
pub trait RetryStrategy: Debug + Send + Sync {
194+
/// Decides whether to retry an operation and how long to wait.
195+
///
196+
/// * `request` — Metadata about the in-flight request (attempt count, idempotency, etc.).
197+
/// * `reason` — Why the operation failed.
198+
///
199+
/// Return `Some(RetryAction)` to retry, or `None` to stop.
133200
fn retry_after(&self, request: &RetryRequest, reason: &RetryReason) -> Option<RetryAction>;
134201
}
135202

203+
/// Metadata about a request that is being considered for retry.
136204
#[derive(Clone, Debug)]
137205
pub struct RetryRequest {
138206
pub(crate) operation: &'static str,
207+
/// Whether the operation is idempotent (safe to retry without side effects).
139208
pub is_idempotent: bool,
209+
/// The number of retry attempts that have already been made.
140210
pub retry_attempts: u32,
211+
/// The set of reasons this request has been retried so far.
141212
pub retry_reasons: HashSet<RetryReason>,
142213
pub(crate) unique_id: Option<String>,
143214
}

sdk/couchbase-core/src/retrybesteffort.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ use std::time::Duration;
2121

2222
use crate::retry::{RetryAction, RetryReason, RetryRequest, RetryStrategy};
2323

24+
/// A retry strategy that retries all eligible operations using a configurable
25+
/// backoff calculator.
26+
///
27+
/// This is the default retry strategy used by the SDK. It retries idempotent
28+
/// operations unconditionally, and non-idempotent operations only when the
29+
/// [`RetryReason`] indicates it is safe to do so.
30+
///
31+
/// The backoff duration between retries is determined by the [`BackoffCalculator`]
32+
/// provided at construction time. If none is specified, an
33+
/// [`ExponentialBackoffCalculator`] with sensible defaults is used.
34+
///
35+
/// # Example
36+
///
37+
/// ```rust
38+
/// use couchbase_core::retrybesteffort::BestEffortRetryStrategy;
39+
/// use std::sync::Arc;
40+
///
41+
/// // Use the default exponential backoff:
42+
/// let strategy = Arc::new(BestEffortRetryStrategy::default());
43+
/// ```
2444
#[derive(Debug, Clone)]
2545
pub struct BestEffortRetryStrategy<Calc> {
2646
backoff_calc: Calc,
@@ -30,6 +50,7 @@ impl<Calc> BestEffortRetryStrategy<Calc>
3050
where
3151
Calc: BackoffCalculator,
3252
{
53+
/// Creates a new `BestEffortRetryStrategy` with the given backoff calculator.
3354
pub fn new(calc: Calc) -> Self {
3455
Self { backoff_calc: calc }
3556
}
@@ -56,10 +77,48 @@ where
5677
}
5778
}
5879

80+
/// A calculator that determines the backoff duration between retry attempts.
81+
///
82+
/// Implement this trait to provide custom backoff logic. The SDK ships with
83+
/// [`ExponentialBackoffCalculator`] as the default implementation.
5984
pub trait BackoffCalculator: Debug + Send + Sync {
85+
/// Returns the duration to wait before the given retry attempt number.
86+
///
87+
/// `retry_attempts` starts at 0 for the first retry.
6088
fn backoff(&self, retry_attempts: u32) -> Duration;
6189
}
6290

91+
/// An exponential backoff calculator that increases the delay between retries
92+
/// exponentially, clamped between a minimum and maximum duration.
93+
///
94+
/// The backoff for attempt `n` is calculated as:
95+
///
96+
/// ```text
97+
/// clamp(min * backoff_factor ^ n, min, max)
98+
/// ```
99+
///
100+
/// # Defaults
101+
///
102+
/// | Parameter | Default |
103+
/// |-----------|---------|
104+
/// | `min` | 1 ms |
105+
/// | `max` | 1000 ms |
106+
/// | `backoff_factor` | 2.0 |
107+
///
108+
/// # Example
109+
///
110+
/// ```rust
111+
/// use couchbase_core::retrybesteffort::{BestEffortRetryStrategy, ExponentialBackoffCalculator};
112+
/// use std::time::Duration;
113+
/// use std::sync::Arc;
114+
///
115+
/// let calc = ExponentialBackoffCalculator::new(
116+
/// Duration::from_millis(5), // min
117+
/// Duration::from_millis(500), // max
118+
/// 2.0, // backoff_factor
119+
/// );
120+
/// let strategy = Arc::new(BestEffortRetryStrategy::new(calc));
121+
/// ```
63122
#[derive(Clone, Debug)]
64123
pub struct ExponentialBackoffCalculator {
65124
min: Duration,
@@ -68,6 +127,11 @@ pub struct ExponentialBackoffCalculator {
68127
}
69128

70129
impl ExponentialBackoffCalculator {
130+
/// Creates a new `ExponentialBackoffCalculator`.
131+
///
132+
/// * `min` — Minimum backoff duration (floor).
133+
/// * `max` — Maximum backoff duration (ceiling).
134+
/// * `backoff_factor` — Multiplier applied per retry attempt (typically `2.0`).
71135
pub fn new(min: Duration, max: Duration, backoff_factor: f64) -> Self {
72136
Self {
73137
min,

0 commit comments

Comments
 (0)