Releases: tkcrm/mx
v0.5.0
What's Changed
- Bump google.golang.org/grpc from 1.79.2 to 1.79.3 in /transport/grpc_transport by @dependabot[bot] in #53
- Bump google.golang.org/grpc from 1.79.2 to 1.79.3 in /clients/grpc_client by @dependabot[bot] in #54
- feat: add service startup priority by @sxwebdev in #55
New
Startup priority
Services can be assigned a startup priority to control initialization order. Services with the same priority start concurrently within a group. Groups are started sequentially in ascending priority order. Priority 0 (default) services start last, concurrently, after all prioritized groups are ready.
ln.ServicesRunner().Register(
// Priority 1: DB layer — start concurrently, both must be ready before next group
launcher.NewService(
launcher.WithServiceName("postgres"),
launcher.WithStartupPriority(1),
launcher.WithService(pgService),
),
launcher.NewService(
launcher.WithServiceName("redis"),
launcher.WithStartupPriority(1),
launcher.WithService(redisService),
),
// Priority 2: message broker — waits for DB layer to be ready
launcher.NewService(
launcher.WithServiceName("rabbitmq"),
launcher.WithStartupPriority(2),
launcher.WithService(rabbitService),
),
// Priority 0 (default): application services — start concurrently after all groups
launcher.NewService(
launcher.WithServiceName("http-server"),
launcher.WithService(httpService),
),
launcher.NewService(
launcher.WithServiceName("grpc-server"),
launcher.WithService(grpcService),
),
)
// Start order: (postgres + redis) → rabbitmq → (http + grpc concurrently)synctest
Cover launcher with synctest and fixed two bugs
Full Changelog: v0.4.0...v0.5.0
v0.4.0
What's Changed
New Features
Service State Machine
Each service now tracks its lifecycle state: idle → starting → running → stopping → stopped / failed.
Access it via svc.State(). The ServiceState type lives in launcher/types and is re-exported from launcher for backward compatibility.
Restart Policy
Services can now restart automatically after failure with exponential backoff:
launcher.WithRestartPolicy(launcher.RestartPolicy{
Mode: launcher.RestartOnFailure,
MaxRetries: 5,
Delay: time.Second,
MaxDelay: 30 * time.Second,
})Modes: RestartNever (default) / RestartOnFailure / RestartAlways.
Liveness probe /livez
Reads ServiceState directly — no HealthChecker required.
Returns 200 when all services are alive, 503 if any service is in Failed state.
{
"status": "ok",
"services": { "db": "running", "cache": "starting", "api": "failed" }
}Readiness probe /readyz
Combines ServiceState + HealthChecker poll results.
Returns 200 (ready) / 424 (starting) / 503 (failed) with per-service detail:
{
"status": "starting",
"services": {
"db": { "state": "running", "health": "ok" },
"cache": { "state": "starting", "health": "starting" },
"api": { "state": "failed", "health": "error" }
}
}The existing /healthy endpoint is unchanged (backward compatible).
Global Shutdown Timeout
Hard deadline for the entire graceful shutdown phase:
launcher.WithGlobalShutdownTimeout(30 * time.Second)Startup Timeout
Per-service timeout independent from ShutdownTimeout:
launcher.WithStartupTimeout(10 * time.Second)Service Lookup
svc, ok := ln.ServicesRunner().Get("my-service")Bug Fixes
BeforeStop/AfterStophook errors no longer overwrite each other — all errors are now aggregated viaerrors.Join.
Documentation
- README: new Launcher capabilities table covering all options and interfaces.
Migration
No breaking changes. All existing options and interfaces are preserved.
ServiceState constants are re-exported from the launcher package — existing imports continue to work.
v0.3.0
Summary of changes
Breaking changes
service and ops packages merged into launcher
| Before | After |
|---|---|
service.New(...) |
launcher.NewService(...) |
service.Option |
launcher.ServiceOption |
service.IService |
launcher/types.IService |
service.HealthChecker |
launcher/types.HealthChecker |
service.Enabler |
launcher/types.Enabler |
ops.Config |
launcher/ops.Config |
ops.New(...) |
launcher/ops.New(...) |
service/pingpong |
launcher/services/pingpong |
cfg package removed — extracted into a separate repository. Use xconfig instead
New packages
launcher/types— shared interfaces (IService,HealthChecker,Enabler) used by both transports andlauncher/opslauncher/ops— relocatedopspackage (metrics, health checker, profiler)launcher/services/pingpong— relocated example ping-pong service
Bug fixes
- Goroutine leak on service startup error — when a service sent to
errChan,cancelFn()was never called andgraceWait.Wait()was never reached, leaving all other service goroutines running indefinitely SIGKILLin signal list —syscall.SIGKILLcannot be caught viasignal.Notify(); removed fromutil/signal- Duplicate signal handling in services — every service registered its own signal handler independently of the launcher; removed from
service.Start() signal.Stop()never called — minor resource leak on launcher exit
New behaviour
Double-stop graceful shutdown:
- 1st signal (
SIGTERM/SIGINT/SIGQUIT) → graceful shutdown begins, logs"graceful shutdown started, send signal again to force exit" - 2nd signal during shutdown → immediate
os.Exit(1)
Dependencies
- Updated
go.modand sub-module dependencies (clients/,transport/grpc_transport,transport/connectrpc_transport)
What's Changed
- Bump golang.org/x/crypto from 0.39.0 to 0.45.0 by @dependabot[bot] in #49
- Bump golang.org/x/net from 0.37.0 to 0.38.0 in /clients/connectrpc_client by @dependabot[bot] in #50
- full refactor service by @sxwebdev in #51
Full Changelog: v0.2.34...v0.3.0
v0.2.34
What's Changed
- Bump golang.org/x/net from 0.37.0 to 0.38.0 in /clients/grpc_client by @dependabot in #46
- Bump golang.org/x/net from 0.37.0 to 0.38.0 by @dependabot in #47
- Update all dependencies by @sxwebdev
Full Changelog: v0.2.33...v0.2.34
v0.2.33
v0.2.32
What's Changed
- Bump golang.org/x/crypto from 0.30.0 to 0.31.0 by @dependabot in #42
- update all deps by @sxwebdev in #43
Full Changelog: v0.2.31...v0.2.32