Feature 04 task 5: Async job runner and GET /api/v1/jobs/{id} (#29)
Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com> Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
This commit was merged in pull request #29.
This commit is contained in:
@@ -175,8 +175,8 @@ func TestMigrateEmbeddedMigrations(t *testing.T) {
|
||||
if err := Migrate(context.Background(), s.Writer, migrations.FS); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := versions(migrationRows(t, s)); got != "0000_bootstrap,0001_init,0002_household_settings_updated_by" {
|
||||
t.Errorf("versions = %q, want 0000_bootstrap,0001_init,0002_household_settings_updated_by", got)
|
||||
if got := versions(migrationRows(t, s)); got != "0000_bootstrap,0001_init,0002_household_settings_updated_by,0003_jobs_status" {
|
||||
t.Errorf("versions = %q, want 0000_bootstrap,0001_init,0002_household_settings_updated_by,0003_jobs_status", got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,8 +196,8 @@ func TestMigrateBootstrapThenEmbeddedInitApplies(t *testing.T) {
|
||||
if err := Migrate(ctx, s.Writer, migrations.FS); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := versions(migrationRows(t, s)); got != "0000_bootstrap,0001_init,0002_household_settings_updated_by" {
|
||||
t.Errorf("versions = %q, want 0000_bootstrap,0001_init,0002_household_settings_updated_by", got)
|
||||
if got := versions(migrationRows(t, s)); got != "0000_bootstrap,0001_init,0002_household_settings_updated_by,0003_jobs_status" {
|
||||
t.Errorf("versions = %q, want 0000_bootstrap,0001_init,0002_household_settings_updated_by,0003_jobs_status", got)
|
||||
}
|
||||
if !tableExists(t, s, "dinners") {
|
||||
t.Error("table from 0001_init was not created")
|
||||
@@ -262,3 +262,50 @@ func TestMigrateReopenSameDataDirIsNoOp(t *testing.T) {
|
||||
t.Errorf("schema changed on reopen:\n got %v\nwant %v", afterSchema, beforeSchema)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMigrateJobsStatusMapsLegacyRows upgrades a database holding jobs in
|
||||
// every 0001 status and checks 0003 carries each row over with its status
|
||||
// mapped and every other column unchanged.
|
||||
func TestMigrateJobsStatusMapsLegacyRows(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := openTestStore(t)
|
||||
before := fstest.MapFS{}
|
||||
for _, name := range []string{"0000_bootstrap.sql", "0001_init.sql", "0002_household_settings_updated_by.sql"} {
|
||||
body, err := fs.ReadFile(migrations.FS, name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
before[name] = &fstest.MapFile{Data: body}
|
||||
}
|
||||
if err := Migrate(ctx, s.Writer, before); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
legacy := map[string]string{"pending": "queued", "running": "running", "done": "succeeded", "failed": "failed"}
|
||||
for old := range legacy {
|
||||
if _, err := s.Writer.Exec(`INSERT INTO jobs (id, kind, status, payload, result, error, started_at, finished_at, created_at, updated_at)
|
||||
VALUES (?, 'suggest', ?, '{"n":1}', '{"r":2}', 'boom', 's', 'f', 'c', 'u')`, "job-"+old, old); err != nil {
|
||||
t.Fatalf("insert %s job: %v", old, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := Migrate(ctx, s.Writer, migrations.FS); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for old, want := range legacy {
|
||||
var kind, status, payload, result, errText, startedAt, finishedAt, createdAt, updatedAt string
|
||||
if err := s.Reader.QueryRow(`SELECT kind, status, payload, result, error, started_at, finished_at, created_at, updated_at FROM jobs WHERE id = ?`, "job-"+old).
|
||||
Scan(&kind, &status, &payload, &result, &errText, &startedAt, &finishedAt, &createdAt, &updatedAt); err != nil {
|
||||
t.Fatalf("read %s job: %v", old, err)
|
||||
}
|
||||
if status != want {
|
||||
t.Errorf("%s job status = %q, want %q", old, status, want)
|
||||
}
|
||||
got := []string{kind, payload, result, errText, startedAt, finishedAt, createdAt, updatedAt}
|
||||
if wantCols := []string{"suggest", `{"n":1}`, `{"r":2}`, "boom", "s", "f", "c", "u"}; !slices.Equal(got, wantCols) {
|
||||
t.Errorf("%s job columns = %v, want %v", old, got, wantCols)
|
||||
}
|
||||
}
|
||||
if tableExists(t, s, "jobs_new") {
|
||||
t.Error("jobs_new left behind")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ func testRow(table string, i int) map[string]any {
|
||||
r["attempts"] = 0
|
||||
case "jobs":
|
||||
r["kind"] = "suggest"
|
||||
r["status"] = "pending"
|
||||
r["status"] = "queued"
|
||||
r["payload"] = "{}"
|
||||
case "schedule_runs":
|
||||
r["schedule"] = "plan_draft"
|
||||
@@ -330,7 +330,7 @@ func TestSchemaEnumChecksRejectInvalidValues(t *testing.T) {
|
||||
{"notification_prefs", "chat", 2},
|
||||
{"notification_outbox", "channel", "email"},
|
||||
{"notification_outbox", "status", "queued"},
|
||||
{"jobs", "status", "queued"},
|
||||
{"jobs", "status", "bogus"},
|
||||
{"schedule_runs", "schedule", "hourly"},
|
||||
}
|
||||
s := seededStore(t)
|
||||
|
||||
Reference in New Issue
Block a user