diff --git a/README.md b/README.md index 7198cb3..b4429e6 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ core: worker_num: 0 # default worker number is runtime.NumCPU() queue_num: 0 # default queue number is 8192 max_notification: 100 + sync: false # set true if you get http response after finish send notification. mode: "release" ssl: false cert_path: "cert.pem" diff --git a/config/config.go b/config/config.go index 7b8e892..a43a961 100644 --- a/config/config.go +++ b/config/config.go @@ -24,6 +24,7 @@ type SectionCore struct { WorkerNum int64 `yaml:"worker_num"` QueueNum int64 `yaml:"queue_num"` Mode string `yaml:"mode"` + Sync bool `yaml:"sync"` SSL bool `yaml:"ssl"` CertPath string `yaml:"cert_path"` KeyPath string `yaml:"key_path"` @@ -123,6 +124,7 @@ func BuildDefaultPushConf() ConfYaml { conf.Core.WorkerNum = int64(runtime.NumCPU()) conf.Core.QueueNum = int64(8192) conf.Core.Mode = "release" + conf.Core.Sync = false conf.Core.SSL = false conf.Core.CertPath = "cert.pem" conf.Core.KeyPath = "key.pem" diff --git a/config/config.yml b/config/config.yml index b079239..81191ac 100644 --- a/config/config.yml +++ b/config/config.yml @@ -3,6 +3,7 @@ core: worker_num: 0 # default worker number is runtime.NumCPU() queue_num: 0 # default queue number is 8192 max_notification: 100 + sync: false # set true if you get http response after finish send notification. mode: "release" ssl: false cert_path: "cert.pem" diff --git a/config/config_test.go b/config/config_test.go index 7f72015..829dfea 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -59,6 +59,7 @@ func (suite *ConfigTestSuite) TestValidateConfDefault() { assert.Equal(suite.T(), int64(runtime.NumCPU()), suite.ConfGorushDefault.Core.WorkerNum) assert.Equal(suite.T(), int64(8192), suite.ConfGorushDefault.Core.QueueNum) assert.Equal(suite.T(), "release", suite.ConfGorushDefault.Core.Mode) + assert.Equal(suite.T(), false, suite.ConfGorushDefault.Core.Sync) assert.Equal(suite.T(), false, suite.ConfGorushDefault.Core.SSL) assert.Equal(suite.T(), "cert.pem", suite.ConfGorushDefault.Core.CertPath) assert.Equal(suite.T(), "key.pem", suite.ConfGorushDefault.Core.KeyPath) @@ -118,6 +119,7 @@ func (suite *ConfigTestSuite) TestValidateConf() { assert.Equal(suite.T(), int64(runtime.NumCPU()), suite.ConfGorush.Core.WorkerNum) assert.Equal(suite.T(), int64(8192), suite.ConfGorush.Core.QueueNum) assert.Equal(suite.T(), "release", suite.ConfGorush.Core.Mode) + assert.Equal(suite.T(), false, suite.ConfGorush.Core.Sync) assert.Equal(suite.T(), false, suite.ConfGorush.Core.SSL) assert.Equal(suite.T(), "cert.pem", suite.ConfGorush.Core.CertPath) assert.Equal(suite.T(), "key.pem", suite.ConfGorush.Core.KeyPath) diff --git a/gorush/notification.go b/gorush/notification.go index 37bfe35..471968f 100644 --- a/gorush/notification.go +++ b/gorush/notification.go @@ -7,6 +7,7 @@ import ( "net/url" "os" "path/filepath" + "sync" "time" "github.com/google/go-gcm" @@ -63,6 +64,7 @@ type PushNotification struct { Sound string `json:"sound,omitempty"` Data D `json:"data,omitempty"` Retry int `json:"retry,omitempty"` + wg *sync.WaitGroup // Android APIKey string `json:"api_key,omitempty"` @@ -85,6 +87,13 @@ type PushNotification struct { MutableContent bool `json:"mutable-content,omitempty"` } +// Done decrements the WaitGroup counter. +func (p *PushNotification) Done() { + if p.wg != nil { + p.wg.Done() + } +} + // CheckMessage for check request message func CheckMessage(req PushNotification) error { var msg string @@ -214,6 +223,7 @@ func startWorker() { // queueNotification add notification to queue list. func queueNotification(req RequestPush) int { var count int + wg := sync.WaitGroup{} for _, notification := range req.Notifications { switch notification.Platform { case PlatFormIos: @@ -225,11 +235,16 @@ func queueNotification(req RequestPush) int { continue } } + wg.Add(1) + notification.wg = &wg QueueNotification <- notification - count += len(notification.Tokens) } + if PushConf.Core.Sync { + wg.Wait() + } + StatStorage.AddTotalCount(int64(count)) return count @@ -351,7 +366,7 @@ func GetIOSNotification(req PushNotification) *apns.Notification { // PushToIOS provide send notification to APNs server. func PushToIOS(req PushNotification) bool { LogAccess.Debug("Start push notification for iOS") - + defer req.Done() var retryCount = 0 var maxRetry = PushConf.Ios.MaxRetry @@ -456,7 +471,7 @@ func GetAndroidNotification(req PushNotification) gcm.HttpMessage { // PushToAndroid provide send notification to Android server. func PushToAndroid(req PushNotification) bool { LogAccess.Debug("Start push notification for Android") - + defer req.Done() var APIKey string var retryCount = 0 var maxRetry = PushConf.Android.MaxRetry @@ -486,7 +501,6 @@ Retry: if err != nil { // GCM server error LogError.Error("GCM server error: " + err.Error()) - return false } diff --git a/gorush/notification_test.go b/gorush/notification_test.go index 1490cb5..0ea310a 100644 --- a/gorush/notification_test.go +++ b/gorush/notification_test.go @@ -604,6 +604,42 @@ func TestDisabledAndroidNotifications(t *testing.T) { assert.Equal(t, 1, count) } +func TestSyncModeForNotifications(t *testing.T) { + PushConf = config.BuildDefaultPushConf() + + PushConf.Ios.Enabled = true + PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem" + InitAPNSClient() + + PushConf.Android.Enabled = true + PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY") + + // enable sync mode + PushConf.Core.Sync = true + + androidToken := os.Getenv("ANDROID_TEST_TOKEN") + + req := RequestPush{ + Notifications: []PushNotification{ + //ios + { + Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"}, + Platform: PlatFormIos, + Message: "Welcome", + }, + // android + { + Tokens: []string{androidToken, "bbbbb"}, + Platform: PlatFormAndroid, + Message: "Welcome", + }, + }, + } + + count := queueNotification(req) + assert.Equal(t, 3, count) +} + func TestDisabledIosNotifications(t *testing.T) { PushConf = config.BuildDefaultPushConf() diff --git a/gorush/server.go b/gorush/server.go index 49a94b5..c8fc545 100644 --- a/gorush/server.go +++ b/gorush/server.go @@ -56,11 +56,11 @@ func pushHandler(c *gin.Context) { return } - // queue notification. - go queueNotification(form) + counts := queueNotification(form) c.JSON(http.StatusOK, gin.H{ "success": "ok", + "counts": counts, }) }