g1t/services/repos/migrations/0011_artifacts_meters_forks_health.sql
| 1 | -- Pull request working copies (`pulls--<pull id>` in the git store) are |
| 2 | -- removed some days after their pull request merges or closes |
| 3 | -- (src/forks.rs), in the hourly sweep. Their rows stay, so the pull |
| 4 | -- request's page still reads its changes, from the repository it came from. |
| 5 | -- |
| 6 | -- retire_after: RFC 3339. Set when the pull request merges or closes, |
| 7 | -- cleared if it reopens in time. The sweep retires it once this passes. |
| 8 | -- retired_at: RFC 3339. When its git data was removed. Null while it has some. |
| 9 | -- retired_head: the commit its branch pointed to when it was removed. Kept |
| 10 | -- in the repository it came from: as part of its history once merged, or |
| 11 | -- under refs/pull/<pull id>/head. Reads of the working copy are answered |
| 12 | -- from there; anything that writes to it makes it again (`revive`). |
| 13 | ALTER TABLE repos ADD COLUMN retire_after TEXT; |
| 14 | ALTER TABLE repos ADD COLUMN retired_at TEXT; |
| 15 | ALTER TABLE repos ADD COLUMN retired_head TEXT; |
| 16 | CREATE INDEX repos_retiring ON repos (retire_after) WHERE retire_after IS NOT NULL AND retired_at IS NULL; |
| 17 | |
| 18 | -- How the git store has been answering, by the minute, for the status |
| 19 | -- page's "Git storage" part (`store_health`). Each isolate adds up its own |
| 20 | -- calls and writes them now and then, after its answers have gone back |
| 21 | -- (src/health.rs). Kept for a day. |
| 22 | -- |
| 23 | -- store: the git store namespace (`g1t`, or a shard's). |
| 24 | -- minute: YYYY-MM-DDTHH:MM, UTC. |
| 25 | -- calls, errors: calls made and how many failed (after retries). |
| 26 | -- rate_limited: of those, how many the store refused for its rate limit. |
| 27 | -- rejected: calls not made because the namespace's breaker was open. |
| 28 | -- ms_total: summed duration of the calls, for the mean. |
| 29 | CREATE TABLE store_health ( |
| 30 | store TEXT NOT NULL, |
| 31 | minute TEXT NOT NULL, |
| 32 | calls INTEGER NOT NULL DEFAULT 0, |
| 33 | errors INTEGER NOT NULL DEFAULT 0, |
| 34 | rate_limited INTEGER NOT NULL DEFAULT 0, |
| 35 | rejected INTEGER NOT NULL DEFAULT 0, |
| 36 | ms_total INTEGER NOT NULL DEFAULT 0, |
| 37 | PRIMARY KEY (store, minute) |
| 38 | ); |
| 39 | |
| 40 | -- Every interaction with the git store, as raw meters: what g1t asked of it, |
| 41 | -- by day, workspace and repository (src/meters.rs). Counted in each isolate |
| 42 | -- and written after answers have gone back, never on the request path. |
| 43 | -- Cloudflare has not said exactly what it bills as an "operation" during |
| 44 | -- the beta, so everything is kept and what counts is decided by data |
| 45 | -- (`operation_mapping`), not code. |
| 46 | -- |
| 47 | -- day: YYYY-MM-DD, UTC. |
| 48 | -- store: the git store namespace (`g1t`, or a shard's). |
| 49 | -- repo: the repository's name in the git store (`acme--rocket`, |
| 50 | -- `pulls--<pull id>`): what Cloudflare's metrics call `repositoryName`. |
| 51 | -- workspace: the workspace it belongs to, when known (`pulls` for a pull |
| 52 | -- request's working copy; join `repos.fork_of` for its repository's). |
| 53 | -- meter: what was asked. Git over HTTPS from people and tools: |
| 54 | -- `git.info_refs`, `git.ls_refs`, `git.fetch`, `git.receive_pack`; by |
| 55 | -- g1t itself (landing, catching up, mirrors, listing branches): |
| 56 | -- `internal.git.info_refs`, `internal.git.fetch`, |
| 57 | -- `internal.git.receive_pack`; calls on the binding: `binding.<method>` |
| 58 | -- (`binding.get`, `binding.create_token`, `binding.log`, ...). |
| 59 | -- count, bytes_in, bytes_out: how many, and the bytes sent to and received |
| 60 | -- from the store where known (0 where not). |
| 61 | CREATE TABLE artifacts_meters ( |
| 62 | day TEXT NOT NULL, |
| 63 | store TEXT NOT NULL, |
| 64 | repo TEXT NOT NULL, |
| 65 | workspace TEXT NOT NULL DEFAULT '', |
| 66 | meter TEXT NOT NULL, |
| 67 | count INTEGER NOT NULL DEFAULT 0, |
| 68 | bytes_in INTEGER NOT NULL DEFAULT 0, |
| 69 | bytes_out INTEGER NOT NULL DEFAULT 0, |
| 70 | PRIMARY KEY (day, store, repo, meter) |
| 71 | ); |
| 72 | CREATE INDEX artifacts_meters_by_workspace ON artifacts_meters (workspace, day); |
| 73 | |
| 74 | -- Which meters are git operations, and how many each is worth: what |
| 75 | -- Cloudflare bills g1t (`cost_operations`, for reconciling with its |
| 76 | -- invoice) and what a workspace is counted for (`billable_operations`, |
| 77 | -- added to `git_operations`, which billing charges past the free amount). |
| 78 | -- Changed by data (`set_operation_mapping`) the day Cloudflare says what it |
| 79 | -- counts; no deploy. A meter not listed counts as 0 for both. |
| 80 | -- |
| 81 | -- The defaults are what Cloudflare most plausibly bills: a clone or fetch |
| 82 | -- (one per upload-pack request that fetches objects), a push (one per |
| 83 | -- receive-pack), and making, forking and deleting a repository. Listing |
| 84 | -- refs, ref answers g1t served from its own cache, and reads through the |
| 85 | -- binding count for nothing. |
| 86 | CREATE TABLE operation_mapping ( |
| 87 | meter TEXT PRIMARY KEY, |
| 88 | cost_operations REAL NOT NULL DEFAULT 0, |
| 89 | billable_operations REAL NOT NULL DEFAULT 0, |
| 90 | note TEXT, |
| 91 | updated_at TEXT NOT NULL |
| 92 | ); |
| 93 | INSERT INTO operation_mapping (meter, cost_operations, billable_operations, note, updated_at) VALUES |
| 94 | ('git.fetch', 1, 1, 'Clone or fetch: an upload-pack request that fetches objects', '2026-10-06T00:00:00Z'), |
| 95 | ('git.receive_pack', 1, 1, 'Push', '2026-10-06T00:00:00Z'), |
| 96 | ('internal.git.fetch', 1, 1, 'g1t fetching objects: landing, catching up, mirrors', '2026-10-06T00:00:00Z'), |
| 97 | ('internal.git.receive_pack', 1, 1, 'g1t pushing: landing, catching up, commits from the web, mirrors', '2026-10-06T00:00:00Z'), |
| 98 | ('binding.create', 1, 1, 'A repository made', '2026-10-06T00:00:00Z'), |
| 99 | ('binding.fork', 1, 1, 'A pull request''s working copy made', '2026-10-06T00:00:00Z'), |
| 100 | ('binding.delete', 1, 1, 'A repository or working copy deleted', '2026-10-06T00:00:00Z'); |