@@ -8,78 +8,33 @@ import (
88 "os"
99 "os/signal"
1010 "syscall"
11-
12- mem "gamifykit/adapters/memory"
13- redisAdapter "gamifykit/adapters/redis"
14- sqlxAdapter "gamifykit/adapters/sqlx"
15- "gamifykit/api/httpapi"
16- "gamifykit/config"
17- "gamifykit/engine"
18- "gamifykit/gamify"
19- "gamifykit/realtime"
2011)
2112
2213func main () {
23- // Load configuration
24- cfg , err := config . Load ( )
14+ ctx := context . Background ()
15+ app , err := BuildApp ( ctx )
2516 if err != nil {
26- fmt .Fprintf (os .Stderr , "Failed to load configuration : %v\n " , err )
17+ fmt .Fprintf (os .Stderr , "Failed to initialize app : %v\n " , err )
2718 os .Exit (1 )
2819 }
2920
30- // Setup logging based on configuration
31- setupLogging (cfg )
32-
33- // Load secrets if in production
34- ctx := context .Background ()
35- if cfg .Environment == config .EnvProduction {
36- if err := cfg .LoadSecretsFromEnv (ctx ); err != nil {
37- slog .Error ("Failed to load secrets" , "error" , err )
38- os .Exit (1 )
39- }
40- }
21+ cfg := app .Config
4122
4223 slog .Info ("starting gamifykit server" ,
4324 "environment" , cfg .Environment ,
4425 "profile" , cfg .Profile ,
4526 "address" , cfg .Server .Address ,
4627 "storage_adapter" , cfg .Storage .Adapter )
4728
48- // Setup storage adapter
49- storage , err := setupStorage (ctx , cfg )
50- if err != nil {
51- slog .Error ("Failed to setup storage" , "error" , err )
52- os .Exit (1 )
53- }
54-
55- // Build service
56- hub := realtime .NewHub ()
57- svc := gamify .New (
58- gamify .WithRealtime (hub ),
59- gamify .WithStorage (storage ),
60- gamify .WithDispatchMode (engine .DispatchAsync ),
61- )
62-
63- // Setup HTTP API
64- handler := httpapi .NewMux (svc , hub , httpapi.Options {
65- PathPrefix : cfg .Server .PathPrefix ,
66- AllowCORSOrigin : cfg .Server .CORSOrigin ,
67- })
68-
69- // Create HTTP server
70- srv := & http.Server {
71- Addr : cfg .Server .Address ,
72- Handler : handler ,
73- ReadHeaderTimeout : cfg .Server .ReadHeaderTimeout ,
74- ReadTimeout : cfg .Server .ReadTimeout ,
75- WriteTimeout : cfg .Server .WriteTimeout ,
76- IdleTimeout : cfg .Server .IdleTimeout ,
77- }
29+ srv := app .Server
7830
7931 // Start server in a goroutine
8032 go func () {
8133 slog .Info ("server listening" , "address" , cfg .Server .Address )
82- if err := srv .ListenAndServe (); err != nil && err != http .ErrServerClosed {
34+ if err := srv .ListenAndServe (); err != nil {
35+ if err == http .ErrServerClosed {
36+ return
37+ }
8338 slog .Error ("failed to start server" , "error" , err )
8439 os .Exit (1 )
8540 }
@@ -102,73 +57,3 @@ func main() {
10257
10358 slog .Info ("server stopped" )
10459}
105-
106- // setupLogging configures the logger based on configuration
107- func setupLogging (cfg * config.Config ) {
108- var handler slog.Handler
109-
110- opts := & slog.HandlerOptions {
111- Level : parseLogLevel (cfg .Logging .Level ),
112- }
113-
114- switch cfg .Logging .Format {
115- case "text" :
116- handler = slog .NewTextHandler (os .Stdout , opts )
117- case "json" :
118- handler = slog .NewJSONHandler (os .Stdout , opts )
119- default :
120- handler = slog .NewJSONHandler (os .Stdout , opts )
121- }
122-
123- // Add attributes if specified
124- if len (cfg .Logging .Attributes ) > 0 {
125- handler = handler .WithAttrs (convertAttributes (cfg .Logging .Attributes ))
126- }
127-
128- slog .SetDefault (slog .New (handler ))
129- }
130-
131- // parseLogLevel converts string log level to slog.Level
132- func parseLogLevel (level string ) slog.Level {
133- switch level {
134- case "debug" :
135- return slog .LevelDebug
136- case "info" :
137- return slog .LevelInfo
138- case "warn" :
139- return slog .LevelWarn
140- case "error" :
141- return slog .LevelError
142- default :
143- return slog .LevelInfo
144- }
145- }
146-
147- // convertAttributes converts map[string]string to []slog.Attr
148- func convertAttributes (attrs map [string ]string ) []slog.Attr {
149- var result []slog.Attr
150- for k , v := range attrs {
151- result = append (result , slog .String (k , v ))
152- }
153- return result
154- }
155-
156- // setupStorage creates the appropriate storage adapter based on configuration
157- func setupStorage (ctx context.Context , cfg * config.Config ) (engine.Storage , error ) {
158- switch cfg .Storage .Adapter {
159- case "memory" :
160- return mem .New (), nil
161-
162- case "redis" :
163- return redisAdapter .New (cfg .Storage .Redis )
164-
165- case "sql" :
166- return sqlxAdapter .New (cfg .Storage .SQL )
167-
168- case "file" :
169- return mem .New (), fmt .Errorf ("file storage not yet implemented, using memory fallback" )
170-
171- default :
172- return mem .New (), fmt .Errorf ("unknown storage adapter: %s" , cfg .Storage .Adapter )
173- }
174- }
0 commit comments