~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

Private repository pages no longer wait on the sync a change started

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:private-sync-wait
crates/knotless-serve/src/web/repo.rs+8−8
@@ -35,21 +35,21 @@ pub(super) fn invalid(message: String) -> Shown {
/// The repository whose record `uri` names, its authority a DID or a
/// handle, or its record in its space, under the name it has now.
pub(super) async fn found(app: &App, uri: &str) -> Result<Repo> {
named(app, uri, false).await
let at = repo_uri(uri)?;
Repo::find(app, &at.author, &at.rkey).await
}
/// [`found`] for a view of its code, which may be of a mirror a change has
/// made stale while it syncs.
async fn found_for_reader(app: &App, uri: &str) -> Result<Repo> {
named(app, uri, true).await
async fn found_for_reader(app: &Arc<App>, uri: &str) -> Result<Repo> {
let at = repo_uri(uri)?;
Repo::find_for_reader(app, &at.author, &at.rkey).await
}
async fn named(app: &App, uri: &str, reader: bool) -> Result<Repo> {
/// `uri`, a repository's record.
fn repo_uri(uri: &str) -> Result<knotless::aturi::AtUri> {
match knotless::aturi::AtUri::parse(uri) {
Ok(at) if at.collection == nsid::REPO && reader => {
Repo::find_for_reader(app, &at.author, &at.rkey).await
}
Ok(at) if at.collection == nsid::REPO => Repo::find(app, &at.author, &at.rkey).await,
Ok(at) if at.collection == nsid::REPO => Ok(at),
_ => Err(invalid(format!(
"{uri} is not at://<authority>/{}/<name>",
nsid::REPO
crates/knotless-serve/src/lib.rs+52−31
@@ -97,6 +97,12 @@ pub struct App {
/// Each public repository's mirror as last synced, by owner and name,
/// for a read to take without waiting on the lock a sync holds.
last: Mutex<HashMap<(String, String), Entry>>,
/// The same of each private repository's for a viewer, by viewer,
/// owner and name, as [`App::viewed`] holds it ([`private`]).
viewed_last: Mutex<HashMap<(String, String, String), Entry>>,
/// Those of them being synced aside as a change made them stale, each
/// by one task at a time ([`App::catch_up`]).
catching: Mutex<std::collections::HashSet<(String, String, String)>>,
/// Each repository's storage as last counted, kept until it moves
/// (`dev.knotless.getRepoStorage`).
pub(crate) counts: web::Counts,
@@ -210,7 +216,7 @@ struct Entry {
/// synced ([`App::writes_for`]).
writes: u64,
/// When the first event came that made it stale, if one has since it
/// was synced: kept with [`App::last`] only.
/// was synced: kept with [`App::last`] and [`App::viewed_last`] only.
stale_since: Option<Instant>,
}
@@ -219,14 +225,14 @@ struct Entry {
const STALE_FOR: Duration = Duration::from_secs(10);
/// Whether a read is served `entry`, a mirror as it was last synced,
/// without waiting on a sync, when its events now stamp as `stamp` and
/// `wrote` writes were made from the pages: if no event has come since it
/// synced, or the first came within [`STALE_FOR`], and the sync it started
/// is then still catching up; never after a write from the pages that it
/// may not have seen.
fn serves(entry: &Entry, stamp: (u64, u64), wrote: u64) -> bool {
/// without waiting on a sync, when it is `quiet`, no change having come
/// since it synced, and `wrote` writes were made from the pages: if
/// quiet, or if the first change came within [`STALE_FOR`], and the sync
/// it started is then still catching up; never after a write from the
/// pages that it may not have seen.
fn serves(entry: &Entry, quiet: bool, wrote: u64) -> bool {
let catching_up = entry.stale_since.is_some_and(|at| at.elapsed() < STALE_FOR);
entry.writes == wrote && (entry.events == stamp || catching_up)
entry.writes == wrote && (quiet || catching_up)
}
/// A repository found by name, and its mirror.
@@ -287,6 +293,8 @@ impl App {
repo_events: Mutex::default(),
writes: Mutex::default(),
last: Mutex::default(),
viewed_last: Mutex::default(),
catching: Mutex::default(),
counts: web::Counts::default(),
revs: Mutex::default(),
watching: AtomicBool::new(false),
@@ -603,7 +611,7 @@ impl App {
let last = self.last.lock().unwrap();
let entry = last.get(&(did.to_string(), name.to_string()))?;
let stamp = self.stamp(did, entry.key(did).as_deref());
serves(entry, stamp, wrote).then(|| entry.clone())
serves(entry, entry.events == stamp, wrote).then(|| entry.clone())
}
/// Keeps `entry`, just synced, as what [`App::served`] gives, or none
@@ -666,9 +674,11 @@ impl App {
let app = self.clone();
let did = did.to_string();
tokio::spawn(async move {
let _ = app.located_with(&did, &name, true).await;
let _ = app.located_with(&did, &name, None).await;
});
}
// Its private ones a viewer reads lately too, apart for each.
self.catch_up(|(_, owner, _), _| owner == did);
}
/// The mirror of `authority/name`, synced if it may be stale.
@@ -680,28 +690,30 @@ impl App {
/// name it has now: a public repository, or a private one the viewer
/// of the request being answered may read ([`private`]).
pub async fn located(&self, authority: &str, name: &str) -> Result<Located, AppError> {
self.located_with(authority, name, true).await
self.located_with(authority, name, None).await
}
/// [`App::located`] for a read of the repository that answers a request:
/// a mirror a change has made stale may be served while it syncs
/// ([`App::served`]). Nothing that derives and keeps something from the
/// mirror may read it so.
/// ([`App::served`], [`App::viewed_served`]). Nothing that derives and
/// keeps something from the mirror may read it so.
pub async fn located_for_reader(
&self,
self: &Arc<Self>,
authority: &str,
name: &str,
) -> Result<Located, AppError> {
self.located_with(authority, name, false).await
self.located_with(authority, name, Some(self)).await
}
/// [`App::located`], waiting for the sync of a stale mirror when `wait`,
/// as the refresh a change starts does: it is the sync.
/// [`App::located`], waiting for the sync of a stale mirror unless
/// `reader`, the app for a read that answers a request to sync a
/// private one aside with; as the refresh a change starts does, which
/// is the sync.
async fn located_with(
&self,
authority: &str,
name: &str,
wait: bool,
reader: Option<&Arc<App>>,
) -> Result<Located, AppError> {
let url = RepoUrl::parse(&format!("knotless://{authority}/{name}"))
.map_err(|e| AppError(StatusCode::BAD_REQUEST, e.to_string()))?;
@@ -715,6 +727,10 @@ impl App {
let delegated = delegated.filter(|_| gateway);
let viewer = private::viewer().filter(|_| gateway);
let viewer = viewer.or_else(|| delegated.as_ref().map(|d| d.did.clone()));
// A page's read of a private one does not wait on the sync a change
// started; one with a token for its space comes from a client,
// which may have just written there itself.
let aside = reader.filter(|_| delegated.is_none());
// One the viewer was shown as private is read as theirs again. Not
// found so, it is looked for as anyone looks: shown here may be only
// a look under way, such as the new repository form's check of a
@@ -723,20 +739,26 @@ impl App {
.as_ref()
.filter(|v| self.shown_private(v, &did, &url.name));
if let Some(viewer) = shown {
let read = self.as_viewer(viewer, &did, &url, None, delegated.as_ref());
let served = aside.map(|_| self.viewed_served(viewer, &did, &url.name));
let served = futures::future::OptionFuture::from(served).await.flatten();
if let Some(found) = served {
return Ok(found);
}
let read = self.as_viewer(viewer, &did, &url, None, delegated.as_ref(), aside);
let read = read.await;
if !read.as_ref().is_err_and(|e| e.0 == StatusCode::NOT_FOUND) {
return read;
}
}
let owner = wait || viewer.as_deref() == Some(did.as_str());
let owner = reader.is_none() || viewer.as_deref() == Some(did.as_str());
let missing = match self.public(remote, &url, owner).await {
Err(e) if e.0 == StatusCode::NOT_FOUND => e,
found => return found,
};
match &viewer {
Some(viewer) => {
let read = self.as_viewer(viewer, &did, &url, Some(missing), delegated.as_ref());
let delegated = delegated.as_ref();
let read = self.as_viewer(viewer, &did, &url, Some(missing), delegated, aside);
read.await
}
None => Err(missing),
@@ -1880,22 +1902,21 @@ mod tests {
fn a_stale_mirror_is_served_while_it_syncs() {
let long_ago = Instant::now().checked_sub(STALE_FOR * 2).unwrap();
let mut entry = Entry {
events: (1, 1),
synced: Some(long_ago),
..Entry::default()
};
// Quiet, it is served however long ago it synced.
entry.synced = Some(long_ago);
assert!(serves(&entry, (1, 1), 0));
// Stale with no event noted, or the first long ago, it is not.
assert!(!serves(&entry, (2, 1), 0));
assert!(serves(&entry, true, 0));
// Stale with no change noted, or the first long ago, it is not.
assert!(!serves(&entry, false, 0));
entry.stale_since = Some(long_ago);
assert!(!serves(&entry, (2, 1), 0));
// The first event only now, it is, however long ago it synced.
assert!(!serves(&entry, false, 0));
// The first change only now, it is, however long ago it synced.
entry.stale_since = Some(Instant::now());
assert!(serves(&entry, (2, 1), 0));
assert!(serves(&entry, false, 0));
// A write from the pages it may not have seen waits for the sync.
assert!(!serves(&entry, (2, 1), 1));
assert!(!serves(&entry, (1, 1), 1));
assert!(!serves(&entry, false, 1));
assert!(!serves(&entry, true, 1));
}
#[test]
crates/knotless-serve/src/private.rs+187−24
@@ -30,16 +30,17 @@
//! ([`crate::spaces::discover`]), so their list of repositories is read
//! from the index too, never from their PDS as they look.
use crate::{App, AppError, Located};
use crate::{App, AppError, Entry, Located, serves};
use axum::http::{HeaderValue, StatusCode, header};
use axum::response::Response;
use futures::future::OptionFuture;
use knotless::env::Ctx;
use knotless::remote::Remote;
use knotless::space::Space;
use knotless::url::RepoUrl;
use std::future::Future;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
/// How long a viewer's reading of a private repository is taken as
@@ -130,6 +131,10 @@ pub fn unshared(mut res: Response) -> Response {
/// next login.
pub fn forget(app: &App, did: &str) {
app.viewed.lock().unwrap().retain(|(v, _, _), _| v != did);
app.viewed_last
.lock()
.unwrap()
.retain(|(v, _, _), _| v != did);
if let Some(index) = &app.spaces {
let _ = index.drop_syncer(did);
}
@@ -138,7 +143,7 @@ pub fn forget(app: &App, did: &str) {
let _ = std::fs::remove_dir_all(&ctx.env.cache_dir);
}
type Viewed = (String, String, String);
pub(crate) type Viewed = (String, String, String);
impl App {
/// Whether `viewer` was shown `did`'s repository `name` as private.
@@ -152,6 +157,8 @@ impl App {
/// not private, so that a non-member learns nothing of it. With
/// `delegated`, a delegation token of theirs for its space, they are
/// proven a member with it rather than with a session of theirs here.
/// With `aside`, for a page's read, a mirror a change made stale is
/// served as it was while its sync catches up aside ([`serves`]).
pub(crate) async fn as_viewer(
&self,
viewer: &str,
@@ -159,6 +166,7 @@ impl App {
url: &RepoUrl,
missing: Option<AppError>,
delegated: Option<&Delegated>,
aside: Option<&Arc<App>>,
) -> Result<Located, AppError> {
let none = format!("{url}: no such repository");
let missing = missing.unwrap_or(AppError(StatusCode::NOT_FOUND, none));
@@ -172,8 +180,7 @@ impl App {
.or_default()
.clone();
let mut entry = entry.lock().await;
let reprove = Duration::from_millis(self.reprove.load(Ordering::Relaxed));
let stale = entry.proved.is_none_or(|at| at.elapsed() >= reprove);
let stale = !self.proved_lately(&entry);
// Between provings the space is read as it was found: its owner's
// session and a member's credential each last a minute more.
let remote = match entry.remote.clone().filter(|_| !stale) {
@@ -204,30 +211,22 @@ impl App {
}
};
let space = entry.space.clone().unwrap_or_default();
let moves = self.moves_of(&space);
let entry_key = entry.key(did);
let any = self.events_for(did);
let events = self.stamp(did, entry_key.as_deref());
// A space no one here has a session for is synced only as it is
// read, with what proved its reader a member.
let followed = self.space_followed(&space);
let fresh = match (&entry.git, entry.synced) {
// Nothing is written to a space but its sync finds, within
// seconds, or the pages touch.
(Some(_), Some(_)) if followed => entry.moves == moves && entry.events == events,
(Some(_), Some(at)) => at.elapsed() < self.ttl && entry.events == events,
_ => false,
};
let fresh = self.fresh_viewed(&entry, did, followed);
// Proved just now, or lately but behind a sync that held this lock,
// a page's read is served it as it was while a change's sync
// catches up, as it is with no lock ([`App::viewed_served`]).
let aside = aside.filter(|_| !fresh && followed && self.serves_last(&key, did));
let synced = !fresh && aside.is_none();
// No `?` ends a block, which coverage would count as a line never
// run.
let mut read = Ok(());
if !fresh {
read = self.sync(&ctx, remote.clone(), url, &mut entry).await;
}
if !fresh && read.is_ok() {
entry.moves = moves;
let found = entry.key(did);
entry.events = self.settled(did, entry_key.as_deref(), events, any, found.as_deref());
if synced {
read = self
.sync_viewed(&ctx, remote.clone(), did, url, &mut entry)
.await;
}
// Fresh or not, it is synced as whoever read it last: once its
// syncer logs out, the next to read it takes over. A reader with a
@@ -250,6 +249,10 @@ impl App {
entry.proved = Some(Instant::now());
entry.remote = Some(remote);
}
self.remember_viewed(&key, &entry, synced);
if let Some(app) = aside {
app.sync_aside(vec![key]);
}
if delegated.is_some() {
proven(viewer);
}
@@ -257,6 +260,164 @@ impl App {
Ok(self.found(&entry, did, ctx))
}
/// Whether `entry`'s viewer was found allowed to read it within
/// [`App::reprove`].
fn proved_lately(&self, entry: &Entry) -> bool {
let reprove = Duration::from_millis(self.reprove.load(Ordering::Relaxed));
entry.proved.is_some_and(|at| at.elapsed() < reprove)
}
/// Whether `entry`, the mirror of `did`'s private repository, is fresh,
/// its space `followed` or not.
fn fresh_viewed(&self, entry: &Entry, did: &str, followed: bool) -> bool {
let space = entry.space.as_deref().unwrap_or_default();
let events = self.stamp(did, entry.key(did).as_deref());
match (&entry.git, entry.synced) {
// Nothing is written to a space but its sync finds, within
// seconds, or the pages touch.
(Some(_), Some(_)) if followed => {
entry.moves == self.moves_of(space) && entry.events == events
}
(Some(_), Some(at)) => at.elapsed() < self.ttl && entry.events == events,
_ => false,
}
}
/// Syncs `entry`, `did`'s private repository `url`, from `remote` read
/// with `ctx`, and notes what it is then fresh as of.
async fn sync_viewed(
&self,
ctx: &Ctx,
remote: Remote,
did: &str,
url: &RepoUrl,
entry: &mut Entry,
) -> Result<(), AppError> {
let moves = self.moves_of(entry.space.as_deref().unwrap_or_default());
let entry_key = entry.key(did);
let any = self.events_for(did);
let events = self.stamp(did, entry_key.as_deref());
let wrote = self.writes_for(did);
let read = self.sync(ctx, remote, url, entry).await;
if read.is_ok() {
entry.moves = moves;
let found = entry.key(did);
entry.events = self.settled(did, entry_key.as_deref(), events, any, found.as_deref());
entry.writes = wrote;
}
read
}
/// `did`'s private repository `name` as last synced for `viewer`, to a
/// page's read that does not wait on the lock its sync holds: theirs
/// if they were found allowed to read it within [`App::reprove`], its
/// space followed and synced lately, and it is fresh or a change made it
/// stale whose sync is catching up ([`serves`]); never after a write
/// from the pages that it may not have seen.
pub(crate) async fn viewed_served(
&self,
viewer: &str,
did: &str,
name: &str,
) -> Option<Located> {
let key = (viewer.to_string(), did.to_string(), name.to_string());
let last = self.viewed_last.lock().unwrap().get(&key).cloned()?;
let space = last.space.as_deref().unwrap_or_default();
let followed = self.space_followed(space) && !self.sync_stale(space);
let quiet = self.fresh_viewed(&last, did, followed);
let served = followed && self.proved_lately(&last);
let served = served && serves(&last, quiet, self.writes_for(did));
// Its space is synced as whoever read it last, as
// [`App::as_viewer`] has it.
let served = served && self.keep(space, viewer).await.is_ok();
served.then(|| {
touched();
self.found(&last, did, crate::login::ctx_for(self, viewer))
})
}
/// Whether what [`App::viewed_last`] holds for `key`, a mirror of
/// `did`'s that a change made stale, is served while its sync catches
/// up ([`serves`]).
fn serves_last(&self, key: &Viewed, did: &str) -> bool {
let wrote = self.writes_for(did);
let last = self.viewed_last.lock().unwrap();
last.get(key).is_some_and(|last| serves(last, false, wrote))
}
/// Keeps `entry`, read for `key`, as what [`App::viewed_served`] serves:
/// as made stale when it was before, unless it was `synced` since.
fn remember_viewed(&self, key: &Viewed, entry: &Entry, synced: bool) {
let mut last = self.viewed_last.lock().unwrap();
let since = last
.get(key)
.and_then(|l| l.stale_since)
.filter(|_| !synced);
let entry = Entry {
stale_since: since,
..entry.clone()
};
last.insert(key.clone(), entry);
}
/// Syncs aside the mirrors of the private repositories viewers were
/// shown that `which` picks, as a change made them stale: each read
/// meanwhile is served one as it was ([`App::viewed_served`]). Only those
/// whose viewer was found allowed to read it lately, the ones served
/// so; the rest are synced as they are next read.
pub(crate) fn catch_up(self: &Arc<Self>, which: impl Fn(&Viewed, &Entry) -> bool) {
let now = Instant::now();
let mut due = Vec::new();
for (key, last) in self.viewed_last.lock().unwrap().iter_mut() {
if which(key, &*last) {
last.stale_since.get_or_insert(now);
due.extend(self.proved_lately(last).then(|| key.clone()));
}
}
self.sync_aside(due);
}
/// Syncs each of `due` aside, unless a sync of it is waiting its turn
/// already, which a change since is left to.
fn sync_aside(self: &Arc<Self>, mut due: Vec<Viewed>) {
let mut catching = self.catching.lock().unwrap();
due.retain(|key| catching.insert(key.clone()));
drop(catching);
for key in due {
tokio::spawn(self.clone().caught_up(key));
}
}
/// Syncs the mirror `key` names, read as its viewer was found allowed,
/// unless it is fresh by its turn, and keeps it for reads to be served.
/// A sync that fails leaves it as it was, to be synced as it is read.
async fn caught_up(self: Arc<Self>, key: Viewed) {
let shared = self.viewed.lock().unwrap().get(&key).cloned();
let entry = OptionFuture::from(shared.map(|s| s.lock_owned())).await;
// Its turn come, a change from now on starts another.
self.catching.lock().unwrap().remove(&key);
let (app, key) = (&self, &key);
let did = key.1.as_str();
let stale = |e: &Entry| {
let followed = app.space_followed(e.space.as_deref().unwrap_or_default());
!app.fresh_viewed(e, did, followed)
};
let due = entry.filter(|e| stale(e));
let due = due.and_then(|e| Some((e.remote.clone()?, e)));
let synced = due.map(|(remote, mut entry)| async move {
let url = RepoUrl {
authority: did.to_string(),
name: key.2.clone(),
};
let ctx = crate::login::ctx_for(app, &key.0);
let synced = app.sync_viewed(&ctx, remote, did, &url, &mut entry).await;
if synced.is_ok() {
app.remember_viewed(key, &entry, true);
}
});
OptionFuture::from(synced).await;
}
/// Keeps an index of the private repository in the space `joined`, as
/// a member reads it with a delegation token: synced now with their
/// credential if it never was, or if no session here syncs it. A client
@@ -392,10 +553,12 @@ impl App {
}
/// `read`, having forgotten that the viewer `key` names was shown its
/// repository if reading it again failed.
/// repository, and its mirror as last synced, if reading it again
/// failed.
fn unview<T>(&self, key: &Viewed, read: Result<T, AppError>) -> Result<T, AppError> {
if read.is_err() {
self.viewed.lock().unwrap().remove(key);
self.viewed_last.lock().unwrap().remove(key);
}
read
}
crates/knotless-serve/src/spaces.rs+3−1
@@ -111,9 +111,11 @@ pub async fn follow(app: Arc<App>, every: Duration) {
let refused = synced.as_ref().err().is_some_and(space::denied);
let gone = synced.as_ref().err().is_some_and(gone);
// What was written there shows on the next look at it, as does
// what a sync that failed read of its other repos.
// what a sync that failed read of its other repos; the mirrors
// of it viewers read lately are synced aside meanwhile.
if !matches!(synced, Ok(false)) {
app.moved(&uri);
app.catch_up(|_, last| last.space.as_deref() == Some(uri.as_str()));
}
crate::telemetry::space_synced(&uri, synced.map(drop));
if gone {
crates/knotless-serve/src/web.rs+1−1
@@ -1466,7 +1466,7 @@ impl Repo {
/// [`Repo::find`] for a view of its code that answers a request, which
/// may be of a mirror a change has made stale while it syncs
/// ([`App::located_for_reader`]).
async fn find_for_reader(app: &App, authority: &str, name: &str) -> Result<Repo> {
async fn find_for_reader(app: &Arc<App>, authority: &str, name: &str) -> Result<Repo> {
let found = app.located_for_reader(authority, repo_name(name)).await?;
Repo::moved(app, authority, found).await
}
crates/knotless-serve/tests/gateway.rs+9−0
@@ -3470,6 +3470,15 @@ fn private_repositories_indexed_here() {
owner.commit_file(&work, "later.md", "# Later\n");
owner.git(&work, &["push", "-q", &url, "main"]);
wait_until(|| read("getTree", "").to_string().contains("later.md"));
// Its member to be proven a member again at each read, the read that
// proves them is served the mirror as it was while the sync of the next
// push catches up aside, and the push is read once it has.
server.app.reprove.store(0, Ordering::Relaxed);
owner.commit_file(&work, "after.md", "# After\n");
owner.git(&work, &["push", "-q", &url, "main"]);
wait_until(|| read("getTree", "").to_string().contains("after.md"));
let reprove = knotless_serve::private::REPROVE.as_millis() as u64;
server.app.reprove.store(reprove, Ordering::Relaxed);
let thread = |uri: &str| format!("&uri={uri}");
let first = read("getThread", &thread(&issue));
assert_eq!(first["item"]["title"], "Private trouble");
docs/design/access.md+4−1
@@ -261,7 +261,10 @@ sequenceDiagram
- Membership is asked again, with a fresh credential, once the last answer
is a minute old; in between, the space is read as it was found then,
with no round trip to look for it again. Its mirror is synced again only
once the sync of its space finds it written to. Someone removed from a repository reads it here for at
once the sync of its space finds it written to, in the background for
one proven within that minute, while a page's look meanwhile is shown
it as last synced, for ten seconds at most ([serve.md](serve.md#mirrors-and-freshness)).
Someone removed from a repository reads it here for at
most that minute more. Logging out forgets what was shown to the
account, its space credentials and its mirrors at once.
- A member who never logged in here, reading through an app that signed
docs/design/serve.md+18−0
@@ -121,6 +121,24 @@ question is when to sync:
something written there: at once as its authority tells of a write, and
every thirty seconds besides. A server not syncing its spaces falls back
to the TTL.
- Each viewer's mirror of a private repository is read as public ones are
above, for the same reads of its code. Whatever its space's sync finds
written there, a push or a runner's check alike, or a change in its
owner's account, starts a sync of the mirrors that viewers were proven
to read within the minute, in the background, one at a time for each.
Meanwhile, its space followed, a page's read is served its viewer's
mirror as last synced, for ten seconds from the first change, without
waiting on the lock that sync holds; one whose viewer is to be proven
again is proven first, then served it so, and starts that sync itself.
It is never served to a viewer not proven within the minute, any more
than a fresh one is. A write from the pages is not served stale, and nor
is a read with a delegation token, which is how the command line shows
the server what it just wrote: each waits for the sync. On knotless.dev
every write to one private repository's space, its checks' among them,
made the next look at it sync its mirror first, which all five of its
page's requests waited on:
100 of the 124 syncs of its mirror in twelve hours were in a page's
request, and 79 of those found nothing new but its records.
- A repository found not to be there is taken as not there for the TTL, or
until a feed reports a change in its owner's account.