feat(db): 新增 0002_memory 迁移;迁移测试改用嵌入式迁移集合(数量无关,避免卡死后续迁移)
This commit is contained in:
1 parent
0a936a3202
commit
285e1e9911
3 files changed
+52
-12
No files matched your search
+30
-12
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -41,6 +42,20 @@ func registeredMigrations(t *testing.T, ctx context.Context, db *sql.DB) []strin
|
||||
return ids
|
||||
}
|
||||
|
||||
// upMigrationIDs returns the ids of the embedded up-migrations in apply order.
|
||||
func upMigrationIDs(t *testing.T) []string {
|
||||
t.Helper()
|
||||
migs, err := loadMigrations()
|
||||
if err != nil {
|
||||
t.Fatalf("loadMigrations: %v", err)
|
||||
}
|
||||
ids := make([]string, len(migs))
|
||||
for i, m := range migs {
|
||||
ids[i] = m.id
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// appMetaExists reports whether the app_meta table is present.
|
||||
func appMetaExists(t *testing.T, ctx context.Context, db *sql.DB) bool {
|
||||
t.Helper()
|
||||
@@ -60,15 +75,16 @@ func TestMigrateUp_FirstApply_正常(t *testing.T) {
|
||||
t.Fatalf("MigrateUp first call: %v", err)
|
||||
}
|
||||
|
||||
// Applies every embedded up-migration, in order.
|
||||
ids := registeredMigrations(t, ctx, db)
|
||||
if len(ids) != 1 || ids[0] != "0001_init" {
|
||||
t.Fatalf("schema_migrations = %v, want exactly [0001_init]", ids)
|
||||
if want := upMigrationIDs(t); !slices.Equal(ids, want) {
|
||||
t.Fatalf("schema_migrations = %v, want %v", ids, want)
|
||||
}
|
||||
if !appMetaExists(t, ctx, db) {
|
||||
t.Fatal("app_meta table should exist after MigrateUp")
|
||||
}
|
||||
|
||||
// applied_at must be recorded on the single row.
|
||||
// applied_at must be recorded on the first migration row.
|
||||
var appliedAt string
|
||||
if err := db.QueryRowContext(ctx, "SELECT applied_at FROM schema_migrations WHERE id = ?", "0001_init").Scan(&appliedAt); err != nil {
|
||||
t.Fatalf("read applied_at: %v", err)
|
||||
@@ -87,13 +103,14 @@ func TestMigrateUp_Idempotent_正常(t *testing.T) {
|
||||
t.Fatalf("MigrateUp first call: %v", err)
|
||||
}
|
||||
|
||||
// Second call must not re-execute or duplicate the record.
|
||||
// Second call must not re-execute or duplicate the records.
|
||||
if err := MigrateUp(ctx, db, testLogger()); err != nil {
|
||||
t.Fatalf("MigrateUp second call: %v", err)
|
||||
}
|
||||
want := upMigrationIDs(t)
|
||||
ids := registeredMigrations(t, ctx, db)
|
||||
if len(ids) != 1 {
|
||||
t.Fatalf("schema_migrations rows = %d, want 1 (idempotent), ids=%v", len(ids), ids)
|
||||
if !slices.Equal(ids, want) {
|
||||
t.Fatalf("idempotent: schema_migrations = %v, want %v", ids, want)
|
||||
}
|
||||
if !appMetaExists(t, ctx, db) {
|
||||
t.Fatal("app_meta should still exist after idempotent re-run")
|
||||
@@ -105,16 +122,17 @@ func TestMigrateDown_ThenReUp_正常(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := openMemory(t)
|
||||
|
||||
want := upMigrationIDs(t)
|
||||
if err := MigrateUp(ctx, db, testLogger()); err != nil {
|
||||
t.Fatalf("MigrateUp: %v", err)
|
||||
}
|
||||
|
||||
// Roll back the single applied migration.
|
||||
if err := MigrateDown(ctx, db, 1, testLogger()); err != nil {
|
||||
t.Fatalf("MigrateDown: %v", err)
|
||||
// Roll back every applied migration.
|
||||
if err := MigrateDown(ctx, db, len(want), testLogger()); err != nil {
|
||||
t.Fatalf("MigrateDown(all): %v", err)
|
||||
}
|
||||
if appMetaExists(t, ctx, db) {
|
||||
t.Fatal("app_meta should be dropped after MigrateDown")
|
||||
t.Fatal("app_meta should be dropped after MigrateDown(all)")
|
||||
}
|
||||
if ids := registeredMigrations(t, ctx, db); len(ids) != 0 {
|
||||
t.Fatalf("schema_migrations should be empty after rollback, got %v", ids)
|
||||
@@ -127,8 +145,8 @@ func TestMigrateDown_ThenReUp_正常(t *testing.T) {
|
||||
if !appMetaExists(t, ctx, db) {
|
||||
t.Fatal("app_meta should exist again after re-MigrateUp")
|
||||
}
|
||||
if ids := registeredMigrations(t, ctx, db); len(ids) != 1 || ids[0] != "0001_init" {
|
||||
t.Fatalf("schema_migrations = %v, want exactly [0001_init]", ids)
|
||||
if ids := registeredMigrations(t, ctx, db); !slices.Equal(ids, want) {
|
||||
t.Fatalf("schema_migrations = %v, want %v", ids, want)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS memory_items;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- M2: long-term memory items (DevDocs/design/03 §0/§3).
|
||||
-- Canonical schema reference; internal/runtime/memory reuses this table.
|
||||
CREATE TABLE IF NOT EXISTS memory_items (
|
||||
id TEXT PRIMARY KEY,
|
||||
persona_id TEXT NOT NULL,
|
||||
role_id TEXT NOT NULL DEFAULT '',
|
||||
scope TEXT NOT NULL,
|
||||
kind TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
tags TEXT NOT NULL DEFAULT '[]',
|
||||
confidence REAL NOT NULL DEFAULT 1.0,
|
||||
source_conversation TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
decay_weight REAL NOT NULL DEFAULT 1.0
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_memory_items_persona_id
|
||||
ON memory_items (persona_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_memory_items_persona_id_created_at
|
||||
ON memory_items (persona_id, created_at);
|
||||
Reference in new issue
Block a user