feat: runtime manager
This commit is contained in:
@@ -46,10 +46,13 @@ const (
|
||||
userServiceBaseURLEnvVar = "NOTIFICATION_USER_SERVICE_BASE_URL"
|
||||
userServiceTimeoutEnvVar = "NOTIFICATION_USER_SERVICE_TIMEOUT"
|
||||
|
||||
adminEmailsGeoReviewRecommendedEnvVar = "NOTIFICATION_ADMIN_EMAILS_GEO_REVIEW_RECOMMENDED"
|
||||
adminEmailsGameGenerationFailedEnvVar = "NOTIFICATION_ADMIN_EMAILS_GAME_GENERATION_FAILED"
|
||||
adminEmailsLobbyRuntimePausedAfterEnvVar = "NOTIFICATION_ADMIN_EMAILS_LOBBY_RUNTIME_PAUSED_AFTER_START"
|
||||
adminEmailsLobbyApplicationSubmittedEnvVar = "NOTIFICATION_ADMIN_EMAILS_LOBBY_APPLICATION_SUBMITTED"
|
||||
adminEmailsGeoReviewRecommendedEnvVar = "NOTIFICATION_ADMIN_EMAILS_GEO_REVIEW_RECOMMENDED"
|
||||
adminEmailsGameGenerationFailedEnvVar = "NOTIFICATION_ADMIN_EMAILS_GAME_GENERATION_FAILED"
|
||||
adminEmailsLobbyRuntimePausedAfterEnvVar = "NOTIFICATION_ADMIN_EMAILS_LOBBY_RUNTIME_PAUSED_AFTER_START"
|
||||
adminEmailsLobbyApplicationSubmittedEnvVar = "NOTIFICATION_ADMIN_EMAILS_LOBBY_APPLICATION_SUBMITTED"
|
||||
adminEmailsRuntimeImagePullFailedEnvVar = "NOTIFICATION_ADMIN_EMAILS_RUNTIME_IMAGE_PULL_FAILED"
|
||||
adminEmailsRuntimeContainerStartFailedEnvVar = "NOTIFICATION_ADMIN_EMAILS_RUNTIME_CONTAINER_START_FAILED"
|
||||
adminEmailsRuntimeStartConfigInvalidEnvVar = "NOTIFICATION_ADMIN_EMAILS_RUNTIME_START_CONFIG_INVALID"
|
||||
|
||||
otelServiceNameEnvVar = "OTEL_SERVICE_NAME"
|
||||
otelTracesExporterEnvVar = "OTEL_TRACES_EXPORTER"
|
||||
@@ -60,18 +63,18 @@ const (
|
||||
otelStdoutTracesEnabledEnvVar = "NOTIFICATION_OTEL_STDOUT_TRACES_ENABLED"
|
||||
otelStdoutMetricsEnabledEnvVar = "NOTIFICATION_OTEL_STDOUT_METRICS_ENABLED"
|
||||
|
||||
defaultShutdownTimeout = 5 * time.Second
|
||||
defaultLogLevel = "info"
|
||||
defaultInternalHTTPAddr = ":8092"
|
||||
defaultReadHeaderTimeout = 2 * time.Second
|
||||
defaultReadTimeout = 10 * time.Second
|
||||
defaultIdleTimeout = time.Minute
|
||||
defaultShutdownTimeout = 5 * time.Second
|
||||
defaultLogLevel = "info"
|
||||
defaultInternalHTTPAddr = ":8092"
|
||||
defaultReadHeaderTimeout = 2 * time.Second
|
||||
defaultReadTimeout = 10 * time.Second
|
||||
defaultIdleTimeout = time.Minute
|
||||
|
||||
defaultIntentsStream = "notification:intents"
|
||||
defaultIntentsReadBlockTimeout = 2 * time.Second
|
||||
defaultGatewayClientEventsStream = "gateway:client-events"
|
||||
defaultIntentsStream = "notification:intents"
|
||||
defaultIntentsReadBlockTimeout = 2 * time.Second
|
||||
defaultGatewayClientEventsStream = "gateway:client-events"
|
||||
defaultGatewayClientEventsStreamMaxLen int64 = 1024
|
||||
defaultMailDeliveryCommandsStream = "mail:delivery_commands"
|
||||
defaultMailDeliveryCommandsStream = "mail:delivery_commands"
|
||||
|
||||
defaultPushRetryMaxAttempts = 3
|
||||
defaultEmailRetryMaxAttempts = 7
|
||||
@@ -352,6 +355,18 @@ type AdminRoutingConfig struct {
|
||||
// LobbyApplicationSubmitted stores recipients for public
|
||||
// `lobby.application.submitted` notifications.
|
||||
LobbyApplicationSubmitted []string
|
||||
|
||||
// RuntimeImagePullFailed stores recipients for
|
||||
// `runtime.image_pull_failed`.
|
||||
RuntimeImagePullFailed []string
|
||||
|
||||
// RuntimeContainerStartFailed stores recipients for
|
||||
// `runtime.container_start_failed`.
|
||||
RuntimeContainerStartFailed []string
|
||||
|
||||
// RuntimeStartConfigInvalid stores recipients for
|
||||
// `runtime.start_config_invalid`.
|
||||
RuntimeStartConfigInvalid []string
|
||||
}
|
||||
|
||||
// Validate reports whether cfg stores valid normalized administrator email
|
||||
@@ -369,6 +384,15 @@ func (cfg AdminRoutingConfig) Validate() error {
|
||||
if err := validateNormalizedEmailList("lobby.application.submitted", cfg.LobbyApplicationSubmitted); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateNormalizedEmailList("runtime.image_pull_failed", cfg.RuntimeImagePullFailed); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateNormalizedEmailList("runtime.container_start_failed", cfg.RuntimeContainerStartFailed); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateNormalizedEmailList("runtime.start_config_invalid", cfg.RuntimeStartConfigInvalid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ const (
|
||||
envRedisTLSEnabled = "NOTIFICATION_REDIS_TLS_ENABLED"
|
||||
envRedisUsername = "NOTIFICATION_REDIS_USERNAME"
|
||||
|
||||
envPostgresPrimaryDSN = "NOTIFICATION_POSTGRES_PRIMARY_DSN"
|
||||
envPostgresOpTimeout = "NOTIFICATION_POSTGRES_OPERATION_TIMEOUT"
|
||||
envPostgresMaxOpenConns = "NOTIFICATION_POSTGRES_MAX_OPEN_CONNS"
|
||||
envPostgresMaxIdleConns = "NOTIFICATION_POSTGRES_MAX_IDLE_CONNS"
|
||||
envPostgresConnMaxLife = "NOTIFICATION_POSTGRES_CONN_MAX_LIFETIME"
|
||||
envPostgresPrimaryDSN = "NOTIFICATION_POSTGRES_PRIMARY_DSN"
|
||||
envPostgresOpTimeout = "NOTIFICATION_POSTGRES_OPERATION_TIMEOUT"
|
||||
envPostgresMaxOpenConns = "NOTIFICATION_POSTGRES_MAX_OPEN_CONNS"
|
||||
envPostgresMaxIdleConns = "NOTIFICATION_POSTGRES_MAX_IDLE_CONNS"
|
||||
envPostgresConnMaxLife = "NOTIFICATION_POSTGRES_CONN_MAX_LIFETIME"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -104,6 +104,9 @@ func TestLoadFromEnvAppliesOverrides(t *testing.T) {
|
||||
t.Setenv(adminEmailsGameGenerationFailedEnvVar, "ops@example.com")
|
||||
t.Setenv(adminEmailsLobbyRuntimePausedAfterEnvVar, "pause@example.com, PAUSE@example.com")
|
||||
t.Setenv(adminEmailsLobbyApplicationSubmittedEnvVar, "owner@example.com, OWNER@example.com")
|
||||
t.Setenv(adminEmailsRuntimeImagePullFailedEnvVar, "image-pull-ops@example.com, IMAGE-PULL-OPS@example.com")
|
||||
t.Setenv(adminEmailsRuntimeContainerStartFailedEnvVar, "container-start-ops@example.com")
|
||||
t.Setenv(adminEmailsRuntimeStartConfigInvalidEnvVar, "start-config-ops@example.com, START-CONFIG-OPS@example.com")
|
||||
t.Setenv(otelServiceNameEnvVar, "custom-notification")
|
||||
t.Setenv(otelTracesExporterEnvVar, "otlp")
|
||||
t.Setenv(otelMetricsExporterEnvVar, "otlp")
|
||||
@@ -172,6 +175,9 @@ func TestLoadFromEnvAppliesOverrides(t *testing.T) {
|
||||
GameGenerationFailed: []string{"ops@example.com"},
|
||||
LobbyRuntimePausedAfterStart: []string{"pause@example.com"},
|
||||
LobbyApplicationSubmitted: []string{"owner@example.com"},
|
||||
RuntimeImagePullFailed: []string{"image-pull-ops@example.com"},
|
||||
RuntimeContainerStartFailed: []string{"container-start-ops@example.com"},
|
||||
RuntimeStartConfigInvalid: []string{"start-config-ops@example.com"},
|
||||
}, cfg.AdminRouting)
|
||||
require.Equal(t, TelemetryConfig{
|
||||
ServiceName: "custom-notification",
|
||||
@@ -295,6 +301,7 @@ func TestLoadFromEnvRejectsInvalidConfiguration(t *testing.T) {
|
||||
{name: "invalid admin email", envName: adminEmailsGeoReviewRecommendedEnvVar, envVal: "broken-email", want: "invalid email address"},
|
||||
{name: "blank admin email slot", envName: adminEmailsGameGenerationFailedEnvVar, envVal: "ops@example.com, , second@example.com", want: "must not be empty"},
|
||||
{name: "invalid public application admin email", envName: adminEmailsLobbyApplicationSubmittedEnvVar, envVal: "Owner <owner@example.com>", want: "must not include a display name"},
|
||||
{name: "invalid runtime image pull admin email", envName: adminEmailsRuntimeImagePullFailedEnvVar, envVal: "broken-runtime-email", want: "invalid email address"},
|
||||
{name: "nonpositive gateway client events stream max len", envName: gatewayClientEventsStreamMaxEnvVar, envVal: "0", want: "must be positive"},
|
||||
{name: "backoff min above max", envName: routeBackoffMinEnvVar, envVal: "10m", want: "must not exceed"},
|
||||
}
|
||||
|
||||
@@ -128,6 +128,18 @@ func LoadFromEnv() (Config, error) {
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.AdminRouting.RuntimeImagePullFailed, err = emailListEnv(adminEmailsRuntimeImagePullFailedEnvVar, cfg.AdminRouting.RuntimeImagePullFailed)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.AdminRouting.RuntimeContainerStartFailed, err = emailListEnv(adminEmailsRuntimeContainerStartFailedEnvVar, cfg.AdminRouting.RuntimeContainerStartFailed)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.AdminRouting.RuntimeStartConfigInvalid, err = emailListEnv(adminEmailsRuntimeStartConfigInvalidEnvVar, cfg.AdminRouting.RuntimeStartConfigInvalid)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
|
||||
cfg.Telemetry.ServiceName = stringEnv(otelServiceNameEnvVar, cfg.Telemetry.ServiceName)
|
||||
cfg.Telemetry.TracesExporter = normalizeExporterValue(stringEnv(otelTracesExporterEnvVar, cfg.Telemetry.TracesExporter))
|
||||
|
||||
Reference in New Issue
Block a user