Skip to main content

Conversation

Struct Conversation 

Source
pub struct Conversation {
    window: Window,
    rendered: Rendered,
    compaction_count: u32,
    dropped: usize,
    watermark: u64,
    dirty: bool,
    folding: bool,
    forged: HashSet<String>,
    occupant: Option<SessionId>,
    live: bool,
    scan: TurnScan,
    dropped_thinking: i64,
}
Expand description

One seat’s conversation: the messages, where its turns sit and how many times it has compacted.

All three come out of one read and one fold, so a page cut on the fold’s boundaries and a record built from messages cannot disagree about where a turn begins, and the count cannot describe a different conversation than the one held.

Fields§

§window: Window§rendered: Rendered

The fold’s boundaries and task endings, which a page is cut on.

Nothing but those is held, because the transport draws nothing: a client folds the frames a page hands it, so the boundaries are what a page here is cut on and the endings are what its turns carry.

§compaction_count: u32§dropped: usize

The messages the cap has dropped off the front, ever.

A page cursor is measured against this rather than against the held list. A cursor names a message in the conversation’s own numbering, which a drop does not move, so a cursor that outlived one still names the message it meant - and one naming a message the drop has taken is answered with the floor rather than with whatever now sits at its old place in the list.

§watermark: u64

The newest frame number this copy reflects, which a reseed resets.

An answer’s number is taken from it, because a reseed lands before the fold’s reset mark and a pre-seal number would have the client skip the new run’s first frames (#2443).

§dirty: bool

The messages moved since the fold last ran.

Memoized rather than made incremental, because making it incremental means deciding where a turn begins from the appended message alone - a second turn-boundary rule, which is the drift turn_ranges’ own doc exists to prevent. One rule in one place, and it runs when the messages changed rather than once per request.

And it never runs under this lock. The socket folds the core’s stream in ONE task for every seat, so a fold holding a seat’s lock stalls update delivery for every client on every seat. Held::fold is where it runs instead.

§folding: bool

The messages are out being folded, so what is here is half a state.

A reader must wait rather than look. A fold takes the messages out in O(1), renders them off the lock, and puts them back with the spans, so between those two the seat reads as no messages against the PREVIOUS fold’s boundaries, and a page sliced on those walks off the end of an empty list. Two requests on one seat is the ordinary case for that, not an exotic one.

§forged: HashSet<String>

The uuids of the delivery rows this transport forged.

A forged row is a frame no transcript has, and nothing about its shape says so - it is a user row like the prompt it draws. Only the site that forged it knows, which is why the set lives here rather than in the row rule. Conversation::has_a_row is what reads it: a walk below the window names this seat’s oldest row TO THE FILE, and naming one the file never wrote answers the read nothing - which reads as the end of the history.

§occupant: Option<SessionId>

The occupant this copy was last seeded for.

What tells a copy of the previous run from the current one. A seal is minted by the fanout and applied by the fold, and a read landing between the two would otherwise pair the new epoch’s count with the old run’s rows: a copy whose occupant is not the seat’s is no copy at all.

§live: bool

Whether the seat’s turn is in flight right now, folded off the frames this copy has seen (liveness_of - the delivered rule: the model’s own frames open a turn, its Result or error closes it).

The fold’s caller carries this, because the frame that would say it directly (session_state_changed) is never sent: the fold reads it as “the open turn the frames describe is live”, which is what keeps a mid-call delivery from being cut off from a result that has not streamed yet (#2379).

§scan: TurnScan

Where the stream opens turns, folded over every frame this copy has seen rather than over the window: a cut moves the window’s front, not the rule that says which frame opens a turn.

§dropped_thinking: i64

The thinking growth a cut took out of the turn open at the window’s end, which the page serving that turn carries back into its first counter.

It never crosses a turn. A Result closes the turn it belonged to, and a frame that opens a turn starts the next one with nothing carried.

Implementations§

Source§

impl Conversation

Source

pub fn new( messages: Vec<Message>, compaction_count: u32, carried: usize, ) -> Self

A conversation from the history a connect or a resume carried.

It does not fold. The spans come from the next Held::fold, which runs on a blocking task; folding here would run an 18 ms render on whatever task built this, and that task is the socket’s single stream folder.

carried is the floor history arrives with: the messages the read it came from left behind a window that was taken before the history crossed (see Conversation::seed), so a window handed over on its own still tells the whole conversation’s numbering.

Source

pub fn empty() -> Self

The conversation a seat with nothing behind it answers as.

Source

pub fn occupant(&self) -> Option<&SessionId>

The occupant this copy was last seeded for.

Source

pub fn set_occupant(&mut self, occupant: Option<SessionId>)

Say which occupant this copy is for.

Source

pub fn watermark(&self) -> u64

The newest frame number this copy reflects.

Source

pub fn set_watermark(&mut self, seq: u64)

Say how far this copy is current, which a reseed resets and an applied frame advances.

Source

pub fn seed( &mut self, messages: Vec<Message>, compaction_count: u32, carried: usize, )

Replace the whole conversation, which is what a connect, a resume or a /new says: the history it carries is the truth about this seat.

It marks the fold rather than running it, for the reason Conversation::new gives: this is reached from the stream fold, and a render there stalls every seat rather than this one.

carried is the floor the history arrives with - the messages the read it came from left behind a window taken before it crossed, which Connected and SessionReplaced carry beside the history they hand over (a resume’s read is windowed at the emit). Without it a seat reseeded from a window reports the window’s own front as the conversation’s, and a client’s walk below it stops there instead of crossing into the transcript.

The numbering restarts, because a connect or a resume carries a transcript READ - a row subset, not this copy’s frame sequence - so an index carried over it would be off by however far the two diverge. A cursor from before resolves by its own number again and is answered from the floor when that number falls below the front the new window starts at.

Source

pub fn append(&mut self, message: Message)

One frame the session emitted.

Source

pub fn append_forged(&mut self, message: Message)

One row this transport forged for display, which no transcript holds.

Forged rows are frames the file counts no row for, and nothing about their shape says so - a delivery row is a user row like the prompt it draws. So the seat keeps their ids, and Self::has_a_row answers with them: a walk below the floor names the seat’s oldest row to the file, and one the file never wrote answers nothing.

Source

pub fn has_a_row(&self, message: &Message) -> bool

Whether a transcript row carries message: the kinds the row rule reads, and nothing this transport forged for display.

The seat’s own answer, because half of it is the seat’s. The rule knows the kinds a file writes; only the seat knows which of its own rows it minted, and a forged row is a user row like the prompt it draws. A walk below the window needs both halves: naming the file a row it does not carry answers the read nothing, which a client draws as the end of the history.

Source

fn push(&mut self, message: Message)

Source

fn take_dirty(&mut self) -> Option<Window>

The messages if the fold is behind them, taken in O(1).

Source

fn merge_fold(&mut self, folded: Window, rendered: Rendered, complete: bool)

Put a fold back, with whatever arrived while it ran appended.

complete is false when the render did not reach its end, which is the guard’s path: the messages are back but the boundaries installed with them describe nothing.

Source

pub fn messages(&self) -> &[Message]

Source

pub fn rendered(&self) -> &Rendered

Source

pub fn compaction_count(&self) -> u32

Source

pub fn dropped(&self) -> usize

How many messages the cap has dropped off the front, which is what turns a held index into the one a page’s cursor carries.

Source

pub fn dropped_thinking(&self) -> i64

The thinking growth a cut took out of the turn open at the window’s end, which a page of that turn carries back into its first counter.

Auto Trait Implementations§

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
§

impl<T> Any for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

§

fn type_name(&self) -> &'static str

§

impl<T> AnySync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ

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
§

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

§

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

§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

impl<T> Instrument for T

§

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

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

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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

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

Initializes a with the given initializer. Read more
§

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

Dereferences the given pointer. Read more
§

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

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

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

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

§

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
§

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
§

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

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

§

fn to_sample_(self) -> U

Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.
§

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

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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