Keep SCUM poll jobs and drop orphan job log streams

The metadata snapshot deleted every SCUM sqlite query job while persisting, so
the recurring database poll lost its job records as soon as anything wrote the
snapshot and left its stdout/stderr streams behind. Those polls are the only
producer for the platform scum_user and scum_vehicle tables, and the service
already retires older terminal polls with their streams, so the snapshot no
longer drops them.

Startup now removes job log streams whose job no longer exists, keeping the
autonomous lifecycle streams the Run posts without a platform job. That clears
the streams left by the removed poll producers instead of carrying them in
every snapshot.
This commit is contained in:
npc0-hue
2026-09-16 18:41:44 +08:00
parent 6985f77963
commit 6488f6b31d
4 changed files with 124 additions and 39 deletions
-37
View File
@@ -17,7 +17,6 @@ func normalizeStoreSnapshot(snapshot StoreSnapshot) StoreSnapshot {
snapshot.PluginLifecycles = rewriteSnapshotPluginLifecycles(snapshot.PluginLifecycles, replacements)
snapshot.AIConfigDiffs = rewriteSnapshotAIConfigDiffs(snapshot.AIConfigDiffs, replacements)
snapshot.PluginDataRecords = retainedSnapshotPluginData(snapshot.PluginDataRecords, replacements)
snapshot.Jobs = retainedSnapshotJobs(snapshot.Jobs, snapshot.ServerInstances, plugins)
return snapshot
}
@@ -119,38 +118,6 @@ func retainedSnapshotPluginData(values []domain.PluginDataRecord, replacements m
return out
}
func retainedSnapshotJobs(values []domain.Job, instances []domain.ServerInstance, plugins []domain.GamePlugin) []domain.Job {
pluginByID := map[string]domain.GamePlugin{}
for _, plugin := range plugins {
pluginByID[plugin.ID] = plugin
}
serverPlugin := map[string]domain.GamePlugin{}
for _, instance := range instances {
if plugin, ok := pluginByID[instance.PluginID]; ok {
serverPlugin[instance.ID] = plugin
}
}
out := make([]domain.Job, 0, len(values))
for _, job := range values {
if isLegacySCUMSQLiteQueryJob(job, serverPlugin) {
continue
}
out = append(out, domain.CopyJob(job))
}
return out
}
func isLegacySCUMSQLiteQueryJob(job domain.Job, serverPlugin map[string]domain.GamePlugin) bool {
if job.Capability != domain.JobCapabilityRemoteRunDBSQLiteQuery {
return false
}
plugin, ok := serverPlugin[job.ServerInstanceID]
if !ok {
return false
}
return isSCUMGamePlugin(plugin)
}
func isLegacySCUMPluginData(pluginID string, collection string) bool {
if !isSCUMPluginID(pluginID) {
return false
@@ -163,10 +130,6 @@ func isLegacySCUMPluginData(pluginID string, collection string) bool {
}
}
func isSCUMGamePlugin(plugin domain.GamePlugin) bool {
return strings.EqualFold(strings.TrimSpace(plugin.ServerType), "scum") || isSCUMPluginID(plugin.ID)
}
func isSCUMPluginID(pluginID string) bool {
canonical := domain.CanonicalGamePluginID(pluginID)
return canonical == "game.scum" || canonical == "server.scum"