github.com/abolfazlbeh/zhycan@v0.0.0-20230819144214-24cf38237387/internal/http/manager.go (about) 1 package http 2 3 import ( 4 "encoding/json" 5 "github.com/abolfazlbeh/zhycan/internal/config" 6 "github.com/abolfazlbeh/zhycan/internal/utils" 7 "github.com/gofiber/fiber/v2" 8 "log" 9 "sync" 10 ) 11 12 // Mark: manager 13 14 // manager object 15 type manager struct { 16 name string 17 lock sync.Mutex 18 servers map[string]*Server 19 defaultServer string 20 isServersStarted bool 21 } 22 23 // MARK: Module variables 24 var managerInstance *manager = nil 25 var once sync.Once 26 27 // Module init function 28 func init() { 29 log.Println("HTTP Manager Package Initialized...") 30 } 31 32 // init - Manager Constructor - It initializes the manager configuration params 33 func (m *manager) init() { 34 m.name = "http" 35 36 m.lock.Lock() 37 defer m.lock.Unlock() 38 39 // read configs and save it 40 serversCfg, err := config.GetManager().Get(m.name, "servers") 41 if err != nil { 42 return 43 } 44 45 var serverNames []string 46 m.servers = make(map[string]*Server) 47 48 for _, item := range serversCfg.([]interface{}) { 49 jsonBody, err2 := json.Marshal(item) 50 if err2 != nil { 51 continue 52 } 53 54 var obj ServerConfig 55 err := json.Unmarshal(jsonBody, &obj) 56 if err == nil { 57 server, err1 := NewServer(m.name, obj) 58 if err1 == nil { 59 m.servers[obj.Name] = server 60 61 serverNames = append(serverNames, obj.Name) 62 } 63 } 64 } 65 66 defaultS, err := config.GetManager().Get(m.name, "default") 67 if err == nil { 68 if utils.ArrayContains(&serverNames, defaultS.(string)) { 69 m.defaultServer = defaultS.(string) 70 } else if len(serverNames) > 0 { 71 m.defaultServer = serverNames[0] 72 } 73 } 74 75 m.isServersStarted = false 76 } 77 78 // restartOnChangeConfig - subscribe a function for when the config is changed 79 func (m *manager) restartOnChangeConfig() { 80 // Config config server to reload 81 wrapper, err := config.GetManager().GetConfigWrapper(m.name) 82 if err == nil { 83 wrapper.RegisterChangeCallback(func() interface{} { 84 if m.isServersStarted { 85 m.StopServers() 86 m.init() 87 m.StartServers() 88 } 89 return nil 90 }) 91 } else { 92 // TODO: make some logs 93 } 94 } 95 96 // MARK: Public Functions 97 98 // GetManager - This function returns singleton instance of Logger Manager 99 func GetManager() *manager { 100 // once used for prevent race condition and manage critical section. 101 once.Do(func() { 102 managerInstance = &manager{} 103 managerInstance.init() 104 managerInstance.restartOnChangeConfig() 105 }) 106 return managerInstance 107 } 108 109 // StartServers - iterate over all servers and start them 110 func (m *manager) StartServers() error { 111 m.lock.Lock() 112 defer m.lock.Unlock() 113 114 if !m.isServersStarted { 115 for _, item := range m.servers { 116 go func(s *Server) { 117 err := s.Start() 118 if err != nil { 119 // TODO: print some error 120 } 121 }(item) 122 } 123 } 124 return nil 125 } 126 127 // StopServers - iterate over all severs and stop them 128 func (m *manager) StopServers() error { 129 m.lock.Lock() 130 defer m.lock.Unlock() 131 132 if m.isServersStarted { 133 for _, item := range m.servers { 134 go func(s *Server) { 135 err := s.Stop() 136 if err != nil { 137 // TODO: print some error 138 } 139 }(item) 140 } 141 } 142 return nil 143 } 144 145 // AddRoute - add a route to the server with specified name 146 func (m *manager) AddRoute(method string, path string, f func(c *fiber.Ctx) error, routeName string, versions []string, groupNames []string, serverName ...string) error { 147 if len(serverName) > 0 { 148 for _, sn := range serverName { 149 if s, ok := m.servers[sn]; ok { 150 return s.AddRoute(method, path, f, routeName, versions, groupNames) 151 } 152 } 153 } else { 154 if m.defaultServer != "" { 155 return m.servers[m.defaultServer].AddRoute(method, path, f, routeName, versions, groupNames) 156 } 157 } 158 return NewAddRouteToNilServerErr(path) 159 } 160 161 func (m *manager) GetRouteByName(routeName string, serverName ...string) (*fiber.Route, error) { 162 if len(serverName) > 1 { 163 return nil, NewFromMultipleServerErr() 164 } else if len(serverName) == 1 { 165 for _, sn := range serverName { 166 if s, ok := m.servers[sn]; ok { 167 return s.GetRouteByName(routeName) 168 } 169 } 170 } else { 171 if m.defaultServer != "" { 172 return m.servers[m.defaultServer].GetRouteByName(routeName) 173 } 174 } 175 return nil, NewFromNilServerErr() 176 } 177 178 // AddGroup - add a group to the server with specified name 179 func (m *manager) AddGroup(groupName string, f func(c *fiber.Ctx) error, groupsName []string, serverName ...string) error { 180 if serverName != nil { 181 if len(serverName) > 0 { 182 for _, sn := range serverName { 183 if s, ok := m.servers[sn]; ok { 184 if groupsName != nil { 185 return s.AddGroup(groupName, f, groupsName...) 186 } else { 187 return s.AddGroup(groupName, f, []string{}...) 188 } 189 } 190 } 191 } else { 192 if m.defaultServer != "" { 193 if groupsName != nil { 194 return m.servers[m.defaultServer].AddGroup(groupName, f, groupsName...) 195 } else { 196 return m.servers[m.defaultServer].AddGroup(groupName, f, []string{}...) 197 } 198 } 199 } 200 } else { 201 if m.defaultServer != "" { 202 if groupsName != nil { 203 return m.servers[m.defaultServer].AddGroup(groupName, f, groupsName...) 204 } else { 205 return m.servers[m.defaultServer].AddGroup(groupName, f, []string{}...) 206 } 207 } 208 } 209 return NewAddGroupToNilServerErr(groupName) 210 } 211 212 // AttachErrorHandler - attach a custom error handler to the server with specified name 213 func (m *manager) AttachErrorHandler(f func(ctx *fiber.Ctx, err error) error, serverNames ...string) error { 214 if len(serverNames) > 0 { 215 for _, sn := range serverNames { 216 if s, ok := m.servers[sn]; ok { 217 s.AttachErrorHandler(f) 218 return nil 219 } 220 } 221 } else { 222 if m.defaultServer != "" { 223 m.servers[m.defaultServer].AttachErrorHandler(f) 224 return nil 225 } 226 } 227 228 return NewAttachErrorHandlerToNilServerErr(serverNames...) 229 }