g1t/services/repos/migrations/0013_backups.sql
| 1 | -- Nightly backups of every repository, outside the git store |
| 2 | -- (src/backups.rs; docs/ARTIFACTS.md, R11). One row per repository that |
| 3 | -- has been queued at least once: its last backup, and the job in hand. |
| 4 | -- |
| 5 | -- status: idle | queued | running. The nightly cron queues the |
| 6 | -- repositories whose refs moved since their last backup; the runner's |
| 7 | -- sweep claims queued ones (`claim_backups`) and starts a sandbox for |
| 8 | -- each; the sandbox's `backup_complete` or `backup_fail` makes it idle |
| 9 | -- again, or queued for another try. |
| 10 | -- queued_ms, claimed_ms: milliseconds since the epoch. A job running past |
| 11 | -- its lease (3 hours) goes back in the queue. |
| 12 | -- attempts: tries tonight; past 3 it waits for the next night. |
| 13 | -- last_error: why the last try failed. |
| 14 | -- |
| 15 | -- The job in hand, while running: |
| 16 | -- job_id, token_hash: the job, and the SHA-256 of the token its sandbox |
| 17 | -- holds (the only credential it has for g1t). |
| 18 | -- target_version: the repository's refs_version when the clone began, |
| 19 | -- which the backup is recorded at once done. |
| 20 | -- backed_from_ms: when that was. |
| 21 | -- store_key: the repository's name in the git store, for its meters. |
| 22 | -- upload_key, upload_id: the bundle's key in storage, and its multipart |
| 23 | -- upload. upload_kind: full | incr. upload_entry: the entry's id in the |
| 24 | -- manifest (`20261006T025300Z`). |
| 25 | -- prerequisites: JSON array, the commits the bundle leaves out. |
| 26 | -- |
| 27 | -- The last backup: |
| 28 | -- refs_version: the refs_version it was cut at. The repository is due |
| 29 | -- again once its own goes past this, or once a credential that can push |
| 30 | -- is handed out after backed_up_ms (repos.refs_open_until). |
| 31 | -- backed_up_ms: when its clone began. |
| 32 | -- tips: JSON object, every ref it held by name: the next bundle's |
| 33 | -- prerequisites. The manifest in storage says the same, and is what a |
| 34 | -- restore reads. |
| 35 | -- last_entry: its id in the manifest. When the manifest's last entry is |
| 36 | -- another, the next backup is full. |
| 37 | CREATE TABLE repo_backups ( |
| 38 | repo_id TEXT PRIMARY KEY, |
| 39 | status TEXT NOT NULL DEFAULT 'idle', |
| 40 | queued_ms INTEGER, |
| 41 | claimed_ms INTEGER, |
| 42 | attempts INTEGER NOT NULL DEFAULT 0, |
| 43 | last_error TEXT, |
| 44 | job_id TEXT, |
| 45 | token_hash TEXT, |
| 46 | target_version INTEGER, |
| 47 | backed_from_ms INTEGER, |
| 48 | store_key TEXT, |
| 49 | upload_key TEXT, |
| 50 | upload_id TEXT, |
| 51 | upload_kind TEXT, |
| 52 | upload_entry TEXT, |
| 53 | prerequisites TEXT, |
| 54 | refs_version INTEGER, |
| 55 | backed_up_ms INTEGER, |
| 56 | tips TEXT, |
| 57 | last_entry TEXT |
| 58 | ); |
| 59 | CREATE INDEX repo_backups_queue ON repo_backups (status, queued_ms); |
| 60 | CREATE UNIQUE INDEX repo_backups_job ON repo_backups (job_id) WHERE job_id IS NOT NULL; |
| 61 | |
| 62 | -- A backup's clone is metered as `internal.git.backup_fetch`: an operation |
| 63 | -- on g1t's own bill, never on a workspace's. |
| 64 | INSERT INTO operation_mapping (meter, cost_operations, billable_operations, note, updated_at) VALUES |
| 65 | ('internal.git.backup_fetch', 1, 0, 'Nightly backup clone (R11): g1t''s cost, not the workspace''s', '2026-10-06T00:00:00Z'); |