chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
An account with no handle is looked up again after ten minutes
crates/knotless-serve/src/web.rs+9−1
| @@ -458,6 +458,10 @@ static HANDLES: LazyLock<Mutex<HashMap<String, String>>> = LazyLock::new(Mutex:: | ||
/// behind the page showing it. An identity event looks it up at once. | ||
const HANDLE_KEPT_FOR: Duration = Duration::from_secs(24 * 60 * 60); | ||
| ||
/// How long an account's having no handle is kept before it is looked up | ||
/// again: a handle's DNS can go live just after the account claims it. | ||
const NO_HANDLE_KEPT_FOR: Duration = Duration::from_secs(600); | ||
| ||
/// Seconds since the epoch. | ||
fn now_secs() -> i64 { | ||
let since = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH); | ||
| @@ -474,7 +478,11 @@ pub(crate) async fn handle(app: &App, did: &str) -> String { | ||
let found = rename(app.ctx.clone(), index, did.to_string()).await; | ||
return found.unwrap_or(did.to_string()); | ||
}; | ||
if now_secs() - checked >= HANDLE_KEPT_FOR.as_secs() as i64 { | ||
let kept_for = match handle { | ||
Some(_) => HANDLE_KEPT_FOR, | ||
None => NO_HANDLE_KEPT_FOR, | ||
}; | ||
if now_secs() - checked >= kept_for.as_secs() as i64 { | ||
// Marked as looked up now, so the pages showing it meanwhile | ||
// look it up once between them. | ||
let _ = index.set_handle(did, handle.as_deref(), now_secs()); | ||
crates/knotless-serve/tests/forge.rs+19−0
| @@ -635,6 +635,25 @@ fn forks_pulls_reviews_and_merges() { | ||
let stale = owners(&[("q", "stale.example")]); | ||
assert_eq!(stale["owners"][0]["owner"]["handle"], "stale.example"); | ||
renamed(&owner.account.handle); | ||
// Having none is kept ten minutes, for a handle whose DNS has just gone | ||
// live: within them the DID is shown, and after them it is looked up. | ||
let profile = || -> serde_json::Value { | ||
reqwest::blocking::Client::new() | ||
.get(format!("{}/xrpc/dev.knotless.getProfile", av.base)) | ||
.query(&[("actor", did)]) | ||
.send() | ||
.unwrap() | ||
.json() | ||
.unwrap() | ||
}; | ||
let seconds = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH); | ||
let seconds = seconds.unwrap().as_secs() as i64; | ||
indexed.set_handle(did, None, seconds).unwrap(); | ||
assert_eq!(profile()["handle"], did); | ||
assert_eq!(kept(), None); | ||
indexed.set_handle(did, None, seconds - 601).unwrap(); | ||
assert_eq!(profile()["handle"], did); | ||
renamed(&owner.account.handle); | ||
let uri = format!("at://{}/dev.knotless.repo/forkable", owner.account.did); | ||
let indexed = av.app.index.as_ref().unwrap(); | ||
let key = indexed.repo(&uri).unwrap().unwrap()["key"] | ||
docs/design/serve.md+3−1
| @@ -160,7 +160,9 @@ restart and search can find owners by them. A handle is kept only when it | ||
resolves back to its DID, and an identity event for an account whose handle | ||
is kept looks it up again at once: the event names the new handle, but is not | ||
trusted for it. One kept a day is still shown, and looked up again behind | ||
the page showing it. Without an index, handles are kept in memory. | ||
the page showing it. An account found to have none shows its DID, and is | ||
looked up again the same way after ten minutes, as a handle's DNS can go live | ||
just after the account claims it. Without an index, handles are kept in memory. | ||
| ||
A filter of pulls or issues by `author:` reads the account from those kept | ||
handles. A handle not kept there is looked up at its host, and what was | ||