mirrorCodebase

tcmts.registry.mirrorCodebase · #6qqcorv7 · term · runs on the server

uses tcmts.registry.codebases, which uses tcmts.server.table, which uses tcmts.server.Table, which uses #tcm/host (database)

Mirror a listed codebase's main branch (a job: queued once its listing checks, and again every CODEBASE_EVERY_MS): ask its server, as a registry asks anyone's (public addresses, no credentials), for its main branch's head; if it moved, or the listing's URL did, fetch its namespace by hash (re-hashed as it arrives) and mount it read-only at codebaseMountFor, in place of what was there. A server that doesn't answer, or holds more than a registry takes, leaves what was mirrored, saying why.

import { IDENT_PATH } from "#codebase/tcmts/cli/codebase";
import { namesNow, within } from "#codebase/tcmts/cli/libraries";
import { fetchNamespaces, publicRemote } from "#codebase/tcmts/cli/sync";
import { codebaseMountFor, codebases, REGISTRY_LIMITS, registryCodebase } from "#codebase/tcmts/registry";

export async function mirrorCodebase(uri: string): Promise<void> {
  const found = await codebases.findOne({ uri });
  if (!found || found.value.state !== "verified") return;
  const c = found.value;
  await codebases.update(found.id, (v) => ({ ...v, triedAt: new Date() }));
  const fail = (reason: string) => codebases.update(found.id, (v) => ({ ...v, reason }));
  const why = (e: unknown) => (e as Error).message.split("\n")[0]!;
  const at = codebaseMountFor(c.did, c.name);
  if (!IDENT_PATH.test(at)) return void (await fail(`no name for it: ${at}`));
  const theirs = (await codebases.find({ did: c.did })).map((x) => x.value);
  if (theirs.some((x) => x.uri !== uri && x.mount === at))
    return void (await fail(`another of their codebases is mirrored at ${at}`));
  if (!c.mount && theirs.filter((x) => x.mount).length >= REGISTRY_LIMITS.codebasesPerAccount)
    return void (await fail(
      `the registry mirrors at most ${REGISTRY_LIMITS.codebasesPerAccount} codebases of one account`,
    ));
  const cb = registryCodebase();
  let head: string;
  let namespace: string;
  try {
    const remote = await publicRemote(c.url, `${c.did}'s codebase`);
    const main = await remote.branch("main");
    if (!main) return void (await fail(`${c.url} has no main branch`));
    head = main.head;
    if (head === c.head && c.from === c.url && c.mount === at) {
      await codebases.update(found.id, (v) => {
        const { reason: _, ...kept } = v;
        return kept;
      });
      return;
    }
    const [causal] = await remote.getCausals([head]);
    if (!causal) return void (await fail(`${c.url} is missing part of its history`));
    namespace = causal.namespace;
    await fetchNamespaces(cb, remote, [namespace], {
      maxNames: REGISTRY_LIMITS.definitionsPerRelease,
      keepLocks: true,
    });
  } catch (e) {
    return void (await fail(`${c.url} couldn't be read without a token: ${why(e)}`));
  }
  // (names as they are, and its in their place: read and written with nothing between, as jobs run side by side)
  const rows = cb.store.namespaceRows(namespace).map((x) => ({ ...x, path: `${at}.${x.path}` }));
  cb.store.setBranchNames(
    cb.store.branch().name,
    [...namesNow(cb.store).filter((n) => !within(n.path, at)), ...rows],
    `mirror ${at}`,
  );
  await codebases.update(found.id, (v) => {
    const { reason: _, ...kept } = v;
    return {
      ...kept,
      mount: at,
      head,
      from: c.url,
      definitions: rows.length,
      fetchedAt: new Date(),
    };
  });
}

uses

used by