Skip to main content

RemoteRefBatch

Struct RemoteRefBatch 

Source
pub struct RemoteRefBatch<'a> { /* private fields */ }
Expand description

Batched writer for remote-tracking refs (#645): amortises the parent-directory fsync across every ref written into it, instead of paying one per ref like write_remote_ref in a loop.

push/fetch publish one tracking ref per branch (refs/remotes/<remote>/<branch>) in a loop; each individual write_remote_ref call goes through write_atomic’s temp+fsync+rename+dirsync pattern, so N branches cost N serial directory fsyncs even though every write lands under the same refs/remotes/<remote>/ tree. RemoteRefBatch instead:

  1. Self::writes each ref durable-content-before-visible (fsyncs the wire bytes, then renames — same invariant crate::atomic::write_content_synced gives object writes: a reader can never observe a torn file), immediately, one call at a time, deferring only the directory fsync that makes the RENAME itself crash-durable;
  2. Self::commit fsyncs every distinct directory touched, once each, deduplicated — O(distinct directories) instead of O(refs). For the common case (one remote, flat branch names) that is exactly one fsync for the whole batch.

This is deliberately scoped to refs/remotes/* ONLY — see atomic.rs’s module docs for why branch heads (refs/heads/*, write_ref/update_ref) keep the unbatched per-write contract: tracking refs are a locally-cached, recomputable-from-a-re-fetch view of another repository, not a pointer anything else orders against.

§Partial-failure semantics

Best-effort, fail-fast — the same contract crate::batch::WriteBatch::commit documents for the object store’s batched writes. Self::write renames each ref as soon as it validates and its content is durable, so a ref that made it through write is visible to readers immediately, exactly as it would have been under the old per-ref loop. If a later write in the same batch fails (bad name or I/O error), earlier successful writes are not rolled back — content-addressed dedup isn’t in play here, but the same reasoning applies: remote-tracking refs are recomputable, so a partially-applied batch is exactly as safe to retry as the old loop was after failing at the same point. Callers that want the successful prefix to be durable even when the batch as a whole errors out should call Self::commit regardless of whether the write loop returned early (see remote_dispatch::push_all_with / fetch_objects_inner for the pattern).

Implementations§

Source§

impl<'a> RemoteRefBatch<'a>

Source

pub fn new(layout: &'a RepoLayout, remote: &str) -> RefResult<Self>

Start a batch for remote.

§Errors

RefError::InvalidRefName if remote fails validate_ref_name.

Source

pub fn write(&mut self, branch: &str, h: &Hash) -> RefResult<()>

Write one remote-tracking ref: validates branch, fsyncs its wire-encoded content, then renames it into place — visible immediately, same as write_remote_ref. Only the directory fsync (rename durability) is deferred to Self::commit.

§Errors
§Panics

Never in practice: ref_path always produces a path with a parent (it is self.layout.common_dir() joined with at least the remote’s subdirectory and the branch name).

Source

pub fn commit(self) -> RefResult<()>

Fsync every directory touched by a completed Self::write, once each. Idempotent to call on a batch with nothing staged (a no-op). MUST be called after the last write a caller intends to make durable — refs written but never committed are visible but not crash-durable (the rename may not have reached stable storage), the same window crate::store::BulkWriter::commit documents for bulk object writes.

§Errors

RefError::Io on the first directory fsync failure. Directories are synced in sorted order for determinism; a failure partway through leaves the remaining directories un-synced (best-effort, matching Self::write’s partial-failure contract).

Trait Implementations§

Source§

impl<'a> Debug for RemoteRefBatch<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for RemoteRefBatch<'a>

§

impl<'a> RefUnwindSafe for RemoteRefBatch<'a>

§

impl<'a> Send for RemoteRefBatch<'a>

§

impl<'a> Sync for RemoteRefBatch<'a>

§

impl<'a> Unpin for RemoteRefBatch<'a>

§

impl<'a> UnsafeUnpin for RemoteRefBatch<'a>

§

impl<'a> UnwindSafe for RemoteRefBatch<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more