From 65fd1590aa1dbf45de2c5b1a8d60f765ea24c594 Mon Sep 17 00:00:00 2001 From: dawn Date: Wed, 21 Oct 2026 22:06:44 +0300 Subject: [PATCH] spindle/db: keep the legacy log renames until the log dir exists Signed-off-by: dawn --- spindle/db/log_migration.go | 16 ++++++++-- spindle/db/log_migration_wait_test.go | 42 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 spindle/db/log_migration_wait_test.go diff --git a/spindle/db/log_migration.go b/spindle/db/log_migration.go index ff16e7729..c725f1d3b 100644 --- a/spindle/db/log_migration.go +++ b/spindle/db/log_migration.go @@ -101,11 +101,11 @@ func (d *DB) MigratePipelineLogFiles(logDir string) error { return nil } if logDir == "" { - return d.finishPipelineLogMigration() + return d.finishUnlessRenamesWait() } if _, err := os.Stat(logDir); err != nil { if os.IsNotExist(err) { - return d.finishPipelineLogMigration() + return d.finishUnlessRenamesWait() } return err } @@ -192,6 +192,18 @@ func (d *DB) MigratePipelineLogFiles(logDir string) error { return d.finishPipelineLogMigration() } +// the renames stay queued in case a missing log dir is just an unmounted disk +func (d *DB) finishUnlessRenamesWait() error { + var waiting int + if err := d.QueryRow(`select count(*) from pipeline_log_renames`).Scan(&waiting); err != nil { + return err + } + if waiting > 0 { + return nil + } + return d.finishPipelineLogMigration() +} + func (d *DB) finishPipelineLogMigration() error { _, err := d.Exec(`drop table if exists pipeline_log_renames`) return err diff --git a/spindle/db/log_migration_wait_test.go b/spindle/db/log_migration_wait_test.go new file mode 100644 index 000000000..71a2f3325 --- /dev/null +++ b/spindle/db/log_migration_wait_test.go @@ -0,0 +1,42 @@ +package db + +import ( + "context" + "os" + "path/filepath" + "testing" + + "tangled.org/core/spindle/models" +) + +func TestLogRenamesWaitForALogDirThatIsMissingAtBoot(t *testing.T) { + database, err := Make(context.Background(), filepath.Join(t.TempDir(), "spindle.db")) + if err != nil { + t.Fatal(err) + } + defer database.Close() + pipelineID := models.PipelineId("3mu2xwiorc2xl") + if _, err := database.Exec(`insert into pipeline_log_renames (knot, pipeline_id, workflow) values (?, ?, ?)`, "knot.test", pipelineID, "ci.yml"); err != nil { + t.Fatal(err) + } + + logDir := filepath.Join(t.TempDir(), "logs") + if err := database.MigratePipelineLogFiles(logDir); err != nil { + t.Fatal(err) + } + + if err := os.MkdirAll(logDir, 0o755); err != nil { + t.Fatal(err) + } + oldPath := models.LegacyLogFilePath(logDir, "knot.test", pipelineID, "ci.yml") + if err := os.WriteFile(oldPath, []byte("old"), 0o600); err != nil { + t.Fatal(err) + } + if err := database.MigratePipelineLogFiles(logDir); err != nil { + t.Fatal(err) + } + newPath := models.LogFilePath(logDir, models.WorkflowId{PipelineId: pipelineID, Name: "ci.yml"}) + if data, err := os.ReadFile(newPath); err != nil || string(data) != "old" { + t.Fatalf("log after the dir showed up = %q, %v, want it renamed", data, err) + } +} -- 2.54.0