g1t/services/repos/migrations/0014_namespace_moves.sql
| 1 | -- Moving a repository from one git store namespace to another |
| 2 | -- (src/moves.rs; docs/ARTIFACTS.md, R7). Additive; nothing is backfilled, |
| 3 | -- and nothing moves until an operator asks. |
| 4 | -- |
| 5 | -- writes_paused_until: milliseconds since the epoch. Until then nothing |
| 6 | -- writes to the repository: pushes wait up to 20 seconds for it to pass, |
| 7 | -- then are told to try again; merges, commits from the web and handed-out |
| 8 | -- push credentials the same. Set while a move copies the repository and |
| 9 | -- its pull requests' working copies, cleared when it ends either way, and |
| 10 | -- it passes on its own should a move die half way. |
| 11 | -- writes_paused_for: why, in words (`moving to g1t-us-1`). |
| 12 | ALTER TABLE repos ADD COLUMN writes_paused_until INTEGER; |
| 13 | ALTER TABLE repos ADD COLUMN writes_paused_for TEXT; |
| 14 | |
| 15 | -- One row per move asked for. The hourly sweep (`23 * * * *`) runs the |
| 16 | -- queued ones, oldest first, one at a time. |
| 17 | -- |
| 18 | -- status: queued | moving | moved | failed | cleaned | diverged. |
| 19 | -- moved: the repository reads and writes in its new namespace; the copy |
| 20 | -- in the old one is kept MOVE_KEEP_DAYS (7) in case of a rollback, then |
| 21 | -- deleted (cleaned). diverged: the old copy's refs changed after the |
| 22 | -- move (a push that slipped past the pause), so it is kept and an |
| 23 | -- operator reconciles it. |
| 24 | -- to_namespace: where it goes. |
| 25 | -- requested_by: who asked, in words. |
| 26 | -- note: the last thing that happened (why it waits, why it failed). |
| 27 | CREATE TABLE repo_moves ( |
| 28 | id TEXT PRIMARY KEY, |
| 29 | repo_id TEXT NOT NULL, |
| 30 | to_namespace TEXT NOT NULL, |
| 31 | status TEXT NOT NULL DEFAULT 'queued', |
| 32 | requested_by TEXT, |
| 33 | queued_ms INTEGER NOT NULL, |
| 34 | started_ms INTEGER, |
| 35 | finished_ms INTEGER, |
| 36 | cleaned_ms INTEGER, |
| 37 | attempts INTEGER NOT NULL DEFAULT 0, |
| 38 | note TEXT |
| 39 | ); |
| 40 | CREATE INDEX repo_moves_queue ON repo_moves (status, queued_ms); |
| 41 | -- At most one move in hand per repository. |
| 42 | CREATE UNIQUE INDEX repo_moves_active ON repo_moves (repo_id) WHERE status IN ('queued', 'moving'); |
| 43 | |
| 44 | -- What each move copied: the repository and each of its pull requests' |
| 45 | -- working copies, from one key to another, with every ref as copied. |
| 46 | -- |
| 47 | -- name: the key's name without its namespace. A name with a copy not yet |
| 48 | -- cleaned stays taken (registry.rs `claim_store_key`), so a new |
| 49 | -- repository never adopts an old copy left behind. |
| 50 | -- refs: JSON object, ref name to object, as copied; the old copy is |
| 51 | -- deleted only while it still says the same. |
| 52 | CREATE TABLE repo_move_copies ( |
| 53 | move_id TEXT NOT NULL, |
| 54 | repo_id TEXT NOT NULL, |
| 55 | from_key TEXT NOT NULL, |
| 56 | to_key TEXT NOT NULL, |
| 57 | name TEXT NOT NULL, |
| 58 | refs TEXT NOT NULL DEFAULT '{}', |
| 59 | cleaned_ms INTEGER, |
| 60 | PRIMARY KEY (move_id, repo_id) |
| 61 | ); |
| 62 | CREATE INDEX repo_move_copies_name ON repo_move_copies (name) WHERE cleaned_ms IS NULL; |