44package config
55
66import (
7- "context"
8- "net/http"
97 "os"
10- "os/signal"
118 "strconv"
12- "syscall"
13- "time"
149
15- "github.com/MitulShah1/golang-rest-api-template/internal/handlers"
16- "github.com/MitulShah1/golang-rest-api-template/package/database"
17- "github.com/MitulShah1/golang-rest-api-template/package/logger"
18- "github.com/MitulShah1/golang-rest-api-template/package/middleware"
1910 "github.com/joho/godotenv"
20- tracesdk "go.opentelemetry.io/otel/sdk/trace"
2111)
2212
23- // Service holds application configuration and manages the application lifecycle .
13+ // Service holds application configuration.
2414// It includes database, server, and telemetry configuration.
2515type Service struct {
2616 Name string
27- Logger * logger.Logger
28- Server * handlers.Server
2917 dbEnv DBConfig
18+ redisEnv RedisConfig
3019 srvConfg ServerConf
3120 jaegerConfig JaegerConfig
32- db * database.Database
33- tp * tracesdk.TracerProvider
3421}
3522
3623type DBConfig struct {
@@ -41,6 +28,13 @@ type DBConfig struct {
4128 Name string
4229}
4330
31+ type RedisConfig struct {
32+ Host string
33+ Port string
34+ Password string
35+ DB int
36+ }
37+
4438type ServerConf struct {
4539 Address string
4640 Port string
@@ -57,98 +51,17 @@ func NewService() *Service {
5751 }
5852}
5953
60- // Init initializes the application configuration, including loading environment variables,
61- // initializing the logger, database connection, and server. It returns an error if any
62- // of the initialization steps fail.
63- func (cnf * Service ) Init () (err error ) {
64- // initialize logger
65- cnf .Logger = logger .NewLogger (logger .DefaultOptions ())
66-
67- // Load environment variables
68- if err := cnf .LoadConfig (); err != nil {
69- return err
70- }
71-
72- // initialize database
73- cnf .db , err = database .NewDatabase (& database.DBConfig {
74- Host : cnf .dbEnv .Host ,
75- Port : cnf .dbEnv .Port ,
76- User : cnf .dbEnv .User ,
77- Password : cnf .dbEnv .Password ,
78- DBName : cnf .dbEnv .Name ,
79- })
80- if err != nil {
81- return err
82- }
83-
84- cnf .Logger .Info ("Database connection successful" )
85-
86- agentPort , _ := strconv .Atoi (cnf .jaegerConfig .AgentPort )
87- tmCnfg := middleware.TelemetryConfig {
88- Host : cnf .jaegerConfig .AgentHost ,
89- Port : agentPort ,
90- ServiceName : "go-rest-api-template" ,
91- }
92-
93- // initialize tracer
94- cnf .tp , err = tmCnfg .InitTracer ()
95- if err != nil {
96- return err
97- }
98-
99- cnf .Logger .Info ("Tracer initialized" )
100-
101- // initialize server
102- serverAddr := cnf .srvConfg .Address + ":" + cnf .srvConfg .Port
103- if cnf .Server , err = handlers .NewServer (serverAddr , cnf .Logger , cnf .db , & tmCnfg ); err != nil {
104- return err
105- }
106-
107- return nil
108- }
109-
110- // Run starts the server and listens for termination signals.
111- // It runs the server in a goroutine and waits for a termination signal (SIGINT or SIGTERM).
112- // When a termination signal is received, it gracefully shuts down the server.
113- func (cnf * Service ) Run () error {
114- // Channel to listen for termination signals
115- stop := make (chan os.Signal , 1 )
116- signal .Notify (stop , os .Interrupt , syscall .SIGTERM )
117-
118- // Run server in a goroutine
119- go func () {
120- cnf .Logger .Info ("Starting server port: " + cnf .srvConfg .Port )
121- if err := cnf .Server .ListenAndServe (); err != nil && err != http .ErrServerClosed {
122- cnf .Logger .Error ("Server error" , "error" , err )
123- os .Exit (1 )
124- }
125- }()
126-
127- // Wait for termination signal
128- <- stop
129- cnf .Logger .Info ("Shutting down server..." )
130-
131- // Graceful shutdown
132- ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
133- defer cancel ()
134-
135- // Shutdown the tracer provider
136- if err := cnf .tp .Shutdown (ctx ); err != nil {
137- cnf .Logger .Error ("Failed to shutdown tracer provider" , "error" , err )
138- }
139-
140- if err := cnf .Server .ServerDown (ctx ); err != nil {
141- cnf .Logger .Error ("Server shutdown failed" , "error" , err )
142- } else {
143- cnf .Logger .Info ("Server exited gracefully" )
144- }
145- return nil
54+ // Init initializes the application configuration by loading environment variables.
55+ // It returns an error if the configuration loading fails.
56+ func (cnf * Service ) Init () error {
57+ return cnf .LoadConfig ()
14658}
14759
60+ // LoadConfig loads configuration from environment variables
14861func (cnf * Service ) LoadConfig () error {
14962 // loads environment variables from .env file
15063 if err := godotenv .Load (); err != nil {
151- cnf . Logger . Warn ( "no .env file found, using system environment variables" )
64+ return err
15265 }
15366
15467 cnf .dbEnv = DBConfig {
@@ -159,6 +72,15 @@ func (cnf *Service) LoadConfig() error {
15972 Name : getEnv ("DB_NAME" , "mydatabase" ),
16073 }
16174
75+ // Redis config
76+ redisDB , _ := strconv .Atoi (getEnv ("REDIS_DB" , "0" ))
77+ cnf .redisEnv = RedisConfig {
78+ Host : getEnv ("REDIS_HOST" , "localhost" ),
79+ Port : getEnv ("REDIS_PORT" , "6379" ),
80+ Password : getEnv ("REDIS_PASSWORD" , "" ),
81+ DB : redisDB ,
82+ }
83+
16284 // Server config
16385 cnf .srvConfg = ServerConf {
16486 Address : getEnv ("SERVER_ADDR" , "" ),
@@ -181,3 +103,23 @@ func getEnv(key, defaultValue string) string {
181103 }
182104 return defaultValue
183105}
106+
107+ // GetDBConfig returns the database configuration
108+ func (cnf * Service ) GetDBConfig () DBConfig {
109+ return cnf .dbEnv
110+ }
111+
112+ // GetRedisConfig returns the Redis configuration
113+ func (cnf * Service ) GetRedisConfig () RedisConfig {
114+ return cnf .redisEnv
115+ }
116+
117+ // GetServerConfig returns the server configuration
118+ func (cnf * Service ) GetServerConfig () ServerConf {
119+ return cnf .srvConfg
120+ }
121+
122+ // GetJaegerConfig returns the Jaeger configuration
123+ func (cnf * Service ) GetJaegerConfig () JaegerConfig {
124+ return cnf .jaegerConfig
125+ }
0 commit comments