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  }