Skip to main content

BatchIsolation

Trait BatchIsolation 

Source
pub trait BatchIsolation: SavepointOperation {
    // Provided methods
    fn run_isolated<'a, T, V, E, F>(
        &'a mut self,
        items: &'a [T],
        f: F,
    ) -> impl Future<Output = Result<Vec<Result<V, E>>, Fault<Profile<{ false }, { true }, { true }>>>> + 'a
       where T: 'a,
             V: 'a,
             E: 'a,
             F: AsyncFnOnce(&mut SavepointOp<'_>, &T) -> Result<V, E> + Clone + Sync + 'a { ... }
    fn run_bisected<'a, T, E, F>(
        &'a mut self,
        items: &'a [T],
        budget: BisectBudget,
        f: F,
    ) -> impl Future<Output = Result<BisectOutcomes<E>, Fault<Profile<{ false }, { true }, { true }>>>> + 'a
       where T: 'a,
             E: Error + 'static,
             F: AsyncFnOnce(&mut SavepointOp<'_>, &[T]) -> Result<(), E> + Clone + Sync + 'a { ... }
    fn run_bisected_with<'a, T, E, F, P>(
        &'a mut self,
        items: &'a [T],
        budget: BisectBudget,
        policy: TransientPolicy<P>,
        f: F,
    ) -> impl Future<Output = Result<BisectOutcomes<E>, Fault<Profile<{ false }, { true }, { true }>>>> + 'a
       where T: 'a,
             E: Display + 'a,
             P: Fn(&E) -> bool + 'a,
             F: AsyncFnOnce(&mut SavepointOp<'_>, &[T]) -> Result<(), E> + Clone + Sync + 'a { ... }
}
Expand description

Batch isolation for every AtomicOperation.

Blanket-implemented, like SavepointOperation, so DbOp, SavepointOp (nesting), HookOperation, and operation types defined outside this crate all get it without naming a concrete type — and so a function generic over impl AtomicOperation can use it.

Provided Methods§

Source

fn run_isolated<'a, T, V, E, F>( &'a mut self, items: &'a [T], f: F, ) -> impl Future<Output = Result<Vec<Result<V, E>>, Fault<Profile<{ false }, { true }, { true }>>>> + 'a
where T: 'a, V: 'a, E: 'a, F: AsyncFnOnce(&mut SavepointOp<'_>, &T) -> Result<V, E> + Clone + Sync + 'a,

Runs f once per item, each inside its own SAVEPOINT, in item order.

A failing item unwinds only its own writes and staged hooks; the transaction stays usable and the loop continues, so its healthy batch-mates still commit. Outcomes are returned positionally: one entry per input, f’s own Ok/Err preserved.

The outer Err means the savepoint machinery itself failed, leaving the enclosing transaction in an indeterminate state: abandon it. The sqlx::Error is classified by errlanes’ sqlx lane table, so a lost connection or a deadlock on the savepoint statement itself arrives as Transient — retry the whole transaction — and anything else as Fatal.

Source

fn run_bisected<'a, T, E, F>( &'a mut self, items: &'a [T], budget: BisectBudget, f: F, ) -> impl Future<Output = Result<BisectOutcomes<E>, Fault<Profile<{ false }, { true }, { true }>>>> + 'a
where T: 'a, E: Error + 'static, F: AsyncFnOnce(&mut SavepointOp<'_>, &[T]) -> Result<(), E> + Clone + Sync + 'a,

Probes the whole slice at once, bisecting only on failure.

The happy path costs one probe. On failure the slice splits and pending ranges are probed largest-first (earliest start breaking ties) until budget is spent, so clean siblings are salvaged and a culprit resolves from its own single-item probe, where its error is attributable to it.

Deadlock victims and serialization failures re-probe the same range unsplit and are refunded to the budget — see TransientPolicy. Use run_bisected_with to widen that class.

Source

fn run_bisected_with<'a, T, E, F, P>( &'a mut self, items: &'a [T], budget: BisectBudget, policy: TransientPolicy<P>, f: F, ) -> impl Future<Output = Result<BisectOutcomes<E>, Fault<Profile<{ false }, { true }, { true }>>>> + 'a
where T: 'a, E: Display + 'a, P: Fn(&E) -> bool + 'a, F: AsyncFnOnce(&mut SavepointOp<'_>, &[T]) -> Result<(), E> + Clone + Sync + 'a,

run_bisected with a caller-supplied notion of which failures are transient.

Classification being the caller’s, the error bound here is just Display.

The outer Err is the search’s own failure, never one of f’s: the savepoint machinery failed (classified as in run_isolated), or the transient allowance ran out before anything could be attributed to a range — Fatal(Exhausted), since the retries have already been spent here; the caller re-runs the whole batch later rather than automatically.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§