~ 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

A private repository's language shows at once on a list after its first count

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:serve/profile-fast
crates/knotless-serve/src/web/actor.rs+42−6
@@ -72,15 +72,40 @@ fn counts(index: &Index, did: &str, key: &str) -> (Option<u64>, Option<u64>) {
(index.star_count(did, key).ok(), forks)
}
/// What each private repository was last counted as mostly written in,
/// by its owner's DID and its key.
static PRIVATE_LANGUAGES: LazyLock<Mutex<Counted>> = LazyLock::new(Default::default);
/// What each repository was counted as written in, by its owner's DID and
/// its key.
type Counted = HashMap<(String, String), Option<Language>>;
/// What `did`'s repository `r` is mostly written in. A public one's is
/// the index's, counted as its refs move ([`languages::follow`]): one never
/// counted is asked for, for a later read, rather than waited on. A
/// private one, which the index never sees, is counted from its mirror.
async fn language(app: &App, did: &str, r: &RepoRecord, private: bool) -> Option<LanguageView> {
/// private one, which the index never sees, is counted from its mirror:
/// once counted, what was counted shows while its mirror syncs and it is
/// counted again in the background, as a sync may wait a second on its
/// owner's PDS.
async fn language(
app: &Arc<App>,
did: &str,
r: &RepoRecord,
private: bool,
) -> Option<LanguageView> {
if private {
let git = app.mirror(did, &r.name).await.ok()?;
let objects = objects::open(&git.dir).ok()?;
return languages::main_of(&objects).map(LanguageView::from);
let key = (did.to_string(), r.key.clone());
let count = count_private(app.clone(), key.clone(), r.name.clone());
let kept = PRIVATE_LANGUAGES.lock().unwrap().get(&key).cloned();
let found = match kept {
Some(kept) => {
let viewer = crate::private::viewer();
tokio::spawn(crate::private::reading(viewer, None, count));
kept
}
None => count.await,
};
return found.map(LanguageView::from);
}
let index = app.index.as_ref()?;
let kept = index.language(did, &r.key).ok().flatten();
@@ -91,6 +116,17 @@ async fn language(app: &App, did: &str, r: &RepoRecord, private: bool) -> Option
found.map(LanguageView::from)
}
/// Counts what the private repository named `name`, of the owner and key
/// `key` names, is mostly written in, from its mirror synced, and keeps it.
async fn count_private(app: Arc<App>, key: (String, String), name: String) -> Option<Language> {
let git = app.mirror(&key.0, &name).await.ok()?;
let objects = objects::open(&git.dir).ok()?;
let found = languages::main_of(&objects);
let mut kept = PRIVATE_LANGUAGES.lock().unwrap();
kept.insert(key, found.clone());
found
}
#[derive(Serialize)]
pub struct Output {
repos: Vec<RepoView>,
@@ -336,7 +372,7 @@ pub async fn get_actor_stars(
}
}
async fn starred(app: &App, index: &Index, did: &str) -> Result<axum::Json<Output>> {
async fn starred(app: &Arc<App>, index: &Index, did: &str) -> Result<axum::Json<Output>> {
let found = index
.actor_stars(did)
.map_err(anyhow::Error::from)
crates/knotless-serve/src/web.rs+9−5
@@ -935,11 +935,15 @@ pub async fn get_profile(
bot: about.bot,
orgs: orgs::orgs_of(&app, remote.did(), viewer.0.as_deref()).await,
badges: match index {
Some(i) => badges::badges_of(
i,
remote.did(),
badges::home(&app, i.clone(), &remote).await,
),
Some(i) => {
let home = badges::home(&app, i.clone(), &remote).await;
// Counted on a thread of its own: an account of many pulls
// takes a while, which would hold up every request this
// worker answers meanwhile.
let (i, did) = (i.clone(), remote.did().to_string());
let count = move || badges::badges_of(&i, &did, home);
tokio::task::spawn_blocking(count).await.unwrap_or_default()
}
None => Vec::new(),
},
};
crates/knotless-serve/tests/gateway.rs+3−0
@@ -3210,6 +3210,9 @@ fn private_repositories_indexed_here() {
names
};
wait_until(|| mine() == ["\"found\"", "\"kept\""]);
// Asked again, what each was counted as written in shows at once, and
// is counted again behind it.
assert_eq!(mine(), ["\"found\"", "\"kept\""]);
let viewer = format!("{}/xrpc/dev.knotless.getViewer", server.base);
let (_, _, me) = browse("GET", &viewer, Some(&owner_in), None, None);
assert_eq!(me["spaces"], true, "{me}");
docs/design/serve.md+3−1
@@ -376,7 +376,9 @@ the repository's refs or its record changes in a feed, which a push or a
new default branch does. Only repositories that were counted are counted
again: a feed carries every push on the network, and syncing a mirror of
each would mirror the network. A private repository, which the index never
sees, is counted from its mirror as its list is read; such lists are short.
sees, is counted from its mirror the first time its list is read; after
that, what was counted shows at once, and its mirror is synced and counted
again in the background, as a sync waits on its owner's PDS.
### Shared steps