Files
nginx-ui/model/namespace.go
0xJacky af2dc9aee9 fix(cluster): survive unsupported config names in a directory sync
An end-to-end run against a two node cluster surfaced two problems in the
synchronization added by 9f70d47.

A real Nginx configuration directory holds files the config validator rejects,
such as nginx.conf.bak.1738662518. The collector pushed them anyway and the
receiver aborted the whole batch on the first one, so a single stale backup
stopped every other file from being deployed. Names the receiver would reject
are now skipped while collecting, and the receiver reports a per-file failure
list instead of discarding the batch, keeping the reply an error only when
nothing could be applied at all. The caller turns a partially applied batch
into a failed result so a summary never claims a clean run.

sync_interval_minutes also advertised a minimum of one minute that the
omitempty rule never enforced. Zero is what the model already treats as "use
the default", so the rule now says so and rejects negatives instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 23:17:57 +08:00

74 lines
2.7 KiB
Go

package model
// PostSyncActionType defines the type of action after synchronization
const (
// PostSyncActionNone indicates no operation after sync
PostSyncActionNone = "none"
// PostSyncActionReloadNginx indicates reload Nginx after sync
PostSyncActionReloadNginx = "reload_nginx"
)
// UpstreamTestType defines the type of upstream test
const (
// UpstreamTestLocal indicates local upstream test
UpstreamTestLocal = "local"
// UpstreamTestRemote indicates remote upstream test
UpstreamTestRemote = "remote"
// UpstreamTestMirror indicates mirror upstream test
UpstreamTestMirror = "mirror"
)
// DeployMode defines where configs should be deployed
const (
// DeployModeLocal indicates deploy locally with optional remote sync
DeployModeLocal = "local"
// DeployModeRemote indicates deploy to remote nodes only
DeployModeRemote = "remote"
)
// SyncStrategy defines when namespace content is replicated to the member nodes
const (
// SyncStrategyManual only replicates on explicit user actions
SyncStrategyManual = "manual"
// SyncStrategyAuto periodically replicates the whole namespace
SyncStrategyAuto = "auto"
)
// DefaultSyncIntervalMinutes is used when a namespace enables automatic sync
// without providing an interval.
const DefaultSyncIntervalMinutes = 30
// Namespace represents a group of environments that can be synced across nodes
type Namespace struct {
Model
Name string `json:"name"`
SyncNodeIds []uint64 `json:"sync_node_ids" gorm:"serializer:json"`
OrderID int `json:"-" gorm:"default:0"`
PostSyncAction string `json:"post_sync_action" gorm:"default:'reload_nginx'"`
UpstreamTestType string `json:"upstream_test_type" gorm:"default:'local'"`
DeployMode string `json:"deploy_mode" gorm:"default:'local'"`
SyncStrategy string `json:"sync_strategy" gorm:"default:'manual'"`
SyncIntervalMinutes int `json:"sync_interval_minutes" gorm:"default:30"`
}
// IsRemoteDeploy reports whether the namespace content is only deployed to the
// member nodes. Local Nginx must never be validated or reloaded for it.
func (n *Namespace) IsRemoteDeploy() bool {
return n != nil && n.DeployMode == DeployModeRemote
}
// IsAutoSync reports whether the namespace content should be replicated
// periodically without user interaction.
func (n *Namespace) IsAutoSync() bool {
return n != nil && n.SyncStrategy == SyncStrategyAuto
}
// EffectiveSyncInterval returns the auto sync interval. Zero means "use the
// default", which is what the API accepts when the field is left unset.
func (n *Namespace) EffectiveSyncInterval() int {
if n == nil || n.SyncIntervalMinutes <= 0 {
return DefaultSyncIntervalMinutes
}
return n.SyncIntervalMinutes
}