47 lines · 1.9 KB
import { first, run } from "../db";

/** Most bytes one account's fork pull requests may hold bridged into other repos at once. */
export const MAX_OPEN_BRIDGED_BYTES = 1024 * 1024 * 1024;

export type BridgeCharge = { headOwnerId: string; baseRepoId: string; number: number };

/** The bytes still pinned by bridges of pull requests whose head repo `ownerId` owns. */
export async function openBridgedBytes(ownerId: string): Promise<number> {
  const row = await first<{ total: number | null }>(
    `SELECT SUM(p.bridged_bytes) AS total FROM pull_requests p JOIN repos r ON r.id = p.head_repo_id
     WHERE r.owner_id = ? AND p.bridged_bytes > 0`,
    ownerId,
  );
  return row?.total ?? 0;
}

/** Whether the head owner may start another relay; bridges reusing objects the target already has stay free. */
export async function bridgeQuotaAvailable(charge: BridgeCharge): Promise<boolean> {
  return (await openBridgedBytes(charge.headOwnerId)) < MAX_OPEN_BRIDGED_BYTES;
}

export async function recordBridgedBytes(charge: BridgeCharge, bytes: number): Promise<void> {
  if (bytes <= 0) return;
  await run(
    `UPDATE pull_requests SET bridged_bytes = bridged_bytes + ?
     WHERE repo_id = ? AND issue_id = (SELECT id FROM issues WHERE repo_id = ? AND number = ?)`,
    bytes,
    charge.baseRepoId,
    charge.baseRepoId,
    charge.number,
  );
}

/** Releases a pull request's charge once its hidden refs are gone. */
export async function releaseBridgedBytes(issueId: string): Promise<void> {
  await run("UPDATE pull_requests SET bridged_bytes = 0 WHERE issue_id = ? AND bridged_bytes > 0", issueId);
}

/** Releases every charge for pull requests touching `repoId` after all of their hidden refs were dropped. */