4.7 KiB
4.7 KiB
Runtime and Components
The diagram below focuses on the deployed galaxy/mail process and its runtime
dependencies.
flowchart LR
subgraph Callers
Auth["Auth / Session Service"]
Notify["Notification Service"]
Ops["Trusted operators"]
end
subgraph Mail["Mail Service process"]
InternalHTTP["Trusted internal HTTP listener\n/api/v1/internal/*"]
Consumer["Redis Stream command consumer"]
Scheduler["Attempt scheduler"]
Workers["Attempt worker pool"]
Cleanup["Index cleanup worker"]
Services["Application services"]
Templates["Immutable template catalog"]
Telemetry["Logs, traces, metrics"]
end
Redis["Redis\nstate + streams + indexes"]
Provider["SMTP or stub provider"]
Auth --> InternalHTTP
Ops --> InternalHTTP
Notify --> Redis
InternalHTTP --> Services
Consumer --> Services
Scheduler --> Services
Workers --> Services
Cleanup --> Services
Services --> Templates
Services --> Redis
Services --> Provider
InternalHTTP --> Telemetry
Consumer --> Telemetry
Scheduler --> Telemetry
Workers --> Telemetry
Listener
mail exposes exactly one HTTP listener:
| Listener | Default addr | Purpose |
|---|---|---|
| Internal HTTP | :8080 |
Trusted intake, operator reads, and resend |
Shared listener defaults:
- read-header timeout:
2s - read timeout:
10s - idle timeout:
1m
Intentional omissions:
- no public listener
- no
/healthz - no
/readyz - no
/metrics
Startup Wiring
cmd/mail loads config, constructs logging, and builds the runtime through
internal/app.NewRuntime.
The runtime wires:
- Redis clients for state access and blocking stream consumption
- filesystem-backed template catalog
- provider adapter selected by
MAIL_SMTP_MODE - acceptance, render, execution, operator-read, and resend services
- internal HTTP server
- command consumer
- scheduler
- attempt worker pool
- cleanup worker
Before startup completes, the process performs bounded PING checks for both
Redis clients and validates the template catalog. Startup fails fast on invalid
configuration or unavailable Redis.
Background Components
Command consumer
- reads one plain
XREADstream - starts from stored offset or
0-0 - advances offset only after durable command acceptance or durable malformed command recording
Scheduler
- polls due work every
250ms - recovers stale claims every
30s - derives recovery deadline from
MAIL_SMTP_TIMEOUT + 30s
Attempt worker pool
- processes only already claimed work items
- concurrency is controlled by
MAIL_ATTEMPT_WORKER_CONCURRENCY
Cleanup worker
- removes stale delivery-index members after primary delivery expiry
- does not clean
mail:attempt_schedule - does not clean malformed-command index entries
Configuration Groups
Required for all starts:
MAIL_REDIS_ADDR
Core process config:
MAIL_SHUTDOWN_TIMEOUTMAIL_LOG_LEVEL
Internal HTTP config:
MAIL_INTERNAL_HTTP_ADDRMAIL_INTERNAL_HTTP_READ_HEADER_TIMEOUTMAIL_INTERNAL_HTTP_READ_TIMEOUTMAIL_INTERNAL_HTTP_IDLE_TIMEOUT
Redis connectivity:
MAIL_REDIS_USERNAMEMAIL_REDIS_PASSWORDMAIL_REDIS_DBMAIL_REDIS_TLS_ENABLEDMAIL_REDIS_OPERATION_TIMEOUTMAIL_REDIS_COMMAND_STREAMMAIL_REDIS_ATTEMPT_SCHEDULE_KEYMAIL_REDIS_DEAD_LETTER_PREFIX
SMTP provider:
MAIL_SMTP_MODEMAIL_SMTP_ADDRMAIL_SMTP_USERNAMEMAIL_SMTP_PASSWORDMAIL_SMTP_FROM_EMAILMAIL_SMTP_FROM_NAMEMAIL_SMTP_TIMEOUTMAIL_SMTP_INSECURE_SKIP_VERIFY
Templates and workers:
MAIL_TEMPLATE_DIRMAIL_ATTEMPT_WORKER_CONCURRENCYMAIL_STREAM_BLOCK_TIMEOUTMAIL_OPERATOR_REQUEST_TIMEOUTMAIL_IDEMPOTENCY_TTLMAIL_DELIVERY_TTLMAIL_ATTEMPT_TTL
Telemetry:
OTEL_SERVICE_NAMEOTEL_TRACES_EXPORTEROTEL_METRICS_EXPORTEROTEL_EXPORTER_OTLP_PROTOCOLOTEL_EXPORTER_OTLP_TRACES_PROTOCOLOTEL_EXPORTER_OTLP_METRICS_PROTOCOLMAIL_OTEL_STDOUT_TRACES_ENABLEDMAIL_OTEL_STDOUT_METRICS_ENABLED
Runtime Notes
MAIL_REDIS_COMMAND_STREAMis the only Redis key override that currently changes runtime behaviorMAIL_SMTP_INSECURE_SKIP_VERIFYis a local-development escape hatch for self-signed SMTP capture only and should remain disabled in production- attempt-schedule and dead-letter key overrides are parsed but not yet wired into Redis adapters
- retention overrides are parsed but storage still uses the fixed
7d,30d, and90dvalues - template catalog parsing is eager and immutable
- auth deliveries in
MAIL_SMTP_MODE=stubsurface assuppressed - auth deliveries in
MAIL_SMTP_MODE=smtpsurface asqueuedand later move through normal attempt execution