Nik Afiq 657b6aeb22 feat: implement initial application structure with health and hello endpoints
- Add bootstrap package to initialize application components including logger, tracer, and HTTP server.
- Create config package to load runtime settings from environment variables.
- Implement observability features including logging, metrics, and tracing.
- Add health check and hello use cases with corresponding HTTP handlers.
- Introduce middleware for request ID, access logging, metrics, and recovery.
- Set up HTTP router with defined routes for health and hello endpoints.
- Include tests for health and hello endpoints to ensure proper functionality.
- Add OpenTelemetry collector configuration for trace exporting.
2026-03-05 21:22:43 +09:00

62 lines
1.1 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"switchbot-api/internal/app/bootstrap"
"switchbot-api/internal/app/config"
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "fatal: %v\n", err)
os.Exit(1)
}
}
func run() error {
cfg := config.Load()
ctx := context.Background()
app, err := bootstrap.New(ctx, cfg)
if err != nil {
return err
}
errCh := make(chan error, 1)
go func() {
errCh <- app.Start()
}()
sigCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
select {
case <-sigCtx.Done():
app.Logger.Info("shutdown signal received")
case err := <-errCh:
if err != nil && !errors.Is(err, http.ErrServerClosed) {
return err
}
}
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := app.Shutdown(shutdownCtx); err != nil {
app.Logger.Error("shutdown failed", slog.String("error", err.Error()))
return err
}
app.Logger.Info("server stopped cleanly")
return nil
}