/** * Record-read helpers that prefer Slingshot (microcosm's edge cache) and fall * back to the regular atproto agent (the PDS / AppView) on miss or error. * * Use this ONLY for read-only public lookups. Do NOT use it for read-then-write * flows that rely on `swapRecord`/CID optimistic concurrency — those must read * from the authoritative PDS via the agent, since a cache can be stale. */ import {type AtpAgent} from '@atproto/api' import {MICROCOSM_ENABLED} from '#/lib/microcosm/config' import {getRecord as slingshotGetRecord} from '#/lib/microcosm/slingshot' import {logger} from '#/logger' export type GetRecordResult = { uri: string cid?: string value: unknown } /** * Fetch a single public record. Tries Slingshot first (when microcosm is * enabled), then falls back to the agent. Returns the same `{uri, cid, value}` * shape as `com.atproto.repo.getRecord`. */ export async function getPublicRecord( agent: AtpAgent, args: {repo: string; collection: string; rkey: string}, signal?: AbortSignal, ): Promise { if (MICROCOSM_ENABLED) { try { const res = await slingshotGetRecord(args, signal) return {uri: res.uri, cid: res.cid, value: res.value} } catch (e) { // Cache miss / transient error — fall through to the agent. Log at debug // so we can see hit-rate without spamming. logger.debug('slingshot getRecord miss, falling back to agent', { safeMessage: String(e), }) } } const res = await agent.api.com.atproto.repo.getRecord(args) return {uri: res.data.uri, cid: res.data.cid, value: res.data.value} }