| @ -1,207 +1,228 @@ | |||
| package service | |||
| import ( | |||
| "net/http" | |||
| "database/sql" | |||
| "github.com/gorilla/mux" | |||
| _ "github.com/lib/pq" | |||
| log "github.com/Sirupsen/logrus" | |||
| "strings" | |||
| "cygnux/kepler/restlet" | |||
| "sync" | |||
| "cygnux/kepler/cache" | |||
| "cygnux/kepler/kv" | |||
| "cygnux/kepler/utils" | |||
| "cygnux/kepler/msq" | |||
| "cygnux/kepler/configs" | |||
| ) | |||
| type KeplerService struct { | |||
| prefix string | |||
| option configs.GenericOption | |||
| params configs.ParameterOption | |||
| db *sql.DB | |||
| db_schema string | |||
| router *mux.Router | |||
| cache cache.Cache | |||
| kvstore kv.KV | |||
| mpub msq.Publisher | |||
| msub msq.Subscriber | |||
| _task_chan chan restlet.TaskObject | |||
| _task_handlers map[string]restlet.TaskletHandler | |||
| _msg_handlers map[string]restlet.TaskletHandler | |||
| } | |||
| const URL_PREFIX = "/" | |||
| func NewService(op OptionProvider, prefixes ...string) (*KeplerService, error) { | |||
| log.Debugln("NewService:> ", op.Option()) | |||
| var e error | |||
| if len(prefixes) == 0 { | |||
| prefixes = []string{URL_PREFIX} | |||
| } | |||
| svr := &KeplerService{ | |||
| params:op.Parameters(), | |||
| option: op.Option(), | |||
| router: mux.NewRouter().StrictSlash(true), | |||
| prefix: prefixes[0], | |||
| } | |||
| if svr.db, svr.db_schema, e = utils.SqlDBConnect(op.Option().DB); nil != e { | |||
| log.Errorln("Open database failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.cache, e = cache.NewCache(op.Option().Cache); nil != e { | |||
| log.Errorln("Make Cache failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.kvstore, e = kv.NewKV(op.Option().KV); nil != e { | |||
| log.Errorln("Make KVStore failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.mpub, e = msq.NewPublisher(op.Option().MPub); nil != e { | |||
| log.Errorln("Make MPub failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.msub, e = msq.NewSubscriber(op.Option().MSub); nil != e { | |||
| log.Errorln("Make MSub failed:> ", e) | |||
| return nil, e | |||
| } | |||
| svr._task_chan = make(chan restlet.TaskObject, 1024) | |||
| if op.Option().Debug { | |||
| restlet.SetDebug(op.Option().Debug) | |||
| log.Debugln("Restlet debug on!") | |||
| } | |||
| svr._task_handlers = make(map[string]restlet.TaskletHandler) | |||
| svr._msg_handlers = make(map[string]restlet.TaskletHandler) | |||
| svr.load_builtin_handlers() | |||
| return svr, nil | |||
| } | |||
| const X_CYGNUX_SIGN = "X-CYGNUX-SIGN" | |||
| func (self *KeplerService) Router() *mux.Router { | |||
| return self.router | |||
| } | |||
| func (self *KeplerService) Predicate(request *http.Request) (string, bool) { | |||
| sign := request.Header.Get(X_CYGNUX_SIGN) | |||
| log.Infoln("X-CYGNUX-SIGN:> ", sign) | |||
| return "", true | |||
| if sign == "" { | |||
| return "", false | |||
| } | |||
| return "", true | |||
| } | |||
| func (self *KeplerService) NewContext(request *http.Request) restlet.RequestContext { | |||
| return NewRequestContext(self, request) | |||
| } | |||
| func (self *KeplerService) makeRestletHandler(h restlet.RestletHandler, methods []string, cache *restlet.CacheController) http.Handler { | |||
| return restlet.MakeRestletHandler(h, self, self, methods, cache) | |||
| } | |||
| func (self *KeplerService) registerRestlet(prefix string, methods []string, handler restlet.RestletHandler, cache *restlet.CacheController) { | |||
| h := self.makeRestletHandler(handler, methods, cache) | |||
| log.Infof("Register:> Registering %s: %s ...", strings.Join(methods, ","), self.prefix + "/" + prefix) | |||
| self.router.Handle(self.prefix + "/" + prefix, h) | |||
| } | |||
| func (self *KeplerService) TaskProc() { | |||
| for t := range self._task_chan { | |||
| if h, ok := self._task_handlers[t.Queue]; ok { | |||
| if e := h.Handle(NewTaskContext(self), t.Params...); nil != e { | |||
| log.Errorf("TaskProc:> %s Handle failed:> %s \n", t.Queue, e) | |||
| } | |||
| } else { | |||
| log.Warnln("TaskProc:> Missing task handler for:", t.Queue) | |||
| } | |||
| } | |||
| } | |||
| func (self *KeplerService) MessageProc() { | |||
| wg := &sync.WaitGroup{} | |||
| for k, h := range self._msg_handlers { | |||
| wg.Add(1) | |||
| err := self.msub.Subscribe(k, func(data []byte) error { | |||
| return h.Handle(NewTaskContext(self), data) | |||
| }) | |||
| if nil != err { | |||
| return | |||
| } | |||
| } | |||
| wg.Wait() | |||
| } | |||
| func (self *KeplerService) Serve() error { | |||
| go self.TaskProc() | |||
| go self.MessageProc() | |||
| return http.ListenAndServe(self.option.ListenAddr, self.router) | |||
| } | |||
| func (self *KeplerService) Register_RestletHandler(prefix string, methods []string, handler restlet.RestletHandler, cache_ctrl *restlet.CacheController) { | |||
| self.registerRestlet(prefix, methods, handler, cache_ctrl) | |||
| } | |||
| func (self *KeplerService) Register_TaskHandler(topic string, handler restlet.TaskletHandler) { | |||
| self._task_handlers[topic] = handler | |||
| } | |||
| func (self *KeplerService) Register_MessageHandler(topic string, handler restlet.TaskletHandler) { | |||
| self._msg_handlers[topic] = handler | |||
| } | |||
| func (self *KeplerService) load_builtin_handlers() { | |||
| for _, x := range builtin_restlet_handlers { | |||
| self.registerRestlet(x.prefix, x.methods, x.handler, x.cache_control) | |||
| } | |||
| for _, x := range builtin_tasklet_handlers { | |||
| self._task_handlers[x.name] = x.handler | |||
| } | |||
| for _, x := range builtin_message_handlers { | |||
| self._msg_handlers[x.name] = x.handler | |||
| } | |||
| } | |||
| var builtin_restlet_handlers []ServiceRestlet = []ServiceRestlet{} | |||
| var builtin_tasklet_handlers []ServiceTasklet = []ServiceTasklet{} | |||
| var builtin_message_handlers []ServiceMessagelet = []ServiceMessagelet{} | |||
| func RegisterRestletHandleFunc(f func(ctx restlet.RequestContext, url_params restlet.Parameters, queries restlet.Parameters, post_data []byte) (*restlet.RestletResult, error), | |||
| methods string, rcc *restlet.CacheController, prefixes ...string) { | |||
| _registerHandler(restlet.RestletHandleFunc(f), methods, rcc, prefixes...) | |||
| } | |||
| func _registerHandler(handler restlet.RestletHandler, methods string, rcc *restlet.CacheController, prefixes ...string) { | |||
| for _, prefix := range prefixes { | |||
| prefix = strings.TrimLeft(strings.TrimSpace(prefix), "/") | |||
| if prefix == "" { | |||
| continue | |||
| } | |||
| p := prefix | |||
| ms := strings.Split(methods, ",") | |||
| if len(ms) == 0 { | |||
| ms = []string{"*"} | |||
| } else { | |||
| for i, x := range ms { | |||
| ms[i] = strings.ToUpper(x) | |||
| } | |||
| } | |||
| builtin_restlet_handlers = append(builtin_restlet_handlers, ServiceRestlet{ | |||
| methods: ms, | |||
| prefix: p, | |||
| handler: handler, | |||
| cache_control: rcc, | |||
| }) | |||
| } | |||
| } | |||
| func RegisterTasklet(queue string, f func(restlet.TaskContext, ...interface{}) error) { | |||
| builtin_tasklet_handlers = append(builtin_tasklet_handlers, ServiceTasklet{name: queue, handler: restlet.TaskletHandlerFunc(f)}) | |||
| } | |||
| func RegisterMsgHandle(queue string, f func(restlet.TaskContext, ...interface{}) error) { | |||
| builtin_message_handlers = append(builtin_message_handlers, ServiceMessagelet{name: queue, handler: restlet.TaskletHandlerFunc(f)}) | |||
| package service | |||
| import ( | |||
| "net/http" | |||
| "database/sql" | |||
| "github.com/gorilla/mux" | |||
| _ "github.com/lib/pq" | |||
| log "github.com/Sirupsen/logrus" | |||
| "strings" | |||
| "cygnux/kepler/restlet" | |||
| "sync" | |||
| "cygnux/kepler/cache" | |||
| "cygnux/kepler/kv" | |||
| "cygnux/kepler/utils" | |||
| "cygnux/kepler/msq" | |||
| "cygnux/kepler/configs" | |||
| ) | |||
| type KeplerService struct { | |||
| prefix string | |||
| option configs.GenericOption | |||
| params configs.ParameterOption | |||
| db *sql.DB | |||
| db_schema string | |||
| router *mux.Router | |||
| cache cache.Cache | |||
| kvstore kv.KV | |||
| mpub msq.Publisher | |||
| msub msq.Subscriber | |||
| _task_chan chan restlet.TaskObject | |||
| _task_handlers map[string]restlet.TaskletHandler | |||
| _msg_handlers map[string]restlet.TaskletHandler | |||
| } | |||
| const URL_PREFIX = "/" | |||
| func NewService(op OptionProvider, prefixes ...string) (*KeplerService, error) { | |||
| log.Debugln("NewService:> ", op.Option()) | |||
| var e error | |||
| if len(prefixes) == 0 { | |||
| prefixes = []string{URL_PREFIX} | |||
| } | |||
| svr := &KeplerService{ | |||
| params:op.Parameters(), | |||
| option: op.Option(), | |||
| router: mux.NewRouter().StrictSlash(true), | |||
| prefix: prefixes[0], | |||
| } | |||
| if svr.db, svr.db_schema, e = utils.SqlDBConnect(op.Option().DB); nil != e { | |||
| log.Errorln("Open database failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.cache, e = cache.NewCache(op.Option().Cache); nil != e { | |||
| log.Errorln("Make Cache failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.kvstore, e = kv.NewKV(op.Option().KV); nil != e { | |||
| log.Errorln("Make KVStore failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.mpub, e = msq.NewPublisher(op.Option().MPub); nil != e { | |||
| log.Errorln("Make MPub failed:> ", e) | |||
| return nil, e | |||
| } | |||
| if svr.msub, e = msq.NewSubscriber(op.Option().MSub); nil != e { | |||
| log.Errorln("Make MSub failed:> ", e) | |||
| return nil, e | |||
| } | |||
| svr._task_chan = make(chan restlet.TaskObject, 1024) | |||
| if op.Option().Debug { | |||
| restlet.SetDebug(op.Option().Debug) | |||
| log.Debugln("Restlet debug on!") | |||
| } | |||
| svr._task_handlers = make(map[string]restlet.TaskletHandler) | |||
| svr._msg_handlers = make(map[string]restlet.TaskletHandler) | |||
| svr.load_builtin_handlers() | |||
| return svr, nil | |||
| } | |||
| const X_CYGNUX_SIGN = "X-CYGNUX-SIGN" | |||
| func (self *KeplerService) Router() *mux.Router { | |||
| return self.router | |||
| } | |||
| func (self *KeplerService) Predicate(request *http.Request) (string, bool) { | |||
| sign := request.Header.Get(X_CYGNUX_SIGN) | |||
| log.Infoln("X-CYGNUX-SIGN:> ", sign) | |||
| return "", true | |||
| if sign == "" { | |||
| return "", false | |||
| } | |||
| return "", true | |||
| } | |||
| func (self *KeplerService) NewContext(request *http.Request) restlet.RequestContext { | |||
| return NewRequestContext(self, request) | |||
| } | |||
| func (self *KeplerService) makeRestletHandler(h restlet.RestletHandler, methods []string, cache *restlet.CacheController) http.Handler { | |||
| return restlet.MakeRestletHandler(h, self, self, methods, cache) | |||
| } | |||
| func (self *KeplerService) registerRestlet(prefix string, methods []string, handler restlet.RestletHandler, cache *restlet.CacheController) { | |||
| h := self.makeRestletHandler(handler, methods, cache) | |||
| log.Infof("Register:> Registering %s: %s ...", strings.Join(methods, ","), self.prefix + "/" + prefix) | |||
| self.router.Handle(self.prefix + "/" + prefix, h) | |||
| } | |||
| func (self *KeplerService) TaskProc() { | |||
| for t := range self._task_chan { | |||
| if h, ok := self._task_handlers[t.Queue]; ok { | |||
| if e := h.Handle(NewTaskContext(self), t.Params...); nil != e { | |||
| log.Errorf("TaskProc:> %s Handle failed:> %s \n", t.Queue, e) | |||
| } | |||
| } else { | |||
| log.Warnln("TaskProc:> Missing task handler for:", t.Queue) | |||
| } | |||
| } | |||
| } | |||
| func (self *KeplerService) MessageProc() { | |||
| wg := &sync.WaitGroup{} | |||
| for k, h := range self._msg_handlers { | |||
| wg.Add(1) | |||
| err := self.msub.Subscribe(k, func(data []byte) error { | |||
| return h.Handle(NewTaskContext(self), data) | |||
| }) | |||
| if nil != err { | |||
| return | |||
| } | |||
| } | |||
| wg.Wait() | |||
| } | |||
| func (self *KeplerService) Serve() error { | |||
| go self.TaskProc() | |||
| go self.MessageProc() | |||
| return http.ListenAndServe(self.option.ListenAddr, self.router) | |||
| } | |||
| func (self *KeplerService) Register_RestletHandler(prefix string, methods []string, handler restlet.RestletHandler, cache_ctrl *restlet.CacheController) { | |||
| self.registerRestlet(prefix, methods, handler, cache_ctrl) | |||
| } | |||
| func (self *KeplerService) Register_TaskHandler(topic string, handler restlet.TaskletHandler) { | |||
| self._task_handlers[topic] = handler | |||
| } | |||
| func (self *KeplerService) Register_MessageHandler(topic string, handler restlet.TaskletHandler) { | |||
| self._msg_handlers[topic] = handler | |||
| } | |||
| func (self *KeplerService) load_builtin_handlers() { | |||
| for _, x := range builtin_restlet_handlers { | |||
| self.registerRestlet(x.prefix, x.methods, x.handler, x.cache_control) | |||
| } | |||
| for _, x := range builtin_tasklet_handlers { | |||
| self._task_handlers[x.name] = x.handler | |||
| } | |||
| for _, x := range builtin_message_handlers { | |||
| self._msg_handlers[x.name] = x.handler | |||
| } | |||
| } | |||
| var builtin_restlet_handlers []ServiceRestlet = []ServiceRestlet{} | |||
| var builtin_tasklet_handlers []ServiceTasklet = []ServiceTasklet{} | |||
| var builtin_message_handlers []ServiceMessagelet = []ServiceMessagelet{} | |||
| var builtin_initialize_procs []ServiceTasklet = []ServiceTasklet{} | |||
| /** | |||
| * RegisterRestletHandleFunc | |||
| * Register a Restlet handler to service. | |||
| */ | |||
| func RegisterRestletHandleFunc(f func(ctx restlet.RequestContext, url_params restlet.Parameters, queries restlet.Parameters, post_data []byte) (*restlet.RestletResult, error), | |||
| methods string, rcc *restlet.CacheController, prefixes ...string) { | |||
| _registerHandler(restlet.RestletHandleFunc(f), methods, rcc, prefixes...) | |||
| } | |||
| func _registerHandler(handler restlet.RestletHandler, methods string, rcc *restlet.CacheController, prefixes ...string) { | |||
| for _, prefix := range prefixes { | |||
| prefix = strings.TrimLeft(strings.TrimSpace(prefix), "/") | |||
| if prefix == "" { | |||
| continue | |||
| } | |||
| p := prefix | |||
| ms := strings.Split(methods, ",") | |||
| if len(ms) == 0 { | |||
| ms = []string{"*"} | |||
| } else { | |||
| for i, x := range ms { | |||
| ms[i] = strings.ToUpper(x) | |||
| } | |||
| } | |||
| builtin_restlet_handlers = append(builtin_restlet_handlers, ServiceRestlet{ | |||
| methods: ms, | |||
| prefix: p, | |||
| handler: handler, | |||
| cache_control: rcc, | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * RegisterTasklet | |||
| * Register a background task. | |||
| */ | |||
| func RegisterTasklet(queue string, f func(restlet.TaskContext, ...interface{}) error) { | |||
| builtin_tasklet_handlers = append(builtin_tasklet_handlers, ServiceTasklet{name: queue, handler: restlet.TaskletHandlerFunc(f)}) | |||
| } | |||
| /** | |||
| * RegisterMsgHandle | |||
| * Register a message handler | |||
| */ | |||
| func RegisterMsgHandle(queue string, f func(restlet.TaskContext, ...interface{}) error) { | |||
| builtin_message_handlers = append(builtin_message_handlers, ServiceMessagelet{name: queue, handler: restlet.TaskletHandlerFunc(f)}) | |||
| } | |||
| /** | |||
| * RegisterInitialize | |||
| * Register an intialize function for service, function only called when service initialize funcation was called. | |||
| */ | |||
| func RegisterInitialize(name string, f func(restlet.TaskContext,...interface{}) error) { | |||
| builtin_initialize_procs = append(builtin_initialize_procs, ServiceTasklet{name:name, handler:restlet.TaskletHandler(f)}) | |||
| } | |||