feat: user service

This commit is contained in:
Ilia Denisov
2026-04-10 19:05:02 +02:00
committed by GitHub
parent 710bad712e
commit 23ffcb7535
140 changed files with 33418 additions and 952 deletions
+151
View File
@@ -0,0 +1,151 @@
# Runtime and Components
The diagram below focuses on the deployed `galaxy/user` process and its
runtime dependencies.
```mermaid
flowchart LR
subgraph Callers
Auth["Auth / Session Service"]
Gateway["Edge Gateway"]
Lobby["Game Lobby Service"]
Geo["Geo Profile Service"]
Admin["Trusted admin callers"]
end
subgraph User["User Service process"]
InternalHTTP["Trusted internal HTTP listener\n/api/v1/internal/*"]
AdminHTTP["Optional admin HTTP listener\n/metrics"]
Services["Application services"]
Telemetry["Logs, traces, metrics"]
end
Redis["Redis\nkeyspace + domain-events stream"]
Auth --> InternalHTTP
Gateway --> InternalHTTP
Lobby --> InternalHTTP
Geo --> InternalHTTP
Admin --> InternalHTTP
InternalHTTP --> Services
Services --> Redis
InternalHTTP --> Telemetry
AdminHTTP --> Telemetry
```
## Listeners
`userservice` exposes two HTTP listeners:
| Listener | Default addr | Purpose |
| --- | --- | --- |
| Internal HTTP | `:8091` | Trusted business API under `/api/v1/internal/*` |
| Admin HTTP | disabled | Optional Prometheus metrics on `/metrics` |
Shared listener defaults:
- read-header timeout: `2s`
- read timeout: `10s`
- idle timeout: `1m`
The internal application timeout is configured separately through
`USERSERVICE_INTERNAL_HTTP_REQUEST_TIMEOUT`.
Intentional omissions:
- no public listener
- no authenticated edge gRPC listener
- no built-in `/healthz`
- no built-in `/readyz`
## Startup Wiring
`cmd/userservice` loads config, constructs logging and telemetry, and then
creates the runtime through `internal/app.NewRuntime`.
The runtime wires:
- Redis-backed stores for accounts, entitlement snapshots, sanctions, limits,
and listing indexes
- the trusted internal HTTP router
- the optional admin metrics listener
- the optional Redis-backed domain-event publishers
- service-local helpers for clock, IDs, and validation/policy adapters
Startup fails fast when Redis connectivity is unavailable or configuration is
invalid.
## Redis Namespaces
The service uses one Redis keyspace prefix plus one auxiliary domain-events
stream.
Configuration:
- `USERSERVICE_REDIS_KEYSPACE_PREFIX`
- `USERSERVICE_REDIS_DOMAIN_EVENTS_STREAM`
- `USERSERVICE_REDIS_DOMAIN_EVENTS_STREAM_MAX_LEN`
The keyspace stores source-of-truth business state. The stream carries
post-commit auxiliary domain events and must not be treated as the source of
truth.
## Configuration Groups
Required for all process starts:
- `USERSERVICE_REDIS_ADDR`
Core process config:
- `USERSERVICE_SHUTDOWN_TIMEOUT`
- `USERSERVICE_LOG_LEVEL`
Internal HTTP config:
- `USERSERVICE_INTERNAL_HTTP_ADDR`
- `USERSERVICE_INTERNAL_HTTP_READ_HEADER_TIMEOUT`
- `USERSERVICE_INTERNAL_HTTP_READ_TIMEOUT`
- `USERSERVICE_INTERNAL_HTTP_IDLE_TIMEOUT`
- `USERSERVICE_INTERNAL_HTTP_REQUEST_TIMEOUT`
Admin HTTP config:
- `USERSERVICE_ADMIN_HTTP_ADDR`
- `USERSERVICE_ADMIN_HTTP_READ_HEADER_TIMEOUT`
- `USERSERVICE_ADMIN_HTTP_READ_TIMEOUT`
- `USERSERVICE_ADMIN_HTTP_IDLE_TIMEOUT`
Redis connectivity and namespace config:
- `USERSERVICE_REDIS_USERNAME`
- `USERSERVICE_REDIS_PASSWORD`
- `USERSERVICE_REDIS_DB`
- `USERSERVICE_REDIS_TLS_ENABLED`
- `USERSERVICE_REDIS_OPERATION_TIMEOUT`
- `USERSERVICE_REDIS_KEYSPACE_PREFIX`
- `USERSERVICE_REDIS_DOMAIN_EVENTS_STREAM`
- `USERSERVICE_REDIS_DOMAIN_EVENTS_STREAM_MAX_LEN`
Telemetry:
- `OTEL_SERVICE_NAME`
- `OTEL_TRACES_EXPORTER`
- `OTEL_METRICS_EXPORTER`
- `OTEL_EXPORTER_OTLP_PROTOCOL`
- `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`
- `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL`
- `USERSERVICE_OTEL_STDOUT_TRACES_ENABLED`
- `USERSERVICE_OTEL_STDOUT_METRICS_ENABLED`
## Runtime Notes
- The service remains internal REST only; gateway owns external authenticated
gRPC and FlatBuffers.
- Gateway self-service traffic reaches this service over REST/JSON after
gateway-side authentication and FlatBuffers transcoding.
- Current direct synchronous callers are `Auth / Session Service`,
`Edge Gateway`, `Game Lobby Service`, `Geo Profile Service`, and trusted
admin callers.
- Domain-event publication is auxiliary. A failed auxiliary consumer must not
become the source of truth for current account state.