Merge pull request #62 from appleboy/redis
Fixed #61 Support redis engine
This commit is contained in:
commit
f14d42d9a8
|
@ -3,14 +3,15 @@ sudo: required
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
- 1.5
|
||||||
|
- 1.6
|
||||||
|
- 1.6.1
|
||||||
- 1.6.2
|
- 1.6.2
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
- redis
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
|
|
@ -21,6 +21,7 @@ A push notification server using [Gin](https://github.com/gin-gonic/gin) framewo
|
||||||
* Support notification queue and multiple workers.
|
* Support notification queue and multiple workers.
|
||||||
* Support `/api/stat/app` show notification success and failure counts.
|
* Support `/api/stat/app` show notification success and failure counts.
|
||||||
* Support `/api/config` show your yml config.
|
* Support `/api/config` show your yml config.
|
||||||
|
* Support store app stat to [redis](http://redis.io/) or memory.
|
||||||
|
|
||||||
See the [YAML config example](config/config.yml):
|
See the [YAML config example](config/config.yml):
|
||||||
|
|
||||||
|
@ -57,6 +58,13 @@ log:
|
||||||
access_level: "debug"
|
access_level: "debug"
|
||||||
error_log: "stderr" # stderr: output to console, or define log path like "log/error_log"
|
error_log: "stderr" # stderr: output to console, or define log path like "log/error_log"
|
||||||
error_level: "error"
|
error_level: "error"
|
||||||
|
|
||||||
|
stat:
|
||||||
|
engine: "memory" # support memory or redis
|
||||||
|
redis:
|
||||||
|
addr: "localhost:6379"
|
||||||
|
password: ""
|
||||||
|
db: 0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
|
@ -30,3 +30,10 @@ log:
|
||||||
access_level: "debug"
|
access_level: "debug"
|
||||||
error_log: "stderr"
|
error_log: "stderr"
|
||||||
error_level: "error"
|
error_level: "error"
|
||||||
|
|
||||||
|
stat:
|
||||||
|
engine: "memory"
|
||||||
|
redis:
|
||||||
|
addr: "localhost:6379"
|
||||||
|
password: ""
|
||||||
|
db: 0
|
||||||
|
|
|
@ -7,6 +7,6 @@ RUN mkdir -p /tmp/build
|
||||||
Add build.tar.gz /tmp/build/
|
Add build.tar.gz /tmp/build/
|
||||||
WORKDIR /tmp/build
|
WORKDIR /tmp/build
|
||||||
RUN go get -v -d
|
RUN go get -v -d
|
||||||
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w" -o bin/gorush gorush.go
|
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/gorush gorush.go
|
||||||
|
|
||||||
CMD tar -C bin -czf - gorush
|
CMD tar -C bin -czf - gorush
|
||||||
|
|
|
@ -13,6 +13,7 @@ type ConfYaml struct {
|
||||||
Android SectionAndroid `yaml:"android"`
|
Android SectionAndroid `yaml:"android"`
|
||||||
Ios SectionIos `yaml:"ios"`
|
Ios SectionIos `yaml:"ios"`
|
||||||
Log SectionLog `yaml:"log"`
|
Log SectionLog `yaml:"log"`
|
||||||
|
Stat SectionStat `yaml:stat`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SectionCore is sub seciont of config.
|
// SectionCore is sub seciont of config.
|
||||||
|
@ -58,6 +59,19 @@ type SectionLog struct {
|
||||||
ErrorLevel string `yaml:"error_level"`
|
ErrorLevel string `yaml:"error_level"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SectionStat is sub seciont of config.
|
||||||
|
type SectionStat struct {
|
||||||
|
Engine string `yaml:"service"`
|
||||||
|
Redis SectionRedis `yaml:"redis"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SectionRedis is sub seciont of config.
|
||||||
|
type SectionRedis struct {
|
||||||
|
Addr string `yaml:"addr"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
DB int64 `yaml:"db"`
|
||||||
|
}
|
||||||
|
|
||||||
// BuildDefaultPushConf is default config setting.
|
// BuildDefaultPushConf is default config setting.
|
||||||
func BuildDefaultPushConf() ConfYaml {
|
func BuildDefaultPushConf() ConfYaml {
|
||||||
var conf ConfYaml
|
var conf ConfYaml
|
||||||
|
@ -95,6 +109,11 @@ func BuildDefaultPushConf() ConfYaml {
|
||||||
conf.Log.ErrorLog = "stderr"
|
conf.Log.ErrorLog = "stderr"
|
||||||
conf.Log.ErrorLevel = "error"
|
conf.Log.ErrorLevel = "error"
|
||||||
|
|
||||||
|
conf.Stat.Engine = "memory"
|
||||||
|
conf.Stat.Redis.Addr = "localhost:6379"
|
||||||
|
conf.Stat.Redis.Password = ""
|
||||||
|
conf.Stat.Redis.DB = 0
|
||||||
|
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,3 +18,12 @@ const (
|
||||||
// FailedPush is log block
|
// FailedPush is log block
|
||||||
FailedPush = "failed-push"
|
FailedPush = "failed-push"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Stat variable for redis
|
||||||
|
const (
|
||||||
|
gorushTotalCount = "gorush-total-count"
|
||||||
|
gorushIosSuccess = "gorush-ios-success-count"
|
||||||
|
gorushIosError = "gorush-ios-error-count"
|
||||||
|
gorushAndroidSuccess = "gorush-android-success-count"
|
||||||
|
gorushAndroidError = "gorush-android-error-count"
|
||||||
|
)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
apns "github.com/sideshow/apns2"
|
apns "github.com/sideshow/apns2"
|
||||||
|
"gopkg.in/redis.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -21,4 +22,6 @@ var (
|
||||||
LogError *logrus.Logger
|
LogError *logrus.Logger
|
||||||
// RushStatus is notification status
|
// RushStatus is notification status
|
||||||
RushStatus StatusApp
|
RushStatus StatusApp
|
||||||
|
// RedisClient is global variable for redis
|
||||||
|
RedisClient *redis.Client
|
||||||
)
|
)
|
||||||
|
|
166
gorush/status.go
166
gorush/status.go
|
@ -2,7 +2,9 @@ package gorush
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gopkg.in/redis.v3"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,8 +29,14 @@ type IosStatus struct {
|
||||||
PushError int64 `json:"push_error"`
|
PushError int64 `json:"push_error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitAppStatus for initialize app status
|
func getRedisInt64Result(key string) int64 {
|
||||||
func InitAppStatus() {
|
val, _ := RedisClient.Get(key).Result()
|
||||||
|
count, _ := strconv.ParseInt(val, 10, 64)
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func initApp() {
|
||||||
RushStatus.TotalCount = 0
|
RushStatus.TotalCount = 0
|
||||||
RushStatus.Ios.PushSuccess = 0
|
RushStatus.Ios.PushSuccess = 0
|
||||||
RushStatus.Ios.PushError = 0
|
RushStatus.Ios.PushError = 0
|
||||||
|
@ -36,24 +44,168 @@ func InitAppStatus() {
|
||||||
RushStatus.Android.PushError = 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitAppStatus for initialize app status
|
||||||
|
func InitAppStatus() {
|
||||||
|
switch PushConf.Stat.Engine {
|
||||||
|
case "memory":
|
||||||
|
initApp()
|
||||||
|
case "redis":
|
||||||
|
initRedis()
|
||||||
|
default:
|
||||||
|
initApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func addTotalCount(count int64) {
|
func addTotalCount(count int64) {
|
||||||
|
switch PushConf.Stat.Engine {
|
||||||
|
case "memory":
|
||||||
atomic.AddInt64(&RushStatus.TotalCount, count)
|
atomic.AddInt64(&RushStatus.TotalCount, count)
|
||||||
|
case "redis":
|
||||||
|
RedisClient.Set(gorushTotalCount, strconv.Itoa(int(count)), 0)
|
||||||
|
default:
|
||||||
|
atomic.AddInt64(&RushStatus.TotalCount, count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addIosSuccess(count int64) {
|
func addIosSuccess(count int64) {
|
||||||
|
switch PushConf.Stat.Engine {
|
||||||
|
case "memory":
|
||||||
atomic.AddInt64(&RushStatus.Ios.PushSuccess, count)
|
atomic.AddInt64(&RushStatus.Ios.PushSuccess, count)
|
||||||
|
case "redis":
|
||||||
|
RedisClient.Set(gorushIosSuccess, strconv.Itoa(int(count)), 0)
|
||||||
|
default:
|
||||||
|
atomic.AddInt64(&RushStatus.Ios.PushSuccess, count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addIosError(count int64) {
|
func addIosError(count int64) {
|
||||||
|
switch PushConf.Stat.Engine {
|
||||||
|
case "memory":
|
||||||
atomic.AddInt64(&RushStatus.Ios.PushError, count)
|
atomic.AddInt64(&RushStatus.Ios.PushError, count)
|
||||||
|
case "redis":
|
||||||
|
RedisClient.Set(gorushIosError, strconv.Itoa(int(count)), 0)
|
||||||
|
default:
|
||||||
|
atomic.AddInt64(&RushStatus.Ios.PushError, count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addAndroidSuccess(count int64) {
|
func addAndroidSuccess(count int64) {
|
||||||
|
switch PushConf.Stat.Engine {
|
||||||
|
case "memory":
|
||||||
atomic.AddInt64(&RushStatus.Android.PushSuccess, count)
|
atomic.AddInt64(&RushStatus.Android.PushSuccess, count)
|
||||||
|
case "redis":
|
||||||
|
|
||||||
|
RedisClient.Set(gorushAndroidSuccess, strconv.Itoa(int(count)), 0)
|
||||||
|
default:
|
||||||
|
atomic.AddInt64(&RushStatus.Android.PushSuccess, count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addAndroidError(count int64) {
|
func addAndroidError(count int64) {
|
||||||
|
switch PushConf.Stat.Engine {
|
||||||
|
case "memory":
|
||||||
atomic.AddInt64(&RushStatus.Android.PushError, count)
|
atomic.AddInt64(&RushStatus.Android.PushError, count)
|
||||||
|
case "redis":
|
||||||
|
RedisClient.Set(gorushAndroidError, strconv.Itoa(int(count)), 0)
|
||||||
|
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":
|
||||||
|
count = getRedisInt64Result(gorushAndroidError)
|
||||||
|
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":
|
||||||
|
count = getRedisInt64Result(gorushAndroidError)
|
||||||
|
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":
|
||||||
|
count = getRedisInt64Result(gorushAndroidError)
|
||||||
|
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":
|
||||||
|
count = getRedisInt64Result(gorushAndroidError)
|
||||||
|
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":
|
||||||
|
count = getRedisInt64Result(gorushAndroidError)
|
||||||
|
default:
|
||||||
|
count = atomic.LoadInt64(&RushStatus.Android.PushError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func appStatusHandler(c *gin.Context) {
|
func appStatusHandler(c *gin.Context) {
|
||||||
|
@ -61,11 +213,11 @@ func appStatusHandler(c *gin.Context) {
|
||||||
|
|
||||||
result.QueueMax = cap(QueueNotification)
|
result.QueueMax = cap(QueueNotification)
|
||||||
result.QueueUsage = len(QueueNotification)
|
result.QueueUsage = len(QueueNotification)
|
||||||
result.TotalCount = atomic.LoadInt64(&RushStatus.TotalCount)
|
result.TotalCount = getTotalCount()
|
||||||
result.Ios.PushSuccess = atomic.LoadInt64(&RushStatus.Ios.PushSuccess)
|
result.Ios.PushSuccess = getIosSuccess()
|
||||||
result.Ios.PushError = atomic.LoadInt64(&RushStatus.Ios.PushError)
|
result.Ios.PushError = getIosError()
|
||||||
result.Android.PushSuccess = atomic.LoadInt64(&RushStatus.Android.PushSuccess)
|
result.Android.PushSuccess = getAndroidSuccess()
|
||||||
result.Android.PushError = atomic.LoadInt64(&RushStatus.Android.PushError)
|
result.Android.PushError = getAndroidError()
|
||||||
|
|
||||||
c.JSON(http.StatusOK, result)
|
c.JSON(http.StatusOK, result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,3 +50,66 @@ func TestAddAndroidError(t *testing.T) {
|
||||||
|
|
||||||
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) {
|
||||||
|
var val int64
|
||||||
|
PushConf.Stat.Engine = "redis"
|
||||||
|
PushConf.Stat.Redis.Addr = "localhost:6379"
|
||||||
|
InitAppStatus()
|
||||||
|
|
||||||
|
addTotalCount(1000)
|
||||||
|
addIosSuccess(1000)
|
||||||
|
addIosError(1000)
|
||||||
|
addAndroidSuccess(1000)
|
||||||
|
addAndroidError(1000)
|
||||||
|
|
||||||
|
val = getTotalCount()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getIosSuccess()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getIosError()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getAndroidSuccess()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getAndroidError()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultEngine(t *testing.T) {
|
||||||
|
var val int64
|
||||||
|
PushConf.Stat.Engine = "test"
|
||||||
|
InitAppStatus()
|
||||||
|
|
||||||
|
addTotalCount(1000)
|
||||||
|
addIosSuccess(1000)
|
||||||
|
addIosError(1000)
|
||||||
|
addAndroidSuccess(1000)
|
||||||
|
addAndroidError(1000)
|
||||||
|
|
||||||
|
val = getTotalCount()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getIosSuccess()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getIosError()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getAndroidSuccess()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
val = getAndroidError()
|
||||||
|
assert.Equal(t, int64(1000), val)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue