feat: CheckSnapshots y UpdateSnapshot en fn_operations library
Añade UpdateTypeSnapshot al store, CheckSnapshots para comparar snapshots locales vs registry (up_to_date/outdated/missing), y UpdateSnapshot para re-snapshot con retorno de old/new para diffing.
This commit is contained in:
@@ -189,6 +189,94 @@ func GetEntityGraph(db *DB) (*Graph, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SnapshotStatus describes the state of a snapshot vs the registry.
|
||||
type SnapshotStatus string
|
||||
|
||||
const (
|
||||
SnapshotUpToDate SnapshotStatus = "up_to_date"
|
||||
SnapshotOutdated SnapshotStatus = "outdated"
|
||||
SnapshotMissing SnapshotStatus = "missing" // exists locally but not in registry
|
||||
)
|
||||
|
||||
// SnapshotCheckResult holds the comparison for one type snapshot.
|
||||
type SnapshotCheckResult struct {
|
||||
ID string
|
||||
LocalVersion string
|
||||
RegistryVersion string
|
||||
Status SnapshotStatus
|
||||
}
|
||||
|
||||
// CheckSnapshots compares all local snapshots against the registry.
|
||||
func CheckSnapshots(opsDB *DB, registryDB *registry.DB) ([]SnapshotCheckResult, error) {
|
||||
snaps, err := opsDB.ListTypeSnapshots()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing snapshots: %w", err)
|
||||
}
|
||||
|
||||
var results []SnapshotCheckResult
|
||||
for _, snap := range snaps {
|
||||
regType, err := registryDB.GetType(snap.ID)
|
||||
if err != nil {
|
||||
// Not found in registry
|
||||
results = append(results, SnapshotCheckResult{
|
||||
ID: snap.ID,
|
||||
LocalVersion: snap.Version,
|
||||
Status: SnapshotMissing,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
status := SnapshotUpToDate
|
||||
if regType.Version != snap.Version {
|
||||
status = SnapshotOutdated
|
||||
}
|
||||
|
||||
results = append(results, SnapshotCheckResult{
|
||||
ID: snap.ID,
|
||||
LocalVersion: snap.Version,
|
||||
RegistryVersion: regType.Version,
|
||||
Status: status,
|
||||
})
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// UpdateSnapshot re-snapshots a type from the registry, replacing the local copy.
|
||||
// Returns the old and new definitions for diffing.
|
||||
func UpdateSnapshot(opsDB *DB, registryDB *registry.DB, typeID string) (old, new_ *TypeSnapshot, err error) {
|
||||
// Get current local snapshot
|
||||
oldSnap, err := opsDB.GetTypeSnapshot(typeID)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("reading local snapshot: %w", err)
|
||||
}
|
||||
if oldSnap == nil {
|
||||
return nil, nil, fmt.Errorf("type %q not found in local snapshots", typeID)
|
||||
}
|
||||
|
||||
// Get current registry type
|
||||
regType, err := registryDB.GetType(typeID)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("fetching type %q from registry: %w", typeID, err)
|
||||
}
|
||||
|
||||
// Build new snapshot
|
||||
newSnap := &TypeSnapshot{
|
||||
ID: regType.ID,
|
||||
Version: regType.Version,
|
||||
Lang: regType.Lang,
|
||||
Algebraic: string(regType.Algebraic),
|
||||
Definition: regType.Definition,
|
||||
Description: regType.Description,
|
||||
SnappedAt: time.Now().UTC(),
|
||||
}
|
||||
|
||||
if err := opsDB.UpdateTypeSnapshot(newSnap); err != nil {
|
||||
return nil, nil, fmt.Errorf("updating snapshot: %w", err)
|
||||
}
|
||||
|
||||
return oldSnap, newSnap, nil
|
||||
}
|
||||
|
||||
func buildEntitySet(db *DB) (map[string]bool, error) {
|
||||
all, err := db.ListEntities("", "")
|
||||
if err != nil {
|
||||
|
||||
@@ -58,6 +58,20 @@ func (db *DB) InsertTypeSnapshot(ts *TypeSnapshot) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateTypeSnapshot replaces an existing snapshot with a new version.
|
||||
func (db *DB) UpdateTypeSnapshot(ts *TypeSnapshot) error {
|
||||
if ts.SnappedAt.IsZero() {
|
||||
ts.SnappedAt = time.Now().UTC()
|
||||
}
|
||||
_, err := db.conn.Exec(`
|
||||
UPDATE types_snapshot SET version=?, lang=?, algebraic=?, definition=?, description=?, snapped_at=?
|
||||
WHERE id=?`,
|
||||
ts.Version, ts.Lang, ts.Algebraic, ts.Definition, ts.Description,
|
||||
ts.SnappedAt.Format(time.RFC3339), ts.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTypeSnapshot returns a type snapshot by ID.
|
||||
func (db *DB) GetTypeSnapshot(id string) (*TypeSnapshot, error) {
|
||||
row := db.conn.QueryRow("SELECT id, version, lang, algebraic, definition, description, snapped_at FROM types_snapshot WHERE id = ?", id)
|
||||
|
||||
Reference in New Issue
Block a user