chore(queue): support NSQ as backend. (#600)
This commit is contained in:
parent
c7112a6eb3
commit
2e2dd9b8d6
|
@ -146,6 +146,13 @@ huawei:
|
||||||
appid: "YOUR_APP_ID"
|
appid: "YOUR_APP_ID"
|
||||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||||
|
|
||||||
|
queue:
|
||||||
|
engine: "nsq" # support "local", "nsq", default value is "local"
|
||||||
|
nsq:
|
||||||
|
addr: 127.0.0.1:4150
|
||||||
|
topic: gorush
|
||||||
|
channel: ch
|
||||||
|
|
||||||
ios:
|
ios:
|
||||||
enabled: false
|
enabled: false
|
||||||
key_path: "key.pem"
|
key_path: "key.pem"
|
||||||
|
|
|
@ -62,6 +62,13 @@ huawei:
|
||||||
appid: "YOUR_APP_ID"
|
appid: "YOUR_APP_ID"
|
||||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||||
|
|
||||||
|
queue:
|
||||||
|
engine: "local" # support "local", "nsq", default value is "local"
|
||||||
|
nsq:
|
||||||
|
addr: 127.0.0.1:4150
|
||||||
|
topic: gorush
|
||||||
|
channel: ch
|
||||||
|
|
||||||
ios:
|
ios:
|
||||||
enabled: false
|
enabled: false
|
||||||
key_path: ""
|
key_path: ""
|
||||||
|
@ -106,6 +113,7 @@ type ConfYaml struct {
|
||||||
Android SectionAndroid `yaml:"android"`
|
Android SectionAndroid `yaml:"android"`
|
||||||
Huawei SectionHuawei `yaml:"huawei"`
|
Huawei SectionHuawei `yaml:"huawei"`
|
||||||
Ios SectionIos `yaml:"ios"`
|
Ios SectionIos `yaml:"ios"`
|
||||||
|
Queue SectionQueue `yaml:"queue"`
|
||||||
Log SectionLog `yaml:"log"`
|
Log SectionLog `yaml:"log"`
|
||||||
Stat SectionStat `yaml:"stat"`
|
Stat SectionStat `yaml:"stat"`
|
||||||
GRPC SectionGRPC `yaml:"grpc"`
|
GRPC SectionGRPC `yaml:"grpc"`
|
||||||
|
@ -201,6 +209,19 @@ type SectionStat struct {
|
||||||
BadgerDB SectionBadgerDB `yaml:"badgerdb"`
|
BadgerDB SectionBadgerDB `yaml:"badgerdb"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SectionQueue is sub section of config.
|
||||||
|
type SectionQueue struct {
|
||||||
|
Engine string `yaml:"engine"`
|
||||||
|
NSQ SectionNSQ `yaml:"nsq"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SectionNSQ is sub section of config.
|
||||||
|
type SectionNSQ struct {
|
||||||
|
Addr string `yaml:"addr"`
|
||||||
|
Topic string `yaml:"topic"`
|
||||||
|
Channel string `yaml:"channel"`
|
||||||
|
}
|
||||||
|
|
||||||
// SectionRedis is sub section of config.
|
// SectionRedis is sub section of config.
|
||||||
type SectionRedis struct {
|
type SectionRedis struct {
|
||||||
Addr string `yaml:"addr"`
|
Addr string `yaml:"addr"`
|
||||||
|
@ -341,6 +362,12 @@ func LoadConf(confPath ...string) (ConfYaml, error) {
|
||||||
conf.Log.ErrorLevel = viper.GetString("log.error_level")
|
conf.Log.ErrorLevel = viper.GetString("log.error_level")
|
||||||
conf.Log.HideToken = viper.GetBool("log.hide_token")
|
conf.Log.HideToken = viper.GetBool("log.hide_token")
|
||||||
|
|
||||||
|
// Queue Engine
|
||||||
|
conf.Queue.Engine = viper.GetString("queue.engine")
|
||||||
|
conf.Queue.NSQ.Addr = viper.GetString("queue.nsq.addr")
|
||||||
|
conf.Queue.NSQ.Topic = viper.GetString("queue.nsq.topic")
|
||||||
|
conf.Queue.NSQ.Channel = viper.GetString("queue.nsq.channel")
|
||||||
|
|
||||||
// Stat Engine
|
// Stat Engine
|
||||||
conf.Stat.Engine = viper.GetString("stat.engine")
|
conf.Stat.Engine = viper.GetString("stat.engine")
|
||||||
conf.Stat.Redis.Addr = viper.GetString("stat.redis.addr")
|
conf.Stat.Redis.Addr = viper.GetString("stat.redis.addr")
|
||||||
|
|
|
@ -88,6 +88,12 @@ func (suite *ConfigTestSuite) TestValidateConfDefault() {
|
||||||
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.KeyID)
|
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.KeyID)
|
||||||
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.TeamID)
|
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.TeamID)
|
||||||
|
|
||||||
|
// queue
|
||||||
|
assert.Equal(suite.T(), "local", suite.ConfGorushDefault.Queue.Engine)
|
||||||
|
assert.Equal(suite.T(), "127.0.0.1:4150", suite.ConfGorushDefault.Queue.NSQ.Addr)
|
||||||
|
assert.Equal(suite.T(), "gorush", suite.ConfGorushDefault.Queue.NSQ.Topic)
|
||||||
|
assert.Equal(suite.T(), "ch", suite.ConfGorushDefault.Queue.NSQ.Channel)
|
||||||
|
|
||||||
// log
|
// log
|
||||||
assert.Equal(suite.T(), "string", suite.ConfGorushDefault.Log.Format)
|
assert.Equal(suite.T(), "string", suite.ConfGorushDefault.Log.Format)
|
||||||
assert.Equal(suite.T(), "stdout", suite.ConfGorushDefault.Log.AccessLog)
|
assert.Equal(suite.T(), "stdout", suite.ConfGorushDefault.Log.AccessLog)
|
||||||
|
|
|
@ -49,6 +49,13 @@ huawei:
|
||||||
appid: "YOUR_APP_ID"
|
appid: "YOUR_APP_ID"
|
||||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||||
|
|
||||||
|
queue:
|
||||||
|
engine: "nsq" # support "local", "nsq", default value is "local"
|
||||||
|
nsq:
|
||||||
|
addr: 127.0.0.1:4150
|
||||||
|
topic: gorush
|
||||||
|
channel: ch
|
||||||
|
|
||||||
ios:
|
ios:
|
||||||
enabled: false
|
enabled: false
|
||||||
key_path: "key.pem"
|
key_path: "key.pem"
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
// Queue as backend
|
||||||
|
type Queue string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// LocalQueue for channel in Go
|
||||||
|
LocalQueue Queue = "local"
|
||||||
|
// NSQ a realtime distributed messaging platform
|
||||||
|
NSQ Queue = "nsq"
|
||||||
|
// NATS Connective Technology for Adaptive Edge & Distributed Systems
|
||||||
|
NATS Queue = "nats"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsLocalQueue check is Local Queue
|
||||||
|
func IsLocalQueue(q Queue) bool {
|
||||||
|
return q == LocalQueue
|
||||||
|
}
|
2
go.mod
2
go.mod
|
@ -13,12 +13,14 @@ require (
|
||||||
github.com/gin-contrib/logger v0.2.0
|
github.com/gin-contrib/logger v0.2.0
|
||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/gin-gonic/gin v1.7.2
|
||||||
github.com/go-redis/redis/v7 v7.4.0
|
github.com/go-redis/redis/v7 v7.4.0
|
||||||
|
github.com/golang/glog v0.0.0-20210429001901-424d2337a529 // indirect
|
||||||
github.com/golang/protobuf v1.5.1
|
github.com/golang/protobuf v1.5.1
|
||||||
github.com/google/flatbuffers v2.0.0+incompatible // indirect
|
github.com/google/flatbuffers v2.0.0+incompatible // indirect
|
||||||
github.com/json-iterator/go v1.1.10
|
github.com/json-iterator/go v1.1.10
|
||||||
github.com/mattn/go-isatty v0.0.12
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/mitchellh/mapstructure v1.4.1
|
github.com/mitchellh/mapstructure v1.4.1
|
||||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616114002-91cd23dfeed4
|
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616114002-91cd23dfeed4
|
||||||
|
github.com/nsqio/go-nsq v1.0.8
|
||||||
github.com/prometheus/client_golang v1.10.0
|
github.com/prometheus/client_golang v1.10.0
|
||||||
github.com/rs/zerolog v1.23.0
|
github.com/rs/zerolog v1.23.0
|
||||||
github.com/sideshow/apns2 v0.20.0
|
github.com/sideshow/apns2 v0.20.0
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -154,8 +154,9 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/glog v0.0.0-20210429001901-424d2337a529 h1:2voWjNECnrZRbfwXxHB1/j8wa6xdKn85B5NzgVL/pTU=
|
||||||
|
github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||||
|
@ -318,6 +319,8 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
|
||||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
github.com/nsqio/go-nsq v1.0.8 h1:3L2F8tNLlwXXlp2slDUrUWSBn2O3nMh8R1/KEDFTHPk=
|
||||||
|
github.com/nsqio/go-nsq v1.0.8/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY=
|
||||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
|
|
@ -391,6 +391,10 @@ func getApnsClient(cfg config.ConfYaml, req PushNotification) (client *apns2.Cli
|
||||||
func PushToIOS(req PushNotification) {
|
func PushToIOS(req PushNotification) {
|
||||||
logx.LogAccess.Debug("Start push notification for iOS")
|
logx.LogAccess.Debug("Start push notification for iOS")
|
||||||
|
|
||||||
|
if req.Cfg.Core.Sync && !core.IsLocalQueue(core.Queue(req.Cfg.Queue.Engine)) {
|
||||||
|
req.Cfg.Core.Sync = false
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
retryCount = 0
|
retryCount = 0
|
||||||
maxRetry = req.Cfg.Ios.MaxRetry
|
maxRetry = req.Cfg.Ios.MaxRetry
|
||||||
|
|
|
@ -109,6 +109,10 @@ func GetAndroidNotification(req PushNotification) *fcm.Message {
|
||||||
func PushToAndroid(req PushNotification) {
|
func PushToAndroid(req PushNotification) {
|
||||||
logx.LogAccess.Debug("Start push notification for Android")
|
logx.LogAccess.Debug("Start push notification for Android")
|
||||||
|
|
||||||
|
if req.Cfg.Core.Sync && !core.IsLocalQueue(core.Queue(req.Cfg.Queue.Engine)) {
|
||||||
|
req.Cfg.Core.Sync = false
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
client *fcm.Client
|
client *fcm.Client
|
||||||
retryCount = 0
|
retryCount = 0
|
||||||
|
|
|
@ -6,24 +6,25 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
|
||||||
c "github.com/msalihkarakasli/go-hms-push/push/config"
|
c "github.com/msalihkarakasli/go-hms-push/push/config"
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/core"
|
client "github.com/msalihkarakasli/go-hms-push/push/core"
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
pushError error
|
pushError error
|
||||||
pushClient *core.HMSClient
|
pushClient *client.HMSClient
|
||||||
once sync.Once
|
once sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPushClient use for create HMS Push
|
// GetPushClient use for create HMS Push
|
||||||
func GetPushClient(conf *c.Config) (*core.HMSClient, error) {
|
func GetPushClient(conf *c.Config) (*client.HMSClient, error) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
client, err := core.NewHttpClient(conf)
|
client, err := client.NewHttpClient(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +36,7 @@ func GetPushClient(conf *c.Config) (*core.HMSClient, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitHMSClient use for initialize HMS Client.
|
// InitHMSClient use for initialize HMS Client.
|
||||||
func InitHMSClient(cfg config.ConfYaml, appSecret, appID string) (*core.HMSClient, error) {
|
func InitHMSClient(cfg config.ConfYaml, appSecret, appID string) (*client.HMSClient, error) {
|
||||||
if appSecret == "" {
|
if appSecret == "" {
|
||||||
return nil, errors.New("Missing Huawei App Secret")
|
return nil, errors.New("Missing Huawei App Secret")
|
||||||
}
|
}
|
||||||
|
@ -167,12 +168,15 @@ func GetHuaweiNotification(req PushNotification) (*model.MessageRequest, error)
|
||||||
// PushToHuawei provide send notification to Android server.
|
// PushToHuawei provide send notification to Android server.
|
||||||
func PushToHuawei(req PushNotification) bool {
|
func PushToHuawei(req PushNotification) bool {
|
||||||
logx.LogAccess.Debug("Start push notification for Huawei")
|
logx.LogAccess.Debug("Start push notification for Huawei")
|
||||||
cfg := req.Cfg
|
|
||||||
|
if req.Cfg.Core.Sync && !core.IsLocalQueue(core.Queue(req.Cfg.Queue.Engine)) {
|
||||||
|
req.Cfg.Core.Sync = false
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
client *core.HMSClient
|
client *client.HMSClient
|
||||||
retryCount = 0
|
retryCount = 0
|
||||||
maxRetry = cfg.Huawei.MaxRetry
|
maxRetry = req.Cfg.Huawei.MaxRetry
|
||||||
)
|
)
|
||||||
|
|
||||||
if req.Retry > 0 && req.Retry < maxRetry {
|
if req.Retry > 0 && req.Retry < maxRetry {
|
||||||
|
@ -191,7 +195,7 @@ Retry:
|
||||||
|
|
||||||
notification, _ := GetHuaweiNotification(req)
|
notification, _ := GetHuaweiNotification(req)
|
||||||
|
|
||||||
client, err = InitHMSClient(cfg, cfg.Huawei.AppSecret, cfg.Huawei.AppID)
|
client, err = InitHMSClient(req.Cfg, req.Cfg.Huawei.AppSecret, req.Cfg.Huawei.AppID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// HMS server error
|
// HMS server error
|
||||||
|
|
12
main.go
12
main.go
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/gorush"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/appleboy/gorush/queue"
|
"github.com/appleboy/gorush/queue"
|
||||||
|
"github.com/appleboy/gorush/queue/nsq"
|
||||||
"github.com/appleboy/gorush/queue/simple"
|
"github.com/appleboy/gorush/queue/simple"
|
||||||
"github.com/appleboy/gorush/router"
|
"github.com/appleboy/gorush/router"
|
||||||
"github.com/appleboy/gorush/rpc"
|
"github.com/appleboy/gorush/rpc"
|
||||||
|
@ -316,7 +317,16 @@ func main() {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w := simple.NewWorker(simple.WithQueueNum(int(cfg.Core.QueueNum)))
|
var w queue.Worker
|
||||||
|
switch core.Queue(cfg.Queue.Engine) {
|
||||||
|
case core.LocalQueue:
|
||||||
|
w = simple.NewWorker(simple.WithQueueNum(int(cfg.Core.QueueNum)))
|
||||||
|
case core.NSQ:
|
||||||
|
w = nsq.NewWorker()
|
||||||
|
default:
|
||||||
|
logx.LogError.Fatalf("we don't support queue engine: %s", cfg.Queue.Engine)
|
||||||
|
}
|
||||||
|
|
||||||
q := queue.NewQueue(w, int(cfg.Core.WorkerNum))
|
q := queue.NewQueue(w, int(cfg.Core.WorkerNum))
|
||||||
q.Start()
|
q.Start()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
package nsq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/appleboy/gorush/gorush"
|
||||||
|
"github.com/appleboy/gorush/queue"
|
||||||
|
|
||||||
|
"github.com/nsqio/go-nsq"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ queue.Worker = (*Worker)(nil)
|
||||||
|
|
||||||
|
// Option for queue system
|
||||||
|
type Option func(*Worker)
|
||||||
|
|
||||||
|
// Worker for NSQ
|
||||||
|
type Worker struct {
|
||||||
|
q *nsq.Consumer
|
||||||
|
p *nsq.Producer
|
||||||
|
once sync.Once
|
||||||
|
addr string
|
||||||
|
topic string
|
||||||
|
channel string
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAddr setup the addr of NSQ
|
||||||
|
func WithAddr(addr string) Option {
|
||||||
|
return func(w *Worker) {
|
||||||
|
w.addr = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTopic setup the topic of NSQ
|
||||||
|
func WithTopic(topic string) Option {
|
||||||
|
return func(w *Worker) {
|
||||||
|
w.topic = topic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithChannel setup the channel of NSQ
|
||||||
|
func WithChannel(channel string) Option {
|
||||||
|
return func(w *Worker) {
|
||||||
|
w.channel = channel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWorker for struc
|
||||||
|
func NewWorker(opts ...Option) *Worker {
|
||||||
|
w := &Worker{
|
||||||
|
addr: "127.0.0.1:4150",
|
||||||
|
topic: "gorush",
|
||||||
|
channel: "ch",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through each option
|
||||||
|
for _, opt := range opts {
|
||||||
|
// Call the option giving the instantiated
|
||||||
|
opt(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := nsq.NewConfig()
|
||||||
|
q, err := nsq.NewConsumer(w.topic, w.channel, cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
w.q = q
|
||||||
|
|
||||||
|
p, err := nsq.NewProducer(w.addr, cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
w.p = p
|
||||||
|
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeRun run script before start worker
|
||||||
|
func (s *Worker) BeforeRun() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterRun run script after start worker
|
||||||
|
func (s *Worker) AfterRun() error {
|
||||||
|
s.once.Do(func() {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
err := s.q.ConnectToNSQLookupd(s.addr)
|
||||||
|
if err != nil {
|
||||||
|
panic("Could not connect nsq server: " + err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run start the worker
|
||||||
|
func (s *Worker) Run(quit chan struct{}) error {
|
||||||
|
s.q.AddHandler(nsq.HandlerFunc(func(msg *nsq.Message) error {
|
||||||
|
var notification gorush.PushNotification
|
||||||
|
if err := json.Unmarshal(msg.Body, ¬ification); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gorush.SendNotification(notification)
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-quit:
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown worker
|
||||||
|
func (s *Worker) Shutdown() error {
|
||||||
|
s.q.Stop()
|
||||||
|
s.p.Stop()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capacity for channel
|
||||||
|
func (s *Worker) Capacity() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage for count of channel usage
|
||||||
|
func (s *Worker) Usage() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue send notification to queue
|
||||||
|
func (s *Worker) Queue(job interface{}) error {
|
||||||
|
v, ok := job.(gorush.PushNotification)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("wrong type of job")
|
||||||
|
}
|
||||||
|
err := s.p.Publish(s.topic, v.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -64,6 +64,7 @@ func (q *Queue) Queue(job interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) work(num int) {
|
func (q *Queue) work(num int) {
|
||||||
|
q.worker.BeforeRun()
|
||||||
q.routineGroup.Run(func() {
|
q.routineGroup.Run(func() {
|
||||||
// to handle panic cases from inside the worker
|
// to handle panic cases from inside the worker
|
||||||
// in such case, we start a new goroutine
|
// in such case, we start a new goroutine
|
||||||
|
@ -78,6 +79,7 @@ func (q *Queue) work(num int) {
|
||||||
q.worker.Run(q.quit)
|
q.worker.Run(q.quit)
|
||||||
logx.LogAccess.Info("closed the worker num ", num)
|
logx.LogAccess.Info("closed the worker num ", num)
|
||||||
})
|
})
|
||||||
|
q.worker.AfterRun()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) startWorker() {
|
func (q *Queue) startWorker() {
|
||||||
|
|
|
@ -20,6 +20,16 @@ type Worker struct {
|
||||||
queueNotification chan gorush.PushNotification
|
queueNotification chan gorush.PushNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BeforeRun run script before start worker
|
||||||
|
func (s *Worker) BeforeRun() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterRun run script after start worker
|
||||||
|
func (s *Worker) AfterRun() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Run start the worker
|
// Run start the worker
|
||||||
func (s *Worker) Run(_ chan struct{}) error {
|
func (s *Worker) Run(_ chan struct{}) error {
|
||||||
for notification := range s.queueNotification {
|
for notification := range s.queueNotification {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/gorush"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@ package queue
|
||||||
|
|
||||||
// Worker interface
|
// Worker interface
|
||||||
type Worker interface {
|
type Worker interface {
|
||||||
|
BeforeRun() error
|
||||||
Run(chan struct{}) error
|
Run(chan struct{}) error
|
||||||
|
AfterRun() error
|
||||||
|
|
||||||
Shutdown() error
|
Shutdown() error
|
||||||
Queue(job interface{}) error
|
Queue(job interface{}) error
|
||||||
Capacity() int
|
Capacity() int
|
||||||
|
|
|
@ -250,6 +250,11 @@ func handleNotification(ctx context.Context, cfg config.ConfYaml, req gorush.Req
|
||||||
var count int
|
var count int
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
newNotification := []*gorush.PushNotification{}
|
newNotification := []*gorush.PushNotification{}
|
||||||
|
|
||||||
|
if cfg.Core.Sync && !core.IsLocalQueue(core.Queue(cfg.Queue.Engine)) {
|
||||||
|
cfg.Core.Sync = false
|
||||||
|
}
|
||||||
|
|
||||||
for i := range req.Notifications {
|
for i := range req.Notifications {
|
||||||
notification := &req.Notifications[i]
|
notification := &req.Notifications[i]
|
||||||
switch notification.Platform {
|
switch notification.Platform {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stats provide response time, status code count, etc.
|
// Stats provide response time, status code count, etc.
|
||||||
var Stats = stats.New()
|
var Stats *stats.Stats
|
||||||
|
|
||||||
// StatStorage implements the storage interface
|
// StatStorage implements the storage interface
|
||||||
var StatStorage storage.Storage
|
var StatStorage storage.Storage
|
||||||
|
@ -78,5 +78,7 @@ func InitAppStatus(conf config.ConfYaml) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stats = stats.New()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue