From 8df5c63860418f1646dbf11ca24468f78d3ab957 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 2 May 2016 17:03:08 +0800 Subject: [PATCH] integrate memory engine. Signed-off-by: Bo-Yi Wu --- gorush/global.go | 4 +- gorush/notification.go | 12 +- gorush/notification_test.go | 1 + gorush/status.go | 231 ++------------------------------- gorush/status_test.go | 235 +++++++++++++++++++--------------- gorush/storage.go | 20 +-- storage/memory/memory.go | 46 +++++-- storage/memory/memory_test.go | 23 ++-- 8 files changed, 203 insertions(+), 369 deletions(-) diff --git a/gorush/global.go b/gorush/global.go index 9beab50..04b6a28 100644 --- a/gorush/global.go +++ b/gorush/global.go @@ -20,8 +20,8 @@ var ( LogAccess *logrus.Logger // LogError is log server error log LogError *logrus.Logger - // RushStatus is notification status - RushStatus StatusApp // RedisClient is global variable for redis RedisClient *redis.Client + // StatStorage implements the storage interface + StatStorage Storage ) diff --git a/gorush/notification.go b/gorush/notification.go index 5a7ffec..ee68dc7 100644 --- a/gorush/notification.go +++ b/gorush/notification.go @@ -199,7 +199,7 @@ func queueNotification(req RequestPush) int { count += len(notification.Tokens) } - addTotalCount(int64(count)) + StatStorage.AddTotalCount(int64(count)) return count } @@ -315,7 +315,7 @@ func PushToIOS(req PushNotification) bool { // apns server error LogPush(FailedPush, token, req, err) isError = true - addIosError(1) + StatStorage.AddIosError(1) continue } @@ -323,13 +323,13 @@ func PushToIOS(req PushNotification) bool { // error message: // ref: https://github.com/sideshow/apns2/blob/master/response.go#L14-L65 LogPush(FailedPush, token, req, errors.New(res.Reason)) - addIosError(1) + StatStorage.AddIosError(1) continue } if res.Sent() { LogPush(SucceededPush, token, req, nil) - addIosSuccess(1) + StatStorage.AddIosSuccess(1) } } @@ -410,8 +410,8 @@ func PushToAndroid(req PushNotification) bool { } LogAccess.Debug(fmt.Sprintf("Android Success count: %d, Failure count: %d", res.Success, res.Failure)) - addAndroidSuccess(int64(res.Success)) - addAndroidError(int64(res.Failure)) + StatStorage.AddAndroidSuccess(int64(res.Success)) + StatStorage.AddAndroidError(int64(res.Failure)) for k, result := range res.Results { if result.Error != "" { diff --git a/gorush/notification_test.go b/gorush/notification_test.go index bf86965..a32ca42 100644 --- a/gorush/notification_test.go +++ b/gorush/notification_test.go @@ -222,6 +222,7 @@ func TestPushToIOS(t *testing.T) { PushConf.Ios.Enabled = true PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem" InitAPNSClient() + InitAppStatus() req := PushNotification{ Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"}, diff --git a/gorush/status.go b/gorush/status.go index b221e82..5c0f2ef 100644 --- a/gorush/status.go +++ b/gorush/status.go @@ -1,12 +1,9 @@ package gorush import ( - "github.com/asdine/storm" + "github.com/appleboy/gorush/gorush/storage/memory" "github.com/gin-gonic/gin" - "gopkg.in/redis.v3" "net/http" - "strconv" - "sync/atomic" ) // StatusApp is app status structure @@ -30,222 +27,18 @@ type IosStatus struct { PushError int64 `json:"push_error"` } -func initApp() { - RushStatus.TotalCount = 0 - RushStatus.Ios.PushSuccess = 0 - RushStatus.Ios.PushError = 0 - RushStatus.Android.PushSuccess = 0 - RushStatus.Android.PushError = 0 -} - -func initRedis() error { - RedisClient = redis.NewClient(&redis.Options{ - Addr: PushConf.Stat.Redis.Addr, - Password: PushConf.Stat.Redis.Password, - DB: PushConf.Stat.Redis.DB, - }) - - _, err := RedisClient.Ping().Result() - - if err != nil { - // redis server error - LogError.Error("Can't connect redis server: " + err.Error()) - - return err - } - - RushStatus.TotalCount = getTotalCount() - RushStatus.Ios.PushSuccess = getIosSuccess() - RushStatus.Ios.PushError = getIosError() - RushStatus.Android.PushSuccess = getAndroidSuccess() - RushStatus.Android.PushError = getAndroidError() - - return nil -} - -func initBoltDB() { - RushStatus.TotalCount = getTotalCount() - RushStatus.Ios.PushSuccess = getIosSuccess() - RushStatus.Ios.PushError = getIosError() - RushStatus.Android.PushSuccess = getAndroidSuccess() - RushStatus.Android.PushError = getAndroidError() -} - // InitAppStatus for initialize app status func InitAppStatus() { switch PushConf.Stat.Engine { case "memory": - initApp() - case "redis": - initRedis() - case "boltdb": - initBoltDB() + StatStorage = memory.New() + // case "redis": + // initRedis() + // case "boltdb": + // initBoltDB() default: - initApp() + StatStorage = memory.New() } - -} - -func getRedisInt64Result(key string, count *int64) { - val, _ := RedisClient.Get(key).Result() - *count, _ = strconv.ParseInt(val, 10, 64) -} - -func boltdbSet(key string, count int64) { - db, _ := storm.Open(PushConf.Stat.BoltDB.Path) - db.Set(PushConf.Stat.BoltDB.Bucket, key, count) - defer db.Close() -} - -func boltdbGet(key string, count *int64) { - db, _ := storm.Open(PushConf.Stat.BoltDB.Path) - db.Get(PushConf.Stat.BoltDB.Bucket, key, count) - defer db.Close() -} - -func addTotalCount(count int64) { - switch PushConf.Stat.Engine { - case "memory": - atomic.AddInt64(&RushStatus.TotalCount, count) - case "redis": - RedisClient.Set(TotalCountKey, strconv.Itoa(int(count)), 0) - case "boltdb": - boltdbSet(TotalCountKey, count) - default: - atomic.AddInt64(&RushStatus.TotalCount, count) - } -} - -func addIosSuccess(count int64) { - switch PushConf.Stat.Engine { - case "memory": - atomic.AddInt64(&RushStatus.Ios.PushSuccess, count) - case "redis": - RedisClient.Set(IosSuccessKey, strconv.Itoa(int(count)), 0) - case "boltdb": - boltdbSet(IosSuccessKey, count) - default: - atomic.AddInt64(&RushStatus.Ios.PushSuccess, count) - } -} - -func addIosError(count int64) { - switch PushConf.Stat.Engine { - case "memory": - atomic.AddInt64(&RushStatus.Ios.PushError, count) - case "redis": - RedisClient.Set(IosErrorKey, strconv.Itoa(int(count)), 0) - case "boltdb": - boltdbSet(IosErrorKey, count) - default: - atomic.AddInt64(&RushStatus.Ios.PushError, count) - } -} - -func addAndroidSuccess(count int64) { - switch PushConf.Stat.Engine { - case "memory": - atomic.AddInt64(&RushStatus.Android.PushSuccess, count) - case "redis": - RedisClient.Set(AndroidSuccessKey, strconv.Itoa(int(count)), 0) - case "boltdb": - boltdbSet(AndroidSuccessKey, count) - default: - atomic.AddInt64(&RushStatus.Android.PushSuccess, count) - } -} - -func addAndroidError(count int64) { - switch PushConf.Stat.Engine { - case "memory": - atomic.AddInt64(&RushStatus.Android.PushError, count) - case "redis": - RedisClient.Set(AndroidErrorKey, strconv.Itoa(int(count)), 0) - case "boltdb": - boltdbSet(AndroidErrorKey, count) - default: - atomic.AddInt64(&RushStatus.Android.PushError, count) - } -} - -func getTotalCount() int64 { - var count int64 - switch PushConf.Stat.Engine { - case "memory": - count = atomic.LoadInt64(&RushStatus.TotalCount) - case "redis": - getRedisInt64Result(TotalCountKey, &count) - case "boltdb": - boltdbGet(TotalCountKey, &count) - default: - count = atomic.LoadInt64(&RushStatus.TotalCount) - } - - return count -} - -func getIosSuccess() int64 { - var count int64 - switch PushConf.Stat.Engine { - case "memory": - count = atomic.LoadInt64(&RushStatus.Ios.PushSuccess) - case "redis": - getRedisInt64Result(IosSuccessKey, &count) - case "boltdb": - boltdbGet(IosSuccessKey, &count) - default: - count = atomic.LoadInt64(&RushStatus.Ios.PushSuccess) - } - - return count -} - -func getIosError() int64 { - var count int64 - switch PushConf.Stat.Engine { - case "memory": - count = atomic.LoadInt64(&RushStatus.Ios.PushError) - case "redis": - getRedisInt64Result(IosErrorKey, &count) - case "boltdb": - boltdbGet(IosErrorKey, &count) - default: - count = atomic.LoadInt64(&RushStatus.Ios.PushError) - } - - return count -} - -func getAndroidSuccess() int64 { - var count int64 - switch PushConf.Stat.Engine { - case "memory": - count = atomic.LoadInt64(&RushStatus.Android.PushSuccess) - case "redis": - getRedisInt64Result(AndroidSuccessKey, &count) - case "boltdb": - boltdbGet(AndroidSuccessKey, &count) - default: - count = atomic.LoadInt64(&RushStatus.Android.PushSuccess) - } - - return count -} - -func getAndroidError() int64 { - var count int64 - switch PushConf.Stat.Engine { - case "memory": - count = atomic.LoadInt64(&RushStatus.Android.PushError) - case "redis": - getRedisInt64Result(AndroidErrorKey, &count) - case "boltdb": - boltdbGet(AndroidErrorKey, &count) - default: - count = atomic.LoadInt64(&RushStatus.Android.PushError) - } - - return count } func appStatusHandler(c *gin.Context) { @@ -253,11 +46,11 @@ func appStatusHandler(c *gin.Context) { result.QueueMax = cap(QueueNotification) result.QueueUsage = len(QueueNotification) - result.TotalCount = getTotalCount() - result.Ios.PushSuccess = getIosSuccess() - result.Ios.PushError = getIosError() - result.Android.PushSuccess = getAndroidSuccess() - result.Android.PushError = getAndroidError() + result.TotalCount = StatStorage.GetTotalCount() + result.Ios.PushSuccess = StatStorage.GetIosSuccess() + result.Ios.PushError = StatStorage.GetIosError() + result.Android.PushSuccess = StatStorage.GetAndroidSuccess() + result.Android.PushError = StatStorage.GetAndroidError() c.JSON(http.StatusOK, result) } diff --git a/gorush/status_test.go b/gorush/status_test.go index 044d4a1..f76c595 100644 --- a/gorush/status_test.go +++ b/gorush/status_test.go @@ -2,137 +2,160 @@ package gorush import ( "github.com/stretchr/testify/assert" - "sync/atomic" + // "sync/atomic" "testing" ) -func TestAddTotalCount(t *testing.T) { - InitAppStatus() - addTotalCount(1000) +// func TestAddTotalCount(t *testing.T) { +// InitAppStatus() +// addTotalCount(1000) - val := atomic.LoadInt64(&RushStatus.TotalCount) +// val := atomic.LoadInt64(&RushStatus.TotalCount) - assert.Equal(t, int64(1000), val) -} +// assert.Equal(t, int64(1000), val) +// } -func TestAddIosSuccess(t *testing.T) { - InitAppStatus() - addIosSuccess(1000) +// func TestAddIosSuccess(t *testing.T) { +// InitAppStatus() +// addIosSuccess(1000) - val := atomic.LoadInt64(&RushStatus.Ios.PushSuccess) +// val := atomic.LoadInt64(&RushStatus.Ios.PushSuccess) - assert.Equal(t, int64(1000), val) -} +// assert.Equal(t, int64(1000), val) +// } -func TestAddIosError(t *testing.T) { - InitAppStatus() - addIosError(1000) +// func TestAddIosError(t *testing.T) { +// InitAppStatus() +// addIosError(1000) - val := atomic.LoadInt64(&RushStatus.Ios.PushError) +// val := atomic.LoadInt64(&RushStatus.Ios.PushError) - assert.Equal(t, int64(1000), val) -} +// assert.Equal(t, int64(1000), val) +// } -func TestAndroidSuccess(t *testing.T) { - InitAppStatus() - addAndroidSuccess(1000) +// func TestAndroidSuccess(t *testing.T) { +// InitAppStatus() +// addAndroidSuccess(1000) - val := atomic.LoadInt64(&RushStatus.Android.PushSuccess) +// val := atomic.LoadInt64(&RushStatus.Android.PushSuccess) - assert.Equal(t, int64(1000), val) -} +// assert.Equal(t, int64(1000), val) +// } -func TestAddAndroidError(t *testing.T) { - InitAppStatus() - addAndroidError(1000) +// func TestAddAndroidError(t *testing.T) { +// InitAppStatus() +// addAndroidError(1000) - val := atomic.LoadInt64(&RushStatus.Android.PushError) +// val := atomic.LoadInt64(&RushStatus.Android.PushError) - assert.Equal(t, int64(1000), val) -} +// assert.Equal(t, int64(1000), val) +// } -func TestRedisServerSuccess(t *testing.T) { - PushConf.Stat.Redis.Addr = "localhost:6379" - - err := initRedis() - - assert.NoError(t, err) -} - -func TestRedisServerError(t *testing.T) { - PushConf.Stat.Redis.Addr = "localhost:6370" - - err := initRedis() - - assert.Error(t, err) -} - -func TestStatForRedisEngine(t *testing.T) { +func TestStatForMemoryEngine(t *testing.T) { var val int64 - PushConf.Stat.Engine = "redis" - PushConf.Stat.Redis.Addr = "localhost:6379" + PushConf.Stat.Engine = "memory" InitAppStatus() - addTotalCount(10) - addIosSuccess(20) - addIosError(30) - addAndroidSuccess(40) - addAndroidError(50) + StatStorage.AddTotalCount(100) + StatStorage.AddIosSuccess(200) + StatStorage.AddIosError(300) + StatStorage.AddAndroidSuccess(400) + StatStorage.AddAndroidError(500) - val = getTotalCount() - assert.Equal(t, int64(10), val) - val = getIosSuccess() - assert.Equal(t, int64(20), val) - val = getIosError() - assert.Equal(t, int64(30), val) - val = getAndroidSuccess() - assert.Equal(t, int64(40), val) - val = getAndroidError() - assert.Equal(t, int64(50), val) -} - -func TestDefaultEngine(t *testing.T) { - var val int64 - PushConf.Stat.Engine = "test" - InitAppStatus() - - addTotalCount(1) - addIosSuccess(2) - addIosError(3) - addAndroidSuccess(4) - addAndroidError(5) - - val = getTotalCount() - assert.Equal(t, int64(1), val) - val = getIosSuccess() - assert.Equal(t, int64(2), val) - val = getIosError() - assert.Equal(t, int64(3), val) - val = getAndroidSuccess() - assert.Equal(t, int64(4), val) - val = getAndroidError() - assert.Equal(t, int64(5), val) -} - -func TestStatForBoltDBEngine(t *testing.T) { - var val int64 - PushConf.Stat.Engine = "boltdb" - InitAppStatus() - - addTotalCount(100) - addIosSuccess(200) - addIosError(300) - addAndroidSuccess(400) - addAndroidError(500) - - val = getTotalCount() + val = StatStorage.GetTotalCount() assert.Equal(t, int64(100), val) - val = getIosSuccess() + val = StatStorage.GetIosSuccess() assert.Equal(t, int64(200), val) - val = getIosError() + val = StatStorage.GetIosError() assert.Equal(t, int64(300), val) - val = getAndroidSuccess() + val = StatStorage.GetAndroidSuccess() assert.Equal(t, int64(400), val) - val = getAndroidError() + val = StatStorage.GetAndroidError() assert.Equal(t, int64(500), val) } + +// func TestRedisServerSuccess(t *testing.T) { +// PushConf.Stat.Redis.Addr = "localhost:6379" + +// err := initRedis() + +// assert.NoError(t, err) +// } + +// func TestRedisServerError(t *testing.T) { +// PushConf.Stat.Redis.Addr = "localhost:6370" + +// err := initRedis() + +// assert.Error(t, err) +// } + +// func TestStatForRedisEngine(t *testing.T) { +// var val int64 +// PushConf.Stat.Engine = "redis" +// PushConf.Stat.Redis.Addr = "localhost:6379" +// InitAppStatus() + +// addTotalCount(10) +// addIosSuccess(20) +// addIosError(30) +// addAndroidSuccess(40) +// addAndroidError(50) + +// val = getTotalCount() +// assert.Equal(t, int64(10), val) +// val = getIosSuccess() +// assert.Equal(t, int64(20), val) +// val = getIosError() +// assert.Equal(t, int64(30), val) +// val = getAndroidSuccess() +// assert.Equal(t, int64(40), val) +// val = getAndroidError() +// assert.Equal(t, int64(50), val) +// } + +// func TestDefaultEngine(t *testing.T) { +// var val int64 +// PushConf.Stat.Engine = "test" +// InitAppStatus() + +// addTotalCount(1) +// addIosSuccess(2) +// addIosError(3) +// addAndroidSuccess(4) +// addAndroidError(5) + +// val = getTotalCount() +// assert.Equal(t, int64(1), val) +// val = getIosSuccess() +// assert.Equal(t, int64(2), val) +// val = getIosError() +// assert.Equal(t, int64(3), val) +// val = getAndroidSuccess() +// assert.Equal(t, int64(4), val) +// val = getAndroidError() +// assert.Equal(t, int64(5), val) +// } + +// func TestStatForBoltDBEngine(t *testing.T) { +// var val int64 +// PushConf.Stat.Engine = "boltdb" +// InitAppStatus() + +// addTotalCount(100) +// addIosSuccess(200) +// addIosError(300) +// addAndroidSuccess(400) +// addAndroidError(500) + +// val = getTotalCount() +// assert.Equal(t, int64(100), val) +// val = getIosSuccess() +// assert.Equal(t, int64(200), val) +// val = getIosError() +// assert.Equal(t, int64(300), val) +// val = getAndroidSuccess() +// assert.Equal(t, int64(400), val) +// val = getAndroidError() +// assert.Equal(t, int64(500), val) +// } diff --git a/gorush/storage.go b/gorush/storage.go index a17e64c..02f23ba 100644 --- a/gorush/storage.go +++ b/gorush/storage.go @@ -2,14 +2,14 @@ package gorush // Storage interface type Storage interface { - addTotalCount(int64) - addIosSuccess(int64) - addIosError(int64) - addAndroidSuccess(int64) - addAndroidError(int64) - getTotalCount() int64 - getIosSuccess() int64 - getIosError() int64 - getAndroidSuccess() int64 - getAndroidError() int64 + AddTotalCount(int64) + AddIosSuccess(int64) + AddIosError(int64) + AddAndroidSuccess(int64) + AddAndroidError(int64) + GetTotalCount() int64 + GetIosSuccess() int64 + GetIosError() int64 + GetAndroidSuccess() int64 + GetAndroidError() int64 } diff --git a/storage/memory/memory.go b/storage/memory/memory.go index d9cdec0..5c3ebcc 100644 --- a/storage/memory/memory.go +++ b/storage/memory/memory.go @@ -1,66 +1,84 @@ package memory import ( - "github.com/appleboy/gorush/gorush" "sync/atomic" ) +// StatusApp is app status structure +type statApp struct { + TotalCount int64 `json:"total_count"` + Ios IosStatus `json:"ios"` + Android AndroidStatus `json:"android"` +} + +// AndroidStatus is android structure +type AndroidStatus struct { + PushSuccess int64 `json:"push_success"` + PushError int64 `json:"push_error"` +} + +// IosStatus is iOS structure +type IosStatus struct { + PushSuccess int64 `json:"push_success"` + PushError int64 `json:"push_error"` +} + // Storage implements the storage interface for gorush (https://github.com/appleboy/gorush) -func New(stat gorush.StatusApp) *Storage { +func New() *Storage { return &Storage{ - stat: stat, + stat: &statApp{}, } } type Storage struct { - stat gorush.StatusApp + stat *statApp } -func (s *Storage) addTotalCount(count int64) { +func (s *Storage) AddTotalCount(count int64) { atomic.AddInt64(&s.stat.TotalCount, count) } -func (s *Storage) addIosSuccess(count int64) { +func (s *Storage) AddIosSuccess(count int64) { atomic.AddInt64(&s.stat.Ios.PushSuccess, count) } -func (s *Storage) addIosError(count int64) { +func (s *Storage) AddIosError(count int64) { atomic.AddInt64(&s.stat.Ios.PushError, count) } -func (s *Storage) addAndroidSuccess(count int64) { +func (s *Storage) AddAndroidSuccess(count int64) { atomic.AddInt64(&s.stat.Android.PushSuccess, count) } -func (s *Storage) addAndroidError(count int64) { +func (s *Storage) AddAndroidError(count int64) { atomic.AddInt64(&s.stat.Android.PushError, count) } -func (s *Storage) getTotalCount() int64 { +func (s *Storage) GetTotalCount() int64 { count := atomic.LoadInt64(&s.stat.TotalCount) return count } -func (s *Storage) getIosSuccess() int64 { +func (s *Storage) GetIosSuccess() int64 { count := atomic.LoadInt64(&s.stat.Ios.PushSuccess) return count } -func (s *Storage) getIosError() int64 { +func (s *Storage) GetIosError() int64 { count := atomic.LoadInt64(&s.stat.Ios.PushError) return count } -func (s *Storage) getAndroidSuccess() int64 { +func (s *Storage) GetAndroidSuccess() int64 { count := atomic.LoadInt64(&s.stat.Android.PushSuccess) return count } -func (s *Storage) getAndroidError() int64 { +func (s *Storage) GetAndroidError() int64 { count := atomic.LoadInt64(&s.stat.Android.PushError) return count diff --git a/storage/memory/memory_test.go b/storage/memory/memory_test.go index 54d670c..491dfd7 100644 --- a/storage/memory/memory_test.go +++ b/storage/memory/memory_test.go @@ -1,7 +1,6 @@ package memory import ( - "github.com/appleboy/gorush/gorush" "github.com/stretchr/testify/assert" "testing" ) @@ -9,25 +8,25 @@ import ( func TestMemoryEngine(t *testing.T) { var val int64 - memory := New(gorush.StatusApp{}) + memory := New() - memory.addTotalCount(1) - val = memory.getTotalCount() + memory.AddTotalCount(1) + val = memory.GetTotalCount() assert.Equal(t, int64(1), val) - memory.addIosSuccess(2) - val = memory.getIosSuccess() + memory.AddIosSuccess(2) + val = memory.GetIosSuccess() assert.Equal(t, int64(2), val) - memory.addIosError(3) - val = memory.getIosError() + memory.AddIosError(3) + val = memory.GetIosError() assert.Equal(t, int64(3), val) - memory.addAndroidSuccess(4) - val = memory.getAndroidSuccess() + memory.AddAndroidSuccess(4) + val = memory.GetAndroidSuccess() assert.Equal(t, int64(4), val) - memory.addAndroidError(5) - val = memory.getAndroidError() + memory.AddAndroidError(5) + val = memory.GetAndroidError() assert.Equal(t, int64(5), val) }