refactor(I5): remove one-and-done GS/IR migration tooling

The GS/IR migration cutover is complete, so the runbook tooling is dead
weight. Removed:
- services/migrators/ (gs_ingest, ir_ingest, tag_apply, ml_queue, verify,
  cleanup), tasks/migration.py, api/migrate.py (+ blueprint registration)
- MigrationRun model; alembic 0027 drops the migration_run table
- frontend LegacyMigrationCard + migration store (+ MaintenancePanel ref)
- celery include + task route + celery_signals queue mapping for migration.*
- the 1 GB MAX_CONTENT_LENGTH / MAX_FORM_MEMORY override (added solely for
  the ir_ingest upload)
- migration-surface tests (test_api_migrate, test_migration_verify,
  test_ir_ingest, test_gs_ingest, test_tag_apply)

Kept: the alembic schema-migration tests (test_migration_00XX — unrelated)
and cleanup_service.py (the permanent artist-cascade/unlink home).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 14:38:59 -04:00
parent 8979e0e377
commit 8649a13118
25 changed files with 55 additions and 2412 deletions
-83
View File
@@ -1,83 +0,0 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { useApi } from '../composables/useApi.js'
const POLL_MS = 2000
export const useMigrationStore = defineStore('migration', () => {
const api = useApi()
const activeRun = ref(null)
const recentRuns = ref([])
const error = ref(null)
const loading = ref(false)
let pollHandle = null
async function trigger(kind, params, file = null) {
loading.value = true
error.value = null
try {
let body
if (file) {
// Multipart upload for ingest kinds.
const form = new FormData()
form.append('export_file', file)
if (params && params.dry_run) form.append('dry_run', 'true')
if (params && params.force) form.append('force', 'true')
body = await api.post(`/api/migrate/${kind}`, { body: form })
} else {
body = await api.post(`/api/migrate/${kind}`, { body: params || {} })
}
await loadRun(body.run_id)
pollActive(body.run_id)
return body
} catch (e) {
error.value = e
throw e
} finally {
loading.value = false
}
}
async function loadRun(runId) {
activeRun.value = await api.get(`/api/migrate/runs/${runId}`)
}
async function loadRecent() {
recentRuns.value = await api.get('/api/migrate/runs', { params: { limit: 10 } })
}
function pollActive(runId) {
stopPolling()
pollHandle = setInterval(async () => {
try {
const run = await api.get(`/api/migrate/runs/${runId}`)
activeRun.value = run
if (run.status === 'ok' || run.status === 'error') {
stopPolling()
await loadRecent()
}
} catch (e) {
error.value = e
stopPolling()
}
}, POLL_MS)
}
function stopPolling() {
if (pollHandle) {
clearInterval(pollHandle)
pollHandle = null
}
}
const isRunning = computed(
() => activeRun.value && activeRun.value.status === 'running',
)
return {
activeRun, recentRuns, error, loading, isRunning,
trigger, loadRun, loadRecent, pollActive, stopPolling,
}
})