github.com/wfusion/gofusion@v1.1.14/cron/construct.go (about) 1 package cron 2 3 import ( 4 "context" 5 "log" 6 "sync" 7 "syscall" 8 9 "github.com/pkg/errors" 10 11 "github.com/wfusion/gofusion/common/di" 12 "github.com/wfusion/gofusion/common/utils" 13 "github.com/wfusion/gofusion/config" 14 15 _ "github.com/wfusion/gofusion/log/customlogger" 16 ) 17 18 var ( 19 locker sync.RWMutex 20 routers map[string]map[string]IRouter 21 ) 22 23 func Construct(ctx context.Context, confs map[string]*Conf, opts ...utils.OptionExtender) func() { 24 opt := utils.ApplyOptions[config.InitOption](opts...) 25 optU := utils.ApplyOptions[useOption](opts...) 26 if opt.AppName == "" { 27 opt.AppName = optU.appName 28 } 29 30 for name, conf := range confs { 31 addInstance(ctx, name, conf, opt) 32 } 33 return func() { 34 locker.Lock() 35 defer locker.Unlock() 36 37 pid := syscall.Getpid() 38 app := config.Use(opt.AppName).AppName() 39 if routers != nil { 40 for name, router := range routers[opt.AppName] { 41 log.Printf("%v [Gofusion] %s %s %s exiting...", pid, app, config.ComponentCron, name) 42 if err := router.shutdown(); err == nil { 43 log.Printf("%v [Gofusion] %s %s %s exited", pid, app, config.ComponentCron, name) 44 } else { 45 log.Printf("%v [Gofusion] %s %s %s exit failed: %s", pid, app, config.ComponentCron, name, err) 46 } 47 } 48 delete(routers, opt.AppName) 49 } 50 } 51 } 52 53 func addInstance(ctx context.Context, name string, conf *Conf, opt *config.InitOption) { 54 var r IRouter 55 switch conf.Type { 56 case schedulerTypeAsynq: 57 r = newAsynq(ctx, opt.AppName, name, conf) 58 default: 59 panic(ErrUnsupportedSchedulerType) 60 } 61 62 locker.Lock() 63 defer locker.Unlock() 64 if routers == nil { 65 routers = make(map[string]map[string]IRouter) 66 } 67 if routers[opt.AppName] == nil { 68 routers[opt.AppName] = make(map[string]IRouter) 69 } 70 if _, ok := routers[opt.AppName][name]; ok { 71 panic(errors.Errorf("duplicated cron name: %s", name)) 72 } 73 routers[opt.AppName][name] = r 74 75 // ioc 76 if opt.DI != nil { 77 opt.DI.MustProvide( 78 func() IRouter { return Use(name, AppName(opt.AppName)) }, 79 di.Name(name), 80 ) 81 } 82 } 83 84 type useOption struct { 85 appName string 86 } 87 88 func AppName(name string) utils.OptionFunc[useOption] { 89 return func(o *useOption) { 90 o.appName = name 91 } 92 } 93 94 func Use(name string, opts ...utils.OptionExtender) IRouter { 95 opt := utils.ApplyOptions[useOption](opts...) 96 97 locker.RLock() 98 defer locker.RUnlock() 99 routers, ok := routers[opt.appName] 100 if !ok { 101 panic(errors.Errorf("cron router instance not found for app: %s", opt.appName)) 102 } 103 104 router, ok := routers[name] 105 if !ok { 106 panic(errors.Errorf("cron router instance not found for name: %s", name)) 107 } 108 return router 109 } 110 111 func init() { 112 config.AddComponent(config.ComponentCron, Construct, config.WithFlag(&flagString)) 113 }