118 lines · 3.6 KB
import { randomId } from "../crypto";
import { run } from "../db";
import { recordUsage } from "./record";

/** Wraps a response body so `onDone(bytes)` runs once the body has streamed (or failed) to the client. */
export function countingBody(
  body: ReadableStream<Uint8Array> | null,
  onDone: (bytes: number) => void,
  onChunk?: (chunk: Uint8Array) => void,
) {
  if (!body) {
    onDone(0);
    return null;
  }
  let bytes = 0;
  let done = false;
  const finish = () => {
    if (done) return;
    done = true;
    onDone(bytes);
  };
  return body.pipeThrough(
    new TransformStream<Uint8Array, Uint8Array>({
      transform(chunk, controller) {
        bytes += chunk.byteLength;
        onChunk?.(chunk);
        controller.enqueue(chunk);
      },
      flush: finish,
    }),
  );
}

/**
 * Meters one git operation through the proxy: a count (`op` = push, fetch or clone) plus bytes in or out.
 * Pushes also grow the repository storage estimate by the received pack size.
 */
export async function meterGitOp(input: {
  accountId: string;
  repoId: string;