66 lines · 2.4 KB
import { all, first } from "../db";
import { accountDb, repoDb, type ScopedDb } from "../scoped-db";
import { locate, type LocatorKind } from "../scoped-db/locators";

/** Ids of runs, jobs and runners never move between scopes, so a resolved scope can be remembered per isolate. */
const cache = new Map<string, string>();
const CACHE_LIMIT = 5000;

async function cachedLocate(kind: LocatorKind, key: string): Promise<string | null> {
  const cacheKey = `${kind}:${key}`;
  const hit = cache.get(cacheKey);
  if (hit) return hit;
  const scopeId = await locate(kind, key);
  if (scopeId) {
    if (cache.size >= CACHE_LIMIT) cache.clear();
    cache.set(cacheKey, scopeId);
  }
  return scopeId;
}

/** Remembers a scope just registered so the next lookup in this isolate skips D1. */
export function rememberScope(kind: LocatorKind, key: string, scopeId: string): void {
  if (cache.size >= CACHE_LIMIT) cache.clear();
  cache.set(`${kind}:${key}`, scopeId);
}

export function jobRepoId(jobId: string): Promise<string | null> {
  return cachedLocate("workflow_job", jobId);
}

export function runRepoId(runId: string): Promise<string | null> {
  return cachedLocate("workflow_run", runId);
}

/** The repository database holding a job, or null for an unknown job. */
export async function jobDb(jobId: string): Promise<ScopedDb | null> {
  const repoId = await jobRepoId(jobId);
  return repoId ? repoDb(repoId) : null;
}