still working on creation/deletion times
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-28 15:19:10 +11:00
parent 49484900ac
commit ff783fb45a
3 changed files with 37 additions and 6 deletions

View File

@@ -557,6 +557,37 @@ ON CONFLICT ("Vcenter","VmId","VmUuid") DO UPDATE SET
return err return err
} }
// MarkVmDeletedFromEvent updates lifecycle cache with a deletion timestamp from vCenter events.
// Event times should override snapshot-derived timestamps, even if later.
func MarkVmDeletedFromEvent(ctx context.Context, dbConn *sqlx.DB, vcenter, vmID, vmUUID, name, cluster string, deletedAt int64) error {
if err := EnsureVmLifecycleCache(ctx, dbConn); err != nil {
return err
}
driver := strings.ToLower(dbConn.DriverName())
bindType := sqlx.BindType(driver)
query := `
INSERT INTO vm_lifecycle_cache ("Vcenter","VmId","VmUuid","Name","Cluster","DeletedAt","FirstSeen","LastSeen")
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT ("Vcenter","VmId","VmUuid") DO UPDATE SET
"DeletedAt"=CASE
WHEN EXCLUDED."DeletedAt" IS NOT NULL AND EXCLUDED."DeletedAt" > 0 THEN EXCLUDED."DeletedAt"
ELSE vm_lifecycle_cache."DeletedAt"
END,
"LastSeen"=COALESCE(vm_lifecycle_cache."LastSeen", EXCLUDED."LastSeen"),
"FirstSeen"=COALESCE(vm_lifecycle_cache."FirstSeen", EXCLUDED."FirstSeen"),
"Name"=COALESCE(NULLIF(vm_lifecycle_cache."Name", ''), EXCLUDED."Name"),
"Cluster"=COALESCE(NULLIF(vm_lifecycle_cache."Cluster", ''), EXCLUDED."Cluster")
`
query = sqlx.Rebind(bindType, query)
args := []interface{}{vcenter, vmID, vmUUID, name, cluster, deletedAt, deletedAt, deletedAt}
_, err := dbConn.ExecContext(ctx, query, args...)
if err != nil {
slog.Warn("lifecycle delete event exec failed", "vcenter", vcenter, "vm_id", vmID, "vm_uuid", vmUUID, "driver", driver, "args_len", len(args), "args", fmt.Sprint(args), "query", strings.TrimSpace(query), "error", err)
}
return err
}
// MarkVmDeleted updates lifecycle cache with a deletion timestamp (legacy signature). // MarkVmDeleted updates lifecycle cache with a deletion timestamp (legacy signature).
func MarkVmDeleted(ctx context.Context, dbConn *sqlx.DB, vcenter, vmID, vmUUID string, deletedAt int64) error { func MarkVmDeleted(ctx context.Context, dbConn *sqlx.DB, vcenter, vmID, vmUUID string, deletedAt int64) error {
return MarkVmDeletedWithDetails(ctx, dbConn, vcenter, vmID, vmUUID, "", "", deletedAt) return MarkVmDeletedWithDetails(ctx, dbConn, vcenter, vmID, vmUUID, "", "", deletedAt)
@@ -1609,7 +1640,6 @@ UPDATE %s dst
SET SET
"CreationTime" = CASE "CreationTime" = CASE
WHEN t.any_creation IS NOT NULL AND t.any_creation > 0 THEN LEAST(COALESCE(NULLIF(dst."CreationTime", 0), t.any_creation), t.any_creation) WHEN t.any_creation IS NOT NULL AND t.any_creation > 0 THEN LEAST(COALESCE(NULLIF(dst."CreationTime", 0), t.any_creation), t.any_creation)
WHEN (dst."CreationTime" IS NULL OR dst."CreationTime" = 0) AND t.first_seen IS NOT NULL AND t.first_seen > 0 THEN t.first_seen
ELSE dst."CreationTime" ELSE dst."CreationTime"
END, END,
"DeletionTime" = CASE "DeletionTime" = CASE
@@ -1671,7 +1701,6 @@ SET
( (
SELECT CASE SELECT CASE
WHEN t.any_creation IS NOT NULL AND t.any_creation > 0 AND COALESCE(NULLIF(%[2]s."CreationTime", 0), t.any_creation) > t.any_creation THEN t.any_creation WHEN t.any_creation IS NOT NULL AND t.any_creation > 0 AND COALESCE(NULLIF(%[2]s."CreationTime", 0), t.any_creation) > t.any_creation THEN t.any_creation
WHEN (%[2]s."CreationTime" IS NULL OR %[2]s."CreationTime" = 0) AND t.first_seen IS NOT NULL AND t.first_seen > 0 THEN t.first_seen
ELSE NULL ELSE NULL
END END
FROM enriched t FROM enriched t

View File

@@ -532,9 +532,11 @@ WHERE "Vcenter" = ? AND "DeletedAt" IS NOT NULL AND "DeletedAt" > 0 AND "Deleted
missed++ missed++
continue continue
} }
if target.deletion == 0 || deletedAt.Int64 < target.deletion {
target.deletion = deletedAt.Int64 target.deletion = deletedAt.Int64
applied++ applied++
} }
}
rows.Close() rows.Close()
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
c.Logger.Warn("failed to read lifecycle deletions", "vcenter", vcenter, "error", err) c.Logger.Warn("failed to read lifecycle deletions", "vcenter", vcenter, "error", err)

View File

@@ -1134,7 +1134,7 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
}); err != nil { }); err != nil {
log.Warn("failed to update inventory deletion time from event", "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "vcenter", url, "error", err) log.Warn("failed to update inventory deletion time from event", "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "vcenter", url, "error", err)
} }
if err := db.MarkVmDeletedWithDetails(ctx, dbConn, url, cand.vmID, cand.vmUUID, cand.name, cand.cluster, t.Unix()); err != nil { if err := db.MarkVmDeletedFromEvent(ctx, dbConn, url, cand.vmID, cand.vmUUID, cand.name, cand.cluster, t.Unix()); err != nil {
log.Warn("failed to refine lifecycle cache deletion time", "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "vcenter", url, "error", err) log.Warn("failed to refine lifecycle cache deletion time", "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "vcenter", url, "error", err)
} }
if snapRow, snapTable, found := findVMInHourlySnapshots(ctx, dbConn, url, cand.vmID); found { if snapRow, snapTable, found := findVMInHourlySnapshots(ctx, dbConn, url, cand.vmID); found {
@@ -1276,7 +1276,7 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
if inv.Cluster.Valid { if inv.Cluster.Valid {
clusterName = inv.Cluster.String clusterName = inv.Cluster.String
} }
if err := db.MarkVmDeletedWithDetails(ctx, dbConn, url, vmID, inv.VmUuid.String, inv.Name, clusterName, t.Unix()); err != nil { if err := db.MarkVmDeletedFromEvent(ctx, dbConn, url, vmID, inv.VmUuid.String, inv.Name, clusterName, t.Unix()); err != nil {
c.Logger.Warn("count-drop: failed to refine lifecycle cache deletion time", "vm_id", vmID, "vm_uuid", inv.VmUuid, "vcenter", url, "error", err) c.Logger.Warn("count-drop: failed to refine lifecycle cache deletion time", "vm_id", vmID, "vm_uuid", inv.VmUuid, "vcenter", url, "error", err)
} }
tableToUpdate := snapTable tableToUpdate := snapTable