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
|
}, 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) {
|
func buildEntitySet(db *DB) (map[string]bool, error) {
|
||||||
all, err := db.ListEntities("", "")
|
all, err := db.ListEntities("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -58,6 +58,20 @@ func (db *DB) InsertTypeSnapshot(ts *TypeSnapshot) error {
|
|||||||
return err
|
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.
|
// GetTypeSnapshot returns a type snapshot by ID.
|
||||||
func (db *DB) GetTypeSnapshot(id string) (*TypeSnapshot, error) {
|
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)
|
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