pub struct StateVersions {
pub(crate) cfg: PersistConfig,
pub(crate) consensus: Arc<dyn Consensus>,
pub(crate) blob: Arc<dyn Blob>,
pub(crate) metrics: Arc<Metrics>,
}Expand description
A durable, truncatable log of versions of State.
As persist metadata changes over time, we make its versions (each identified by a SeqNo) durable in two ways:
rollups: Periodic copies of the entirety of State, written to Blob.diffs: Incremental StateDiffs, written to Consensus.
The following invariants are maintained at all times:
- A shard is initialized iff there is at least one version of it in Consensus.
- The first version of state is written to
SeqNo(1). Each successive state version is assigned its predecessor’s SeqNo +1. current: The latest version of state. By definition, the largest SeqNo present in Consensus.- As state changes over time, we keep a range of consecutive versions
available. These are periodically
truncatedto prune old versions that are no longer necessary. earliest: The first version of state that it is possible to reconstruct.- Invariant:
earliest <= current.seqno_since()(we don’t garbage collect versions still being used by some reader). - Invariant:
earliestis always the smallest Seqno present in Consensus.- This doesn’t have to be true, but we select to enforce it.
- Because the data stored at that smallest Seqno is an incremental diff,
to make this invariant work, there needs to be a rollup at either
earliest-1orearliest. We chooseearliestbecause it seems to make the code easier to reason about in practice. - A consequence of the above is when we garbage collect old versions of
state, we’re only free to truncate ones that are
<the latest rollup that is<= current.seqno_since.
- Invariant:
live diffs: The set of SeqNos present in Consensus at any given time.live states: The range of state versions that it is possible to reconstruct:[earliest,current].- Because of earliest and current invariants above, the range of
live diffsandlive statesare the same.
- Because of earliest and current invariants above, the range of
- The set of known rollups are tracked in the shard state itself.
- For efficiency of common operations, the most recent rollup’s Blob key is always denormalized in each StateDiff written to Consensus. (As described above, there is always a rollup at earliest, so we’re guaranteed that there is always at least one live rollup.)
- Invariant: The rollups in
currentexist in Blob.- A consequence is that, if a rollup in a state you believe is
currentdoesn’t exist, it’s a guarantee thatcurrenthas changed (or it’s a bug).
- A consequence is that, if a rollup in a state you believe is
- Any rollup at a version
< earliest-1is useless (we’ve lost the incremental diffs between it and the live states). GC is tasked with deleting these rollups from Blob before truncating diffs from Consensus. Thus, any rollup at a seqno < earliest can be considered “leaked” and deleted by the leaked blob detector. - Note that this means, while
current’s rollups exist, it will be common for other live states to reference rollups that no longer exist.
Fields§
§cfg: PersistConfig§consensus: Arc<dyn Consensus>§blob: Arc<dyn Blob>§metrics: Arc<Metrics>Implementations§
Source§impl StateVersions
impl StateVersions
pub fn new( cfg: PersistConfig, consensus: Arc<dyn Consensus>, blob: Arc<dyn Blob>, metrics: Arc<Metrics>, ) -> Self
Sourcepub async fn maybe_init_shard<K, V, T, D>(
&self,
shard_metrics: &ShardMetrics,
) -> Result<TypedState<K, V, T, D>, Box<CodecMismatch>>
pub async fn maybe_init_shard<K, V, T, D>( &self, shard_metrics: &ShardMetrics, ) -> Result<TypedState<K, V, T, D>, Box<CodecMismatch>>
Fetches the current state of the requested shard, or creates it if
uninitialized.
Sourcepub async fn try_compare_and_set_current<K, V, T, D>(
&self,
cmd_name: &str,
shard_metrics: &ShardMetrics,
expected: Option<SeqNo>,
new_state: &TypedState<K, V, T, D>,
diff: &StateDiff<T>,
) -> Result<(CaSResult, VersionedData), Indeterminate>
pub async fn try_compare_and_set_current<K, V, T, D>( &self, cmd_name: &str, shard_metrics: &ShardMetrics, expected: Option<SeqNo>, new_state: &TypedState<K, V, T, D>, diff: &StateDiff<T>, ) -> Result<(CaSResult, VersionedData), Indeterminate>
Updates the state of a shard to a new current iff expected matches
current.
May be called on uninitialized shards.
Sourcepub async fn fetch_current_state<T>(
&self,
shard_id: &ShardId,
live_diffs: Vec<VersionedData>,
) -> UntypedState<T>
pub async fn fetch_current_state<T>( &self, shard_id: &ShardId, live_diffs: Vec<VersionedData>, ) -> UntypedState<T>
Fetches the current state of the requested shard.
Uses the provided hint (live_diffs), which is a possibly outdated copy of all or recent live diffs, to avoid fetches where possible.
Panics if called on an uninitialized shard.
Sourcepub async fn fetch_all_live_states<T>(
&self,
shard_id: ShardId,
) -> Option<UntypedStateVersionsIter<T>>
pub async fn fetch_all_live_states<T>( &self, shard_id: ShardId, ) -> Option<UntypedStateVersionsIter<T>>
Returns an iterator over all live states for the requested shard.
Returns None if called on an uninitialized shard.
Sourcepub async fn fetch_all_live_diffs(&self, shard_id: &ShardId) -> AllLiveDiffs
pub async fn fetch_all_live_diffs(&self, shard_id: &ShardId) -> AllLiveDiffs
Fetches all live_diffs for a shard. Intended only for when a caller needs to reconstruct all states still referenced by Consensus. Prefer Self::fetch_recent_live_diffs when the caller simply needs to fetch the latest state.
Returns an empty Vec iff called on an uninitialized shard.
Sourcepub async fn fetch_recent_live_diffs<T>(
&self,
shard_id: &ShardId,
) -> RecentLiveDiffs
pub async fn fetch_recent_live_diffs<T>( &self, shard_id: &ShardId, ) -> RecentLiveDiffs
Fetches recent live_diffs for a shard. Intended for when a caller needs to fetch the latest state in Consensus.
“Recent” is defined as either:
- All of the diffs known in Consensus
- All of the diffs in Consensus after the latest rollup
Sourcepub async fn fetch_all_live_diffs_gt_seqno<K, V, T, D>(
&self,
shard_id: &ShardId,
seqno: SeqNo,
) -> Vec<VersionedData>
pub async fn fetch_all_live_diffs_gt_seqno<K, V, T, D>( &self, shard_id: &ShardId, seqno: SeqNo, ) -> Vec<VersionedData>
Fetches all live diffs greater than the given SeqNo.
TODO: Apply a limit to this scan. This could additionally be used as an internal
call within fetch_recent_live_diffs.
Sourcepub async fn truncate_diffs(&self, shard_id: &ShardId, seqno: SeqNo)
pub async fn truncate_diffs(&self, shard_id: &ShardId, seqno: SeqNo)
Truncates any diffs in consensus less than the given seqno.
async fn write_initial_rollup<K, V, T, D>( &self, shard_metrics: &ShardMetrics, ) -> (TypedState<K, V, T, D>, StateDiff<T>)
pub async fn write_rollup_for_state<K, V, T, D>( &self, shard_metrics: &ShardMetrics, state: TypedState<K, V, T, D>, rollup_id: &RollupId, ) -> Option<EncodedRollup>
Sourcepub fn encode_rollup_blob<K, V, T, D>(
&self,
shard_metrics: &ShardMetrics,
state: TypedState<K, V, T, D>,
diffs: Vec<VersionedData>,
key: PartialRollupKey,
) -> EncodedRollup
pub fn encode_rollup_blob<K, V, T, D>( &self, shard_metrics: &ShardMetrics, state: TypedState<K, V, T, D>, diffs: Vec<VersionedData>, key: PartialRollupKey, ) -> EncodedRollup
Encodes the given state and diffs as a rollup to be written to the specified key.
The diffs must span the seqno range (state.last_rollup().seqno, state.seqno].
Sourcepub async fn write_rollup_blob(&self, rollup: &EncodedRollup)
pub async fn write_rollup_blob(&self, rollup: &EncodedRollup)
Writes the given state rollup out to blob.
Sourceasync fn fetch_rollup_at_seqno<T>(
&self,
shard_id: &ShardId,
live_diffs: Vec<VersionedData>,
seqno: SeqNo,
) -> Option<UntypedState<T>>
async fn fetch_rollup_at_seqno<T>( &self, shard_id: &ShardId, live_diffs: Vec<VersionedData>, seqno: SeqNo, ) -> Option<UntypedState<T>>
Fetches a rollup for the given SeqNo, if it exists.
Uses the provided hint, which is a possibly outdated copy of all or recent live diffs, to avoid fetches where possible.
Panics if called on an uninitialized shard.
Sourceasync fn fetch_rollup_at_key<T>(
&self,
shard_id: &ShardId,
rollup_key: &PartialRollupKey,
) -> Option<UntypedState<T>>
async fn fetch_rollup_at_key<T>( &self, shard_id: &ShardId, rollup_key: &PartialRollupKey, ) -> Option<UntypedState<T>>
Fetches the rollup at the given key, if it exists.
Sourcepub async fn delete_rollup(&self, shard_id: &ShardId, key: &PartialRollupKey)
pub async fn delete_rollup(&self, shard_id: &ShardId, key: &PartialRollupKey)
Deletes the rollup at the given key, if it exists.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for StateVersions
impl !RefUnwindSafe for StateVersions
impl Send for StateVersions
impl Sync for StateVersions
impl Unpin for StateVersions
impl !UnwindSafe for StateVersions
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<P, R> ProtoType<R> for Pwhere
R: RustType<P>,
impl<P, R> ProtoType<R> for Pwhere
R: RustType<P>,
Source§fn into_rust(self) -> Result<R, TryFromProtoError>
fn into_rust(self) -> Result<R, TryFromProtoError>
RustType::from_proto.Source§fn from_rust(rust: &R) -> P
fn from_rust(rust: &R) -> P
RustType::into_proto.Source§impl<'a, S, T> Semigroup<&'a S> for Twhere
T: Semigroup<S>,
impl<'a, S, T> Semigroup<&'a S> for Twhere
T: Semigroup<S>,
Source§fn plus_equals(&mut self, rhs: &&'a S)
fn plus_equals(&mut self, rhs: &&'a S)
std::ops::AddAssign, for types that do not implement AddAssign.