Prune stale plugin metadata
This commit is contained in:
@@ -728,10 +728,7 @@ func (svc *CoreService) CreateGamePlugin(plugin domain.GamePlugin) (domain.GameP
|
||||
if err := validator.ValidateGamePlugin(plugin); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
if err := svc.store.GamePlugins().Create(plugin); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
return domain.CopyGamePlugin(plugin), nil
|
||||
return svc.upsertLatestGamePlugin(plugin)
|
||||
}
|
||||
|
||||
func (svc *CoreService) RegisterGamePluginManifest(registration domain.GamePluginManifestRegistration) (domain.GamePlugin, error) {
|
||||
@@ -743,11 +740,35 @@ func (svc *CoreService) RegisterGamePluginManifest(registration domain.GamePlugi
|
||||
if err := validator.ValidateGamePlugin(plugin); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
if existing, err := svc.store.GamePlugins().Get(plugin.ID); err == nil {
|
||||
if err := svc.store.GamePlugins().Update(plugin); err != nil {
|
||||
return svc.upsertLatestGamePlugin(plugin)
|
||||
}
|
||||
|
||||
func (svc *CoreService) upsertLatestGamePlugin(plugin domain.GamePlugin) (domain.GamePlugin, error) {
|
||||
plugins, err := svc.store.GamePlugins().List(domain.GamePluginFilter{})
|
||||
if err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
identity := domain.GamePluginIdentityKey(plugin)
|
||||
var current domain.GamePlugin
|
||||
matched := make([]domain.GamePlugin, 0, len(plugins))
|
||||
for _, candidate := range plugins {
|
||||
if domain.GamePluginIdentityKey(candidate) != identity {
|
||||
continue
|
||||
}
|
||||
matched = append(matched, candidate)
|
||||
if current.ID == "" || domain.GamePluginIsNewer(candidate, current) {
|
||||
current = candidate
|
||||
}
|
||||
}
|
||||
if current.ID != "" && !domain.GamePluginIsNewer(plugin, current) {
|
||||
if err := svc.pruneOlderGamePluginVersions(current, matched); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
if err := svc.refreshServerPluginReferences(existing.ID, plugin.Version); err != nil {
|
||||
return domain.CopyGamePlugin(current), nil
|
||||
}
|
||||
|
||||
if _, err := svc.store.GamePlugins().Get(plugin.ID); err == nil {
|
||||
if err := svc.store.GamePlugins().Update(plugin); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
} else if errors.Is(err, repo.ErrNotFound) {
|
||||
@@ -757,9 +778,128 @@ func (svc *CoreService) RegisterGamePluginManifest(registration domain.GamePlugi
|
||||
} else {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
for _, stale := range matched {
|
||||
if stale.ID == plugin.ID {
|
||||
continue
|
||||
}
|
||||
if err := svc.replaceGamePluginReference(stale.ID, plugin.ID, plugin.Version); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
if err := svc.store.GamePlugins().Delete(stale.ID); err != nil && !errors.Is(err, repo.ErrNotFound) {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
}
|
||||
if err := svc.refreshServerPluginReferences(plugin.ID, plugin.Version); err != nil {
|
||||
return domain.GamePlugin{}, err
|
||||
}
|
||||
return domain.CopyGamePlugin(plugin), nil
|
||||
}
|
||||
|
||||
func (svc *CoreService) pruneOlderGamePluginVersions(latest domain.GamePlugin, plugins []domain.GamePlugin) error {
|
||||
for _, plugin := range plugins {
|
||||
if plugin.ID == latest.ID {
|
||||
continue
|
||||
}
|
||||
if err := svc.replaceGamePluginReference(plugin.ID, latest.ID, latest.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := svc.store.GamePlugins().Delete(plugin.ID); err != nil && !errors.Is(err, repo.ErrNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return svc.refreshServerPluginReferences(latest.ID, latest.Version)
|
||||
}
|
||||
|
||||
func (svc *CoreService) replaceGamePluginReference(fromPluginID, toPluginID, toPluginVersion string) error {
|
||||
if strings.TrimSpace(fromPluginID) == "" || fromPluginID == toPluginID {
|
||||
return nil
|
||||
}
|
||||
stamp := svc.now()
|
||||
instances, err := svc.store.ServerInstances().List(domain.ServerInstanceFilter{PluginID: fromPluginID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, instance := range instances {
|
||||
instance.PluginID = toPluginID
|
||||
instance.PluginVersion = toPluginVersion
|
||||
instance.UpdatedAt = stamp
|
||||
if err := validator.ValidateStoredServerInstance(instance); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := svc.store.ServerInstances().Update(instance); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
bindings, err := svc.store.RuntimeBindings().List(domain.RuntimeBindingFilter{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, binding := range bindings {
|
||||
if binding.PluginID != fromPluginID {
|
||||
continue
|
||||
}
|
||||
binding.PluginID = toPluginID
|
||||
binding.PluginVersion = toPluginVersion
|
||||
binding.UpdatedAt = stamp
|
||||
if err := svc.store.RuntimeBindings().Update(binding); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
installations, err := svc.store.PluginLifecycles().List(domain.PluginLifecycleFilter{PluginID: fromPluginID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, installation := range installations {
|
||||
installation.PluginID = toPluginID
|
||||
if installation.TargetVersion != "" {
|
||||
installation.TargetVersion = toPluginVersion
|
||||
}
|
||||
installation.UpdatedAt = stamp
|
||||
if err := svc.store.PluginLifecycles().Update(installation); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
previews, err := svc.store.AIConfigDiffs().List(domain.AIConfigDiffFilter{PluginID: fromPluginID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, preview := range previews {
|
||||
preview.PluginID = toPluginID
|
||||
preview.UpdatedAt = stamp
|
||||
if err := svc.store.AIConfigDiffs().Update(preview); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return svc.replacePluginDataReferences(fromPluginID, toPluginID)
|
||||
}
|
||||
|
||||
func (svc *CoreService) replacePluginDataReferences(fromPluginID, toPluginID string) error {
|
||||
items, err := svc.store.PluginDataRecords().List(domain.PluginDataFilter{PluginID: fromPluginID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
upserts := make([]domain.PluginDataRecord, 0, len(items))
|
||||
deleteIDs := make([]string, 0, len(items))
|
||||
for _, item := range items {
|
||||
deleteIDs = append(deleteIDs, item.ID)
|
||||
if legacySCUMPluginDataCollection(fromPluginID, item.Collection) {
|
||||
continue
|
||||
}
|
||||
item.PluginID = toPluginID
|
||||
item.ID = pluginDataID(item.ServerInstanceID, toPluginID, item.Collection, item.Key)
|
||||
if existing, getErr := svc.store.PluginDataRecords().Get(item.ID); getErr == nil && existing.UpdatedAt.After(item.UpdatedAt) {
|
||||
continue
|
||||
} else if getErr != nil && !errors.Is(getErr, repo.ErrNotFound) {
|
||||
return getErr
|
||||
}
|
||||
upserts = append(upserts, item)
|
||||
}
|
||||
if len(upserts) == 0 && len(deleteIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return svc.store.PluginDataRecords().Apply(upserts, deleteIDs)
|
||||
}
|
||||
|
||||
// refreshServerPluginReferences keeps existing server projections usable when a
|
||||
// manifest is refreshed in place. The server and its logical runtime binding
|
||||
// carry the manifest version used for lifecycle validation; leaving either at a
|
||||
|
||||
Reference in New Issue
Block a user