feat: add AttachmentReadinessTimeout config field
New deploy.attachment_readiness_timeout config option controls how long Gordon waits for attachment containers (postgres, redis) to become ready before starting the main app container.
- commit
- a02523919d9eb34926b823d056e51ab4747c39ce
- author
- brice · · 2026-03-23 19:06 UTC
- parent
- 63e7f3a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +55 -53
M internal/app/run.go +26 -25
| @@ -1285,31 +1285,32 @@ func createContainerService(ctx context.Context, v *viper.Viper, cfg Config, svc | |||
| 1285 | 1285 | } | |
| 1286 | 1286 | ||
| 1287 | 1287 | containerConfig := container.Config{ | |
| 1288 | - | RegistryAuthEnabled: cfg.Auth.Enabled, | |
| 1289 | - | RegistryDomain: cfg.Server.RegistryDomain, | |
| 1290 | - | RegistryPort: cfg.Server.RegistryPort, | |
| 1291 | - | InternalRegistryUsername: svc.internalRegUser, | |
| 1292 | - | InternalRegistryPassword: svc.internalRegPass, | |
| 1293 | - | PullPolicy: v.GetString("deploy.pull_policy"), | |
| 1294 | - | VolumeAutoCreate: v.GetBool("volumes.auto_create"), | |
| 1295 | - | VolumePrefix: v.GetString("volumes.prefix"), | |
| 1296 | - | VolumePreserve: v.GetBool("volumes.preserve"), | |
| 1297 | - | NetworkIsolation: v.GetBool("network_isolation.enabled"), | |
| 1298 | - | NetworkPrefix: v.GetString("network_isolation.network_prefix"), | |
| 1299 | - | NetworkGroups: svc.configSvc.GetNetworkGroups(), | |
| 1300 | - | Attachments: svc.configSvc.GetAttachments(), | |
| 1301 | - | ReadinessDelay: v.GetDuration("deploy.readiness_delay"), | |
| 1302 | - | ReadinessMode: v.GetString("deploy.readiness_mode"), | |
| 1303 | - | HealthTimeout: v.GetDuration("deploy.health_timeout"), | |
| 1304 | - | StabilizationDelay: v.GetDuration("deploy.stabilization_delay"), | |
| 1305 | - | TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"), | |
| 1306 | - | HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"), | |
| 1307 | - | DrainDelay: v.GetDuration("deploy.drain_delay"), | |
| 1308 | - | DrainMode: v.GetString("deploy.drain_mode"), | |
| 1309 | - | DrainTimeout: v.GetDuration("deploy.drain_timeout"), | |
| 1310 | - | DefaultMemoryLimit: defaultMemoryLimit, | |
| 1311 | - | DefaultNanoCPUs: defaultNanoCPUs, | |
| 1312 | - | DefaultPidsLimit: cfg.Containers.PidsLimit, | |
| 1288 | + | RegistryAuthEnabled: cfg.Auth.Enabled, | |
| 1289 | + | RegistryDomain: cfg.Server.RegistryDomain, | |
| 1290 | + | RegistryPort: cfg.Server.RegistryPort, | |
| 1291 | + | InternalRegistryUsername: svc.internalRegUser, | |
| 1292 | + | InternalRegistryPassword: svc.internalRegPass, | |
| 1293 | + | PullPolicy: v.GetString("deploy.pull_policy"), | |
| 1294 | + | VolumeAutoCreate: v.GetBool("volumes.auto_create"), | |
| 1295 | + | VolumePrefix: v.GetString("volumes.prefix"), | |
| 1296 | + | VolumePreserve: v.GetBool("volumes.preserve"), | |
| 1297 | + | NetworkIsolation: v.GetBool("network_isolation.enabled"), | |
| 1298 | + | NetworkPrefix: v.GetString("network_isolation.network_prefix"), | |
| 1299 | + | NetworkGroups: svc.configSvc.GetNetworkGroups(), | |
| 1300 | + | Attachments: svc.configSvc.GetAttachments(), | |
| 1301 | + | ReadinessDelay: v.GetDuration("deploy.readiness_delay"), | |
| 1302 | + | ReadinessMode: v.GetString("deploy.readiness_mode"), | |
| 1303 | + | HealthTimeout: v.GetDuration("deploy.health_timeout"), | |
| 1304 | + | StabilizationDelay: v.GetDuration("deploy.stabilization_delay"), | |
| 1305 | + | TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"), | |
| 1306 | + | HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"), | |
| 1307 | + | DrainDelay: v.GetDuration("deploy.drain_delay"), | |
| 1308 | + | DrainMode: v.GetString("deploy.drain_mode"), | |
| 1309 | + | DrainTimeout: v.GetDuration("deploy.drain_timeout"), | |
| 1310 | + | DefaultMemoryLimit: defaultMemoryLimit, | |
| 1311 | + | DefaultNanoCPUs: defaultNanoCPUs, | |
| 1312 | + | DefaultPidsLimit: cfg.Containers.PidsLimit, | |
| 1313 | + | AttachmentReadinessTimeout: v.GetDuration("deploy.attachment_readiness_timeout"), | |
| 1313 | 1314 | } | |
| 1314 | 1315 | if v.IsSet("deploy.drain_delay") { | |
| 1315 | 1316 | containerConfig.DrainDelayConfigured = true | |
| @@ -1285,31 +1285,32 @@ func createContainerService(ctx context.Context, v *viper.Viper, cfg Config, svc | |||||
| 1285 | } | 1285 | } | ||
| 1286 | 1286 | ||||
| 1287 | containerConfig := container.Config{ | 1287 | containerConfig := container.Config{ | ||
| 1288 | - | RegistryAuthEnabled: cfg.Auth.Enabled, | 1288 | + | RegistryAuthEnabled: cfg.Auth.Enabled, |
| 1289 | - | RegistryDomain: cfg.Server.RegistryDomain, | 1289 | + | RegistryDomain: cfg.Server.RegistryDomain, |
| 1290 | - | RegistryPort: cfg.Server.RegistryPort, | 1290 | + | RegistryPort: cfg.Server.RegistryPort, |
| 1291 | - | InternalRegistryUsername: svc.internalRegUser, | 1291 | + | InternalRegistryUsername: svc.internalRegUser, |
| 1292 | - | InternalRegistryPassword: svc.internalRegPass, | 1292 | + | InternalRegistryPassword: svc.internalRegPass, |
| 1293 | - | PullPolicy: v.GetString("deploy.pull_policy"), | 1293 | + | PullPolicy: v.GetString("deploy.pull_policy"), |
| 1294 | - | VolumeAutoCreate: v.GetBool("volumes.auto_create"), | 1294 | + | VolumeAutoCreate: v.GetBool("volumes.auto_create"), |
| 1295 | - | VolumePrefix: v.GetString("volumes.prefix"), | 1295 | + | VolumePrefix: v.GetString("volumes.prefix"), |
| 1296 | - | VolumePreserve: v.GetBool("volumes.preserve"), | 1296 | + | VolumePreserve: v.GetBool("volumes.preserve"), |
| 1297 | - | NetworkIsolation: v.GetBool("network_isolation.enabled"), | 1297 | + | NetworkIsolation: v.GetBool("network_isolation.enabled"), |
| 1298 | - | NetworkPrefix: v.GetString("network_isolation.network_prefix"), | 1298 | + | NetworkPrefix: v.GetString("network_isolation.network_prefix"), |
| 1299 | - | NetworkGroups: svc.configSvc.GetNetworkGroups(), | 1299 | + | NetworkGroups: svc.configSvc.GetNetworkGroups(), |
| 1300 | - | Attachments: svc.configSvc.GetAttachments(), | 1300 | + | Attachments: svc.configSvc.GetAttachments(), |
| 1301 | - | ReadinessDelay: v.GetDuration("deploy.readiness_delay"), | 1301 | + | ReadinessDelay: v.GetDuration("deploy.readiness_delay"), |
| 1302 | - | ReadinessMode: v.GetString("deploy.readiness_mode"), | 1302 | + | ReadinessMode: v.GetString("deploy.readiness_mode"), |
| 1303 | - | HealthTimeout: v.GetDuration("deploy.health_timeout"), | 1303 | + | HealthTimeout: v.GetDuration("deploy.health_timeout"), |
| 1304 | - | StabilizationDelay: v.GetDuration("deploy.stabilization_delay"), | 1304 | + | StabilizationDelay: v.GetDuration("deploy.stabilization_delay"), |
| 1305 | - | TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"), | 1305 | + | TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"), |
| 1306 | - | HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"), | 1306 | + | HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"), |
| 1307 | - | DrainDelay: v.GetDuration("deploy.drain_delay"), | 1307 | + | DrainDelay: v.GetDuration("deploy.drain_delay"), |
| 1308 | - | DrainMode: v.GetString("deploy.drain_mode"), | 1308 | + | DrainMode: v.GetString("deploy.drain_mode"), |
| 1309 | - | DrainTimeout: v.GetDuration("deploy.drain_timeout"), | 1309 | + | DrainTimeout: v.GetDuration("deploy.drain_timeout"), |
| 1310 | - | DefaultMemoryLimit: defaultMemoryLimit, | 1310 | + | DefaultMemoryLimit: defaultMemoryLimit, |
| 1311 | - | DefaultNanoCPUs: defaultNanoCPUs, | 1311 | + | DefaultNanoCPUs: defaultNanoCPUs, |
| 1312 | - | DefaultPidsLimit: cfg.Containers.PidsLimit, | 1312 | + | DefaultPidsLimit: cfg.Containers.PidsLimit, |
| 1313 | + | AttachmentReadinessTimeout: v.GetDuration("deploy.attachment_readiness_timeout"), | |||
| 1313 | } | 1314 | } | ||
| 1314 | if v.IsSet("deploy.drain_delay") { | 1315 | if v.IsSet("deploy.drain_delay") { | ||
| 1315 | containerConfig.DrainDelayConfigured = true | 1316 | containerConfig.DrainDelayConfigured = true | ||
M internal/usecase/container/service.go +29 -28
| @@ -26,34 +26,35 @@ import ( | |||
| 26 | 26 | ||
| 27 | 27 | // Config holds configuration needed by the container service. | |
| 28 | 28 | type Config struct { | |
| 29 | - | RegistryAuthEnabled bool | |
| 30 | - | RegistryDomain string | |
| 31 | - | RegistryPort int | |
| 32 | - | ServiceTokenUsername string | |
| 33 | - | ServiceToken string | |
| 34 | - | InternalRegistryUsername string | |
| 35 | - | InternalRegistryPassword string | |
| 36 | - | PullPolicy string | |
| 37 | - | VolumeAutoCreate bool | |
| 38 | - | VolumePrefix string | |
| 39 | - | VolumePreserve bool | |
| 40 | - | NetworkIsolation bool | |
| 41 | - | NetworkPrefix string | |
| 42 | - | NetworkGroups map[string][]string | |
| 43 | - | Attachments map[string][]string | |
| 44 | - | ReadinessDelay time.Duration // Delay after container starts before considering it ready | |
| 45 | - | ReadinessMode string // Readiness strategy: auto, docker-health, delay | |
| 46 | - | HealthTimeout time.Duration // Max wait for health-based readiness | |
| 47 | - | DrainDelay time.Duration // Grace period after cache invalidation before stopping old container | |
| 48 | - | DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured | |
| 49 | - | DrainMode string // Drain strategy: auto, inflight, delay | |
| 50 | - | DrainTimeout time.Duration // Max wait for in-flight requests to drain | |
| 51 | - | StabilizationDelay time.Duration // Post-switch monitoring window (default 2s) | |
| 52 | - | TCPProbeTimeout time.Duration // TCP probe timeout (default 30s) | |
| 53 | - | HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s) | |
| 54 | - | DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit) | |
| 55 | - | DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit) | |
| 56 | - | DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit) | |
| 29 | + | RegistryAuthEnabled bool | |
| 30 | + | RegistryDomain string | |
| 31 | + | RegistryPort int | |
| 32 | + | ServiceTokenUsername string | |
| 33 | + | ServiceToken string | |
| 34 | + | InternalRegistryUsername string | |
| 35 | + | InternalRegistryPassword string | |
| 36 | + | PullPolicy string | |
| 37 | + | VolumeAutoCreate bool | |
| 38 | + | VolumePrefix string | |
| 39 | + | VolumePreserve bool | |
| 40 | + | NetworkIsolation bool | |
| 41 | + | NetworkPrefix string | |
| 42 | + | NetworkGroups map[string][]string | |
| 43 | + | Attachments map[string][]string | |
| 44 | + | ReadinessDelay time.Duration // Delay after container starts before considering it ready | |
| 45 | + | ReadinessMode string // Readiness strategy: auto, docker-health, delay | |
| 46 | + | HealthTimeout time.Duration // Max wait for health-based readiness | |
| 47 | + | DrainDelay time.Duration // Grace period after cache invalidation before stopping old container | |
| 48 | + | DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured | |
| 49 | + | DrainMode string // Drain strategy: auto, inflight, delay | |
| 50 | + | DrainTimeout time.Duration // Max wait for in-flight requests to drain | |
| 51 | + | StabilizationDelay time.Duration // Post-switch monitoring window (default 2s) | |
| 52 | + | TCPProbeTimeout time.Duration // TCP probe timeout (default 30s) | |
| 53 | + | HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s) | |
| 54 | + | AttachmentReadinessTimeout time.Duration // Max wait for attachment readiness (default 30s) | |
| 55 | + | DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit) | |
| 56 | + | DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit) | |
| 57 | + | DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit) | |
| 57 | 58 | } | |
| 58 | 59 | ||
| 59 | 60 | var tracer = otel.Tracer("gordon.container") | |
| @@ -26,34 +26,35 @@ import ( | |||||
| 26 | 26 | ||||
| 27 | // Config holds configuration needed by the container service. | 27 | // Config holds configuration needed by the container service. | ||
| 28 | type Config struct { | 28 | type Config struct { | ||
| 29 | - | RegistryAuthEnabled bool | 29 | + | RegistryAuthEnabled bool |
| 30 | - | RegistryDomain string | 30 | + | RegistryDomain string |
| 31 | - | RegistryPort int | 31 | + | RegistryPort int |
| 32 | - | ServiceTokenUsername string | 32 | + | ServiceTokenUsername string |
| 33 | - | ServiceToken string | 33 | + | ServiceToken string |
| 34 | - | InternalRegistryUsername string | 34 | + | InternalRegistryUsername string |
| 35 | - | InternalRegistryPassword string | 35 | + | InternalRegistryPassword string |
| 36 | - | PullPolicy string | 36 | + | PullPolicy string |
| 37 | - | VolumeAutoCreate bool | 37 | + | VolumeAutoCreate bool |
| 38 | - | VolumePrefix string | 38 | + | VolumePrefix string |
| 39 | - | VolumePreserve bool | 39 | + | VolumePreserve bool |
| 40 | - | NetworkIsolation bool | 40 | + | NetworkIsolation bool |
| 41 | - | NetworkPrefix string | 41 | + | NetworkPrefix string |
| 42 | - | NetworkGroups map[string][]string | 42 | + | NetworkGroups map[string][]string |
| 43 | - | Attachments map[string][]string | 43 | + | Attachments map[string][]string |
| 44 | - | ReadinessDelay time.Duration // Delay after container starts before considering it ready | 44 | + | ReadinessDelay time.Duration // Delay after container starts before considering it ready |
| 45 | - | ReadinessMode string // Readiness strategy: auto, docker-health, delay | 45 | + | ReadinessMode string // Readiness strategy: auto, docker-health, delay |
| 46 | - | HealthTimeout time.Duration // Max wait for health-based readiness | 46 | + | HealthTimeout time.Duration // Max wait for health-based readiness |
| 47 | - | DrainDelay time.Duration // Grace period after cache invalidation before stopping old container | 47 | + | DrainDelay time.Duration // Grace period after cache invalidation before stopping old container |
| 48 | - | DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured | 48 | + | DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured |
| 49 | - | DrainMode string // Drain strategy: auto, inflight, delay | 49 | + | DrainMode string // Drain strategy: auto, inflight, delay |
| 50 | - | DrainTimeout time.Duration // Max wait for in-flight requests to drain | 50 | + | DrainTimeout time.Duration // Max wait for in-flight requests to drain |
| 51 | - | StabilizationDelay time.Duration // Post-switch monitoring window (default 2s) | 51 | + | StabilizationDelay time.Duration // Post-switch monitoring window (default 2s) |
| 52 | - | TCPProbeTimeout time.Duration // TCP probe timeout (default 30s) | 52 | + | TCPProbeTimeout time.Duration // TCP probe timeout (default 30s) |
| 53 | - | HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s) | 53 | + | HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s) |
| 54 | - | DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit) | 54 | + | AttachmentReadinessTimeout time.Duration // Max wait for attachment readiness (default 30s) |
| 55 | - | DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit) | 55 | + | DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit) |
| 56 | - | DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit) | 56 | + | DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit) |
| 57 | + | DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit) | |||
| 57 | } | 58 | } | ||
| 58 | 59 | ||||
| 59 | var tracer = otel.Tracer("gordon.container") | 60 | var tracer = otel.Tracer("gordon.container") | ||