mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
Docker container URL preserved on update (#1054): container updates recreate the container with a new runtime ID. The agent now includes {oldContainerId, newContainerId} in the completion ACK payload; the server uses this to copy persisted metadata (custom URLs, descriptions, tags) to the new ID so nothing is lost. Migration is a copy, not a move, so rollback scenarios still find metadata under the original ID. Reduce metrics.db write amplification (#1124): add a UNIQUE index on (resource_type, resource_id, metric_type, timestamp, tier) so rollup reprocessing after a failed checkpoint uses INSERT OR IGNORE instead of creating duplicate rows. Existing duplicates are deduplicated once on startup if the index creation would otherwise fail. Also sets wal_autocheckpoint(500) to checkpoint the WAL more frequently, preventing unbounded WAL growth. Fixes #1054 Fixes #1124
72 lines
2.3 KiB
Go
72 lines
2.3 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
|
)
|
|
|
|
// CopyDockerContainerMetadata copies persisted container metadata from an old container runtime ID to a new one.
|
|
//
|
|
// Docker container updates typically recreate the container, producing a new runtime ID. Persisted metadata
|
|
// (custom URL, description, tags, notes) is keyed by resource ID and would otherwise be "lost" for the new
|
|
// container.
|
|
//
|
|
// This is intentionally a copy (not a move) so rollback-to-backup scenarios can still find metadata under
|
|
// the original container ID.
|
|
func (m *Monitor) CopyDockerContainerMetadata(hostID, oldContainerID, newContainerID string) error {
|
|
if m == nil || m.dockerMetadataStore == nil {
|
|
return nil
|
|
}
|
|
|
|
hostID = strings.TrimSpace(hostID)
|
|
oldContainerID = strings.TrimSpace(oldContainerID)
|
|
newContainerID = strings.TrimSpace(newContainerID)
|
|
if hostID == "" || oldContainerID == "" || newContainerID == "" || oldContainerID == newContainerID {
|
|
return nil
|
|
}
|
|
|
|
oldKey := fmt.Sprintf("%s:container:%s", hostID, oldContainerID)
|
|
newKey := fmt.Sprintf("%s:container:%s", hostID, newContainerID)
|
|
|
|
oldMeta := m.dockerMetadataStore.Get(oldKey)
|
|
if oldMeta == nil {
|
|
return nil
|
|
}
|
|
if oldMeta.CustomURL == "" && oldMeta.Description == "" && len(oldMeta.Tags) == 0 && len(oldMeta.Notes) == 0 {
|
|
return nil
|
|
}
|
|
|
|
newMeta := m.dockerMetadataStore.Get(newKey)
|
|
var merged config.DockerMetadata
|
|
if newMeta != nil {
|
|
merged = *newMeta
|
|
}
|
|
|
|
// Merge missing fields from old -> new, so we don't clobber any metadata already present under the new ID.
|
|
if merged.CustomURL == "" {
|
|
merged.CustomURL = oldMeta.CustomURL
|
|
}
|
|
if merged.Description == "" {
|
|
merged.Description = oldMeta.Description
|
|
}
|
|
if len(merged.Tags) == 0 && len(oldMeta.Tags) > 0 {
|
|
merged.Tags = append([]string(nil), oldMeta.Tags...)
|
|
}
|
|
if len(merged.Notes) == 0 && len(oldMeta.Notes) > 0 {
|
|
merged.Notes = append([]string(nil), oldMeta.Notes...)
|
|
}
|
|
|
|
// Avoid an unnecessary disk write if nothing changed.
|
|
if newMeta != nil &&
|
|
merged.CustomURL == newMeta.CustomURL &&
|
|
merged.Description == newMeta.Description &&
|
|
slices.Equal(merged.Tags, newMeta.Tags) &&
|
|
slices.Equal(merged.Notes, newMeta.Notes) {
|
|
return nil
|
|
}
|
|
|
|
return m.dockerMetadataStore.Set(newKey, &merged)
|
|
}
|