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
+59 -2
View File
@@ -2,12 +2,18 @@ package service
import (
"errors"
"sort"
"strings"
"browser.local/platform/domain"
"browser.local/platform/repo"
)
const (
defaultPluginDataListLimit = 500
maxPluginDataListLimit = 2000
)
func (svc *CoreService) ListPluginDataForSession(sessionID string, filter domain.PluginDataFilter) ([]domain.PluginDataRecord, error) {
if err := svc.authorizePluginData(sessionID, filter.PluginID, filter.ServerInstanceID, filter.Collection); err != nil {
return nil, err
@@ -16,8 +22,18 @@ func (svc *CoreService) ListPluginDataForSession(sessionID string, filter domain
if err != nil {
return nil, err
}
if filter.Limit > 0 && len(values) > filter.Limit {
values = values[:filter.Limit]
sort.SliceStable(values, func(left, right int) bool {
if !values[left].UpdatedAt.Equal(values[right].UpdatedAt) {
return values[left].UpdatedAt.After(values[right].UpdatedAt)
}
if !values[left].CreatedAt.Equal(values[right].CreatedAt) {
return values[left].CreatedAt.After(values[right].CreatedAt)
}
return values[left].Key < values[right].Key
})
limit := boundedPluginDataLimit(filter.Limit)
if len(values) > limit {
values = values[:limit]
}
return values, nil
}
@@ -39,6 +55,9 @@ func (svc *CoreService) applyPluginDataTransaction(transaction domain.PluginData
if len(transaction.Mutations) == 0 {
return nil, validationError("plugin data mutations are required")
}
if err := svc.validatePluginDataMutations(transaction); err != nil {
return nil, err
}
stamp := svc.now()
upserts := make([]domain.PluginDataRecord, 0, len(transaction.Mutations))
deleteIDs := make([]string, 0, len(transaction.Mutations))
@@ -91,6 +110,9 @@ func (svc *CoreService) PutPluginDataForSession(sessionID string, value domain.P
if value.Value == nil {
return domain.PluginDataRecord{}, validationError("plugin data value is required")
}
if legacySCUMPluginDataCollection(value.PluginID, value.Collection) {
return domain.PluginDataRecord{}, validationError("SCUM user, vehicle, and trajectory data must be written to platform SCUM tables")
}
value.ID = pluginDataID(value.ServerInstanceID, value.PluginID, value.Collection, value.Key)
stamp := svc.now()
existing, err := svc.store.PluginDataRecords().Get(value.ID)
@@ -128,6 +150,41 @@ func (svc *CoreService) authorizePluginData(sessionID, pluginID, serverInstanceI
return nil
}
func (svc *CoreService) validatePluginDataMutations(transaction domain.PluginDataTransaction) error {
if !legacySCUMPluginDataCollection(transaction.PluginID, transaction.Collection) {
return nil
}
for _, mutation := range transaction.Mutations {
if mutation.Operation == domain.PluginDataMutationPut {
return validationError("SCUM user, vehicle, and trajectory data must be written to platform SCUM tables")
}
}
return nil
}
func boundedPluginDataLimit(requested int) int {
if requested <= 0 {
return defaultPluginDataListLimit
}
if requested > maxPluginDataListLimit {
return maxPluginDataListLimit
}
return requested
}
func legacySCUMPluginDataCollection(pluginID string, collection string) bool {
canonical := domain.CanonicalGamePluginID(pluginID)
if canonical != "game.scum" && canonical != "server.scum" {
return false
}
switch strings.ToLower(strings.TrimSpace(collection)) {
case "scum_users", "scum_players", "scum_trajectories", "scum_user_trajectories", "scum_vehicles", "scum_vehicle_trajectories", "scum_vehicle_locks":
return true
default:
return false
}
}
func pluginDataID(serverID, pluginID, collection, key string) string {
return "plugin-data-" + fingerprintID(serverID, pluginID+"\x00"+collection+"\x00"+key)
}