feat(at-identity): PdsHandleResolver for cluster-local DID→handle resolution
The AppView's handle_sync worker consulted the public PLC directory and the did:web: HTTPS resolver only. DIDs hosted on the local PDS (notably did🔑 users and any other operator-hosted method) weren't reachable without an external round trip, and unresolvable DIDs (did🔑 not on this PDS, did:foo: anything) blocked the 100-row batch forever because did🔑 sorts lexicographically before did:plc: / did:web:. This commit adds: * `PdsHandleResolver` (at-identity) — POSTs the DID as the `handle` field to the PDS's resolveHandle XRPC method. The PDS now recognises a `did:` prefix and does a PK lookup on `users.did`, returning `{did, handle}`. The resolver reads the `handle` field, so the AppView finally gets a real local handle for did🔑 users without ever dialing plc.directory. * A 2 s timeout per request (was 10 s) and `DISPATCH_CONCURRENCY = 8` so the worker caps a 100-DID batch at ~2 s with parallel dispatch instead of the ~17 min worst case the old serial + 10 s setup allowed. * A new `posts.handle_sync_attempted_at` column (migration 0006) and `mark_attempted()` helper. The SELECT filter excludes rows attempted within the last hour, so an unresolvable DID dominates at most one batch before the worker advances. Cleared on success. * `PDS_INTERNAL_URL` config so the AppView can reach the PDS via a cluster-internal hostname when the public URL isn't routable from inside the cluster. Tests: * `crates/at-identity/src/pds_handle.rs` — 4 unit tests against a stub HTTP server (200/404/5xx/missing-did-field). * Existing handle_sync integration tests updated to wire in the new `pds_resolver` field.
This commit is contained in:
@@ -67,13 +67,14 @@ impl DidHandleResolver for StubResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a worker whose PLC and web resolvers are both the same stub.
|
||||
/// The integration tests in this file don't care which method the
|
||||
/// DID uses — the stub answers for any prefix.
|
||||
/// Build a worker whose PDS, PLC and web resolvers are all the same
|
||||
/// stub. The integration tests in this file don't care which method
|
||||
/// the DID uses — the stub answers for any prefix.
|
||||
fn worker_with(db: sqlx::PgPool, stub: Arc<StubResolver>) -> HandleSyncWorker {
|
||||
let r: Arc<dyn DidHandleResolver> = stub;
|
||||
HandleSyncWorker {
|
||||
db,
|
||||
pds_resolver: Arc::clone(&r),
|
||||
plc_resolver: Arc::clone(&r),
|
||||
web_resolver: Arc::clone(&r),
|
||||
interval_secs: 999,
|
||||
@@ -389,6 +390,7 @@ async fn sync_resolves_did_web_via_web_resolver() {
|
||||
|
||||
let worker = HandleSyncWorker {
|
||||
db: db.clone(),
|
||||
pds_resolver: Arc::clone(&plc_arc),
|
||||
plc_resolver: plc_arc,
|
||||
web_resolver: web_arc,
|
||||
interval_secs: 999,
|
||||
@@ -442,6 +444,7 @@ async fn sync_resolves_did_plc_via_plc_resolver() {
|
||||
|
||||
let worker = HandleSyncWorker {
|
||||
db: db.clone(),
|
||||
pds_resolver: Arc::clone(&plc_arc),
|
||||
plc_resolver: plc_arc,
|
||||
web_resolver: web_arc,
|
||||
interval_secs: 999,
|
||||
|
||||
Reference in New Issue
Block a user