| 1 | import { Container } from "@cloudflare/containers"; |
| 2 | import type { StopParams } from "@cloudflare/containers"; |
| 3 | import type { Env } from "../env.js"; |
| 4 | import { ImportService } from "./service.js"; |
| 5 | |
| 6 | /** |
| 7 | * One container per GitHub import's Git transfer: the runner image in import |
| 8 | * mode (`DIFFINERY_IMPORT_ID`), which clones from GitHub, pushes to Diffinery in |
| 9 | * size-bounded chunks and reports back through the import's agent endpoints. |
| 10 | */ |
| 11 | export class ImportContainer extends Container<Env> { |
| 12 | // The agent makes no inbound requests, so activity-based sleep is the only timer; a little over the 6h transfer cap. |
| 13 | override sleepAfter = "7h"; |
| 14 | override enableInternet = true; |
| 15 | |
| 16 | async startImport(input: { importId: string; token: string; apiUrl: string; chunkBytes?: number; stamp?: string }): Promise<void> { |
| 17 | await this.ctx.storage.put("import", input.importId); |
| 18 | // The attempt-try this container serves, so a late stop of an old try is ignored (M4 / Correctness 7). |
| 19 | if (input.stamp) await this.ctx.storage.put("stamp", input.stamp); |
| 20 | await this.start({ |
| 21 | envVars: { |
| 22 | DIFFINERY_API_URL: input.apiUrl, |
| 23 | DIFFINERY_IMPORT_ID: input.importId, |
| 24 | DIFFINERY_IMPORT_TOKEN: input.token, |
| 25 | ...(input.chunkBytes ? { DIFFINERY_IMPORT_CHUNK_BYTES: String(input.chunkBytes) } : {}), |
| 26 | }, |
| 27 | }); |
| 28 | } |
| 29 | |
| 30 | async stopImport(): Promise<void> { |
| 31 | if (this.ctx.container?.running) await this.stop("SIGTERM"); |
| 32 | } |
| 33 | |
| 34 | override async onStop(params: StopParams): Promise<void> { |
| 35 | const importId = await this.ctx.storage.get<string>("import"); |
| 36 | if (!importId) return; |
| 37 | const stamp = await this.ctx.storage.get<string>("stamp"); |
| 38 | // A transfer that stopped without reporting (crash, out of memory, platform restart) fails so the workflow can retry it; |
| 39 | // a stale stamp (an old try stopping late) is ignored by the service. |
| 40 | await new ImportService(this.env).gitStopped(importId, params.exitCode ?? null, stamp); |
| 41 | await this.ctx.storage.delete("import"); |
| 42 | await this.ctx.storage.delete("stamp"); |
| 43 | } |
| 44 | |
| 45 | override onError(error: unknown): void { |
| 46 | console.error("import container error", error); |
| 47 | } |
| 48 | } |