pub struct Live { /* private fields */ }Expand description
The repository a process reads, kept current.
Two forms, and the difference is whether anything is watched at all:
Live::pinned— one context, forever, at no cost. A command that answers and exits, a benchmark, a test: the picture cannot go stale inside them, and making them pay astatper call to prove it would be a regression bought with nothing.Live::watching— the shared server’s form. EveryLive::currenttakes aStampfirst and rebuilds when it differs from the one the generation it holds was built at.
// the shared server follows the repository; a one-shot command does not
let followed = Live::watching(args, Arc::clone(&ctx));
let pinned = Live::pinned(ctx);
assert_eq!(pinned.generation(), followed.generation(), "both start at the first");Implementations§
Source§impl Live
impl Live
Sourcepub fn pinned(ctx: Arc<Context>) -> Live
pub fn pinned(ctx: Arc<Context>) -> Live
One context that never changes: no stamp is taken and nothing is rebuilt.
let live = Live::pinned(Arc::clone(&ctx));
assert!(Arc::ptr_eq(&live.current(), &ctx), "the very context it was given");Sourcepub fn watching(args: RepoArgs, ctx: Arc<Context>) -> Live
pub fn watching(args: RepoArgs, ctx: Arc<Context>) -> Live
A context that follows the repository, reloaded with args when git moves it.
args is how the process was pointed at the repository in the first place, kept so
that a reload discovers the same root, the same distribution and the same discovery
mode the first load did. Falls back to Live::pinned when the root is not a work
tree: there is nothing to follow, and pretending otherwise would take a stamp over
a handful of absent files on every request forever.
let live = Live::watching(args, ctx);
// the first reading is the one it was handed; a commit makes the next one the second
assert_eq!(live.view().generation, 0);Sourcepub fn generation(&self) -> u64
pub fn generation(&self) -> u64
Which generation is current, without taking a stamp.
Only for a caller that already holds a View and wants to say which one it is; a
caller that is about to use the context must take Live::view, because reading
the number and then the context is two reads with a reload possible between them —
the bug this whole module exists to end, one layer in. A projection memoised under
the number read before the reload is the previous generation’s, handed out as the
current one.
let live = Live::pinned(ctx);
assert_eq!(live.generation(), live.view().generation);Sourcepub fn current(&self) -> Arc<Context> ⓘ
pub fn current(&self) -> Arc<Context> ⓘ
The context as it is now: the one that was loaded, or a newly built one when the repository has moved under this process.
let live = Live::pinned(ctx);
assert!(Arc::ptr_eq(&live.current(), &live.view().ctx));Sourcepub fn view(&self) -> View
pub fn view(&self) -> View
The current generation and the context of it, as one reading.
One call, so that a caller keying a memo on the number and filling it from the context cannot key the new context under the old number.
let live = Live::pinned(ctx);
let memo: Memo<usize> = Memo::default();
// the shape every projection uses: one reading, keyed and filled from itself
let view = live.view();
let objects = memo.get_or_init(view.generation, || view.ctx.index.objects.len());
assert_eq!(*objects, view.ctx.index.objects.len());Sourcepub fn view_without_waiting(self: &Arc<Self>) -> (View, bool)
pub fn view_without_waiting(self: &Arc<Self>) -> (View, bool)
The generation there is, at once, and whether the repository has moved past it: what a page a person is looking at asks for (ADR 0142).
Live::view waits for a reload, because an answer must be of the repository the
caller saw. A page need not be: it is drawn from the generation that exists, says that
the repository changed, and is read again once the new generation has loaded. So
when the repository has moved, this starts the reload on a thread of its own, unless
one is already running, and returns the existing generation with behind set.
Nothing about Live::view changes for any other caller.
use majordomus_cli::live::Live;
use majordomus_cli::synthetic::SyntheticRepository;
use std::sync::Arc;
let repo = SyntheticRepository::small().unwrap();
let live = Arc::new(Live::pinned(repo.context().unwrap()));
// a pinned view follows nothing, so the generation there is is the one to show and
// the repository has never moved past it
let (view, behind) = live.view_without_waiting();
assert!(!behind);
assert_eq!(view.generation, live.view().generation);