Prune stale plugin metadata

This commit is contained in:
npc0-hue
2026-09-14 17:32:51 +08:00
parent ecdca8e28b
commit 63e2340db7
10 changed files with 659 additions and 13 deletions
+64
View File
@@ -1933,6 +1933,70 @@ func TestCoreServiceUpsertsDuplicateGamePluginManifest(t *testing.T) {
}
}
func TestCoreServiceKeepsOnlyLatestPluginVersionAndMigratesReferences(t *testing.T) {
svc := newTestCoreService()
stale := validPluginManifestRegistration()
stale.Manifest.ID = "game.scum.codex.20260804095301"
stale.Manifest.Name = "SCUM Server"
stale.Manifest.Version = "0.1.4"
stale.Manifest.Server.Type = "scum"
stale.Manifest.Server.DisplayName = "SCUM Dedicated Server"
stale.ManifestRef = "plugins/examples/scum-server-plugin/game.scum.codex.20260804095301/manifest.json"
if _, err := svc.RegisterGamePluginManifest(stale); err != nil {
t.Fatalf("register stale manifest: %v", err)
}
if _, err := svc.CreateServerInstance(domain.ServerInstance{ID: "stale-plugin-server", PluginID: stale.Manifest.ID, PluginVersion: stale.Manifest.Version, Name: "SCUM Old Plugin"}); err != nil {
t.Fatalf("create stale plugin server: %v", err)
}
if err := svc.store.RuntimeBindings().Create(domain.RuntimeBinding{ID: "runtime-binding-stale-plugin-server", ServerInstanceID: "stale-plugin-server", PluginID: stale.Manifest.ID, PluginVersion: stale.Manifest.Version, ProfileKey: "local", Mode: "local-process", Status: domain.RuntimeBindingStatusComplete, CreatedAt: fixedTime, UpdatedAt: fixedTime}); err != nil {
t.Fatalf("create stale runtime binding: %v", err)
}
if err := svc.store.PluginDataRecords().Create(domain.PluginDataRecord{ID: pluginDataID("stale-plugin-server", stale.Manifest.ID, "scum_gifts", "starter"), PluginID: stale.Manifest.ID, ServerInstanceID: "stale-plugin-server", Collection: "scum_gifts", Key: "starter", Value: map[string]any{"name": "Starter"}, CreatedAt: fixedTime, UpdatedAt: fixedTime}); err != nil {
t.Fatalf("seed plugin config data: %v", err)
}
if err := svc.store.PluginDataRecords().Create(domain.PluginDataRecord{ID: pluginDataID("stale-plugin-server", stale.Manifest.ID, "scum_trajectories", "point-1"), PluginID: stale.Manifest.ID, ServerInstanceID: "stale-plugin-server", Collection: "scum_trajectories", Key: "point-1", Value: map[string]any{"source": "legacy"}, CreatedAt: fixedTime, UpdatedAt: fixedTime}); err != nil {
t.Fatalf("seed legacy projection data: %v", err)
}
latest := validPluginManifestRegistration()
latest.Manifest.ID = "game.scum"
latest.Manifest.Name = "SCUM Server"
latest.Manifest.Version = "0.1.15"
latest.Manifest.Server.Type = "scum"
latest.Manifest.Server.DisplayName = "SCUM Dedicated Server"
latest.ManifestRef = "artifact://manifests/game.scum/0.1.15"
registered, err := svc.RegisterGamePluginManifest(latest)
if err != nil {
t.Fatalf("register latest manifest: %v", err)
}
if registered.ID != "game.scum" || registered.Version != "0.1.15" {
t.Fatalf("expected latest plugin to win, got %+v", registered)
}
if _, err := svc.GetGamePlugin(stale.Manifest.ID); !errors.Is(err, repo.ErrNotFound) {
t.Fatalf("expected stale plugin record to be removed, got %v", err)
}
plugins, err := svc.ListGamePlugins(domain.GamePluginFilter{ServerType: "scum", Status: domain.GamePluginStatusInstalled})
if err != nil || len(plugins) != 1 || plugins[0].ID != "game.scum" || plugins[0].Version != "0.1.15" {
t.Fatalf("expected only latest SCUM plugin, plugins=%+v err=%v", plugins, err)
}
server, err := svc.GetServerInstance("stale-plugin-server")
if err != nil || server.PluginID != "game.scum" || server.PluginVersion != "0.1.15" {
t.Fatalf("expected server to migrate to latest plugin, server=%+v err=%v", server, err)
}
binding, err := svc.store.RuntimeBindings().Get("runtime-binding-stale-plugin-server")
if err != nil || binding.PluginID != "game.scum" || binding.PluginVersion != "0.1.15" {
t.Fatalf("expected runtime binding to migrate to latest plugin, binding=%+v err=%v", binding, err)
}
configRecords, err := svc.store.PluginDataRecords().List(domain.PluginDataFilter{PluginID: "game.scum", ServerInstanceID: "stale-plugin-server", Collection: "scum_gifts"})
if err != nil || len(configRecords) != 1 || configRecords[0].Key != "starter" {
t.Fatalf("expected plugin config data to migrate, records=%+v err=%v", configRecords, err)
}
legacyRecords, err := svc.store.PluginDataRecords().List(domain.PluginDataFilter{ServerInstanceID: "stale-plugin-server", Collection: "scum_trajectories"})
if err != nil || len(legacyRecords) != 0 {
t.Fatalf("expected legacy SCUM projection data to be dropped, records=%+v err=%v", legacyRecords, err)
}
}
func TestCoreServiceRejectsUnsafeGamePluginManifest(t *testing.T) {
svc := newTestCoreService()
registration := validPluginManifestRegistration()