chore: support single queue and multiple worker (#589)
This commit is contained in:
parent
0658f18430
commit
ab8b1991ab
|
@ -243,7 +243,7 @@ type SectionGRPC struct {
|
|||
}
|
||||
|
||||
// LoadConf load config from file and read in environment variables that match
|
||||
func LoadConf(confPath string) (ConfYaml, error) {
|
||||
func LoadConf(confPath ...string) (ConfYaml, error) {
|
||||
var conf ConfYaml
|
||||
|
||||
viper.SetConfigType("yaml")
|
||||
|
@ -251,8 +251,8 @@ func LoadConf(confPath string) (ConfYaml, error) {
|
|||
viper.SetEnvPrefix("gorush") // will be uppercased automatically
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
|
||||
if confPath != "" {
|
||||
content, err := ioutil.ReadFile(confPath)
|
||||
if len(confPath) > 0 && confPath[0] != "" {
|
||||
content, err := ioutil.ReadFile(confPath[0])
|
||||
if err != nil {
|
||||
return conf, err
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ type ConfigTestSuite struct {
|
|||
|
||||
func (suite *ConfigTestSuite) SetupTest() {
|
||||
var err error
|
||||
suite.ConfGorushDefault, err = LoadConf("")
|
||||
suite.ConfGorushDefault, err = LoadConf()
|
||||
if err != nil {
|
||||
panic("failed to load default config.yml")
|
||||
}
|
||||
|
@ -215,6 +215,6 @@ func TestLoadConfigFromEnv(t *testing.T) {
|
|||
|
||||
func TestLoadWrongDefaultYAMLConfig(t *testing.T) {
|
||||
defaultConf = []byte(`a`)
|
||||
_, err := LoadConf("")
|
||||
_, err := LoadConf()
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
package gorush
|
||||
|
||||
// Stat variable for redis
|
||||
const (
|
||||
TotalCountKey = "gorush-total-count"
|
||||
IosSuccessKey = "gorush-ios-success-count"
|
||||
IosErrorKey = "gorush-ios-error-count"
|
||||
AndroidSuccessKey = "gorush-android-success-count"
|
||||
AndroidErrorKey = "gorush-android-error-count"
|
||||
HuaweiSuccessKey = "gorush-huawei-success-count"
|
||||
HuaweiErrorKey = "gorush-huawei-error-count"
|
||||
)
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
func TestEmptyFeedbackURL(t *testing.T) {
|
||||
// PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
logEntry := logx.LogPushEntry{
|
||||
ID: "",
|
||||
Type: "",
|
||||
|
@ -23,13 +23,13 @@ func TestEmptyFeedbackURL(t *testing.T) {
|
|||
Error: "",
|
||||
}
|
||||
|
||||
err := DispatchFeedback(logEntry, PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
||||
err := DispatchFeedback(logEntry, cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestHTTPErrorInFeedbackCall(t *testing.T) {
|
||||
config, _ := config.LoadConf("")
|
||||
config.Core.FeedbackURL = "http://test.example.com/api/"
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Core.FeedbackURL = "http://test.example.com/api/"
|
||||
logEntry := logx.LogPushEntry{
|
||||
ID: "",
|
||||
Type: "",
|
||||
|
@ -39,7 +39,7 @@ func TestHTTPErrorInFeedbackCall(t *testing.T) {
|
|||
Error: "",
|
||||
}
|
||||
|
||||
err := DispatchFeedback(logEntry, config.Core.FeedbackURL, config.Core.FeedbackTimeout)
|
||||
err := DispatchFeedback(logEntry, cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ func TestSuccessfulFeedbackCall(t *testing.T) {
|
|||
)
|
||||
defer httpMock.Close()
|
||||
|
||||
config, _ := config.LoadConf("")
|
||||
config.Core.FeedbackURL = httpMock.URL
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Core.FeedbackURL = httpMock.URL
|
||||
logEntry := logx.LogPushEntry{
|
||||
ID: "",
|
||||
Type: "",
|
||||
|
@ -70,6 +70,6 @@ func TestSuccessfulFeedbackCall(t *testing.T) {
|
|||
Error: "",
|
||||
}
|
||||
|
||||
err := DispatchFeedback(logEntry, config.Core.FeedbackURL, config.Core.FeedbackTimeout)
|
||||
err := DispatchFeedback(logEntry, cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"github.com/appleboy/gorush/config"
|
||||
|
||||
"github.com/appleboy/go-fcm"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/core"
|
||||
"github.com/sideshow/apns2"
|
||||
)
|
||||
|
||||
var (
|
||||
// PushConf is gorush config
|
||||
PushConf config.ConfYaml
|
||||
// QueueNotification is chan type
|
||||
QueueNotification chan PushNotification
|
||||
// ApnsClient is apns client
|
||||
ApnsClient *apns2.Client
|
||||
// FCMClient is apns client
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
|
@ -12,33 +10,19 @@ import (
|
|||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
if err := logx.InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := status.InitAppStatus(PushConf); err != nil {
|
||||
if err := status.InitAppStatus(cfg); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(int(PushConf.Core.WorkerNum))
|
||||
InitWorkers(ctx, wg, PushConf.Core.WorkerNum, PushConf.Core.QueueNum)
|
||||
|
||||
if err := status.InitAppStatus(PushConf); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
close(QueueNotification)
|
||||
cancel()
|
||||
}()
|
||||
|
||||
m.Run()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/appleboy/go-fcm"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||
|
@ -54,8 +55,8 @@ type RequestPush struct {
|
|||
|
||||
// PushNotification is single notification request
|
||||
type PushNotification struct {
|
||||
wg *sync.WaitGroup
|
||||
log *[]logx.LogPushEntry
|
||||
Wg *sync.WaitGroup
|
||||
Log *[]logx.LogPushEntry
|
||||
|
||||
// Common
|
||||
ID string `json:"notif_id,omitempty"`
|
||||
|
@ -112,22 +113,22 @@ type PushNotification struct {
|
|||
|
||||
// WaitDone decrements the WaitGroup counter.
|
||||
func (p *PushNotification) WaitDone() {
|
||||
if p.wg != nil {
|
||||
p.wg.Done()
|
||||
if p.Wg != nil {
|
||||
p.Wg.Done()
|
||||
}
|
||||
}
|
||||
|
||||
// AddWaitCount increments the WaitGroup counter.
|
||||
func (p *PushNotification) AddWaitCount() {
|
||||
if p.wg != nil {
|
||||
p.wg.Add(1)
|
||||
if p.Wg != nil {
|
||||
p.Wg.Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
// AddLog record fail log of notification
|
||||
func (p *PushNotification) AddLog(log logx.LogPushEntry) {
|
||||
if p.log != nil {
|
||||
*p.log = append(*p.log, log)
|
||||
if p.Log != nil {
|
||||
*p.Log = append(*p.Log, log)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,39 +200,55 @@ func SetProxy(proxy string) error {
|
|||
}
|
||||
|
||||
// CheckPushConf provide check your yml config.
|
||||
func CheckPushConf() error {
|
||||
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled && !PushConf.Huawei.Enabled {
|
||||
func CheckPushConf(cfg config.ConfYaml) error {
|
||||
if !cfg.Ios.Enabled && !cfg.Android.Enabled && !cfg.Huawei.Enabled {
|
||||
return errors.New("Please enable iOS, Android or Huawei config in yml config")
|
||||
}
|
||||
|
||||
if PushConf.Ios.Enabled {
|
||||
if PushConf.Ios.KeyPath == "" && PushConf.Ios.KeyBase64 == "" {
|
||||
if cfg.Ios.Enabled {
|
||||
if cfg.Ios.KeyPath == "" && cfg.Ios.KeyBase64 == "" {
|
||||
return errors.New("Missing iOS certificate key")
|
||||
}
|
||||
|
||||
// check certificate file exist
|
||||
if PushConf.Ios.KeyPath != "" {
|
||||
if _, err := os.Stat(PushConf.Ios.KeyPath); os.IsNotExist(err) {
|
||||
if cfg.Ios.KeyPath != "" {
|
||||
if _, err := os.Stat(cfg.Ios.KeyPath); os.IsNotExist(err) {
|
||||
return errors.New("certificate file does not exist")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if PushConf.Android.Enabled {
|
||||
if PushConf.Android.APIKey == "" {
|
||||
if cfg.Android.Enabled {
|
||||
if cfg.Android.APIKey == "" {
|
||||
return errors.New("Missing Android API Key")
|
||||
}
|
||||
}
|
||||
|
||||
if PushConf.Huawei.Enabled {
|
||||
if PushConf.Huawei.AppSecret == "" {
|
||||
if cfg.Huawei.Enabled {
|
||||
if cfg.Huawei.AppSecret == "" {
|
||||
return errors.New("Missing Huawei App Secret")
|
||||
}
|
||||
|
||||
if PushConf.Huawei.AppID == "" {
|
||||
if cfg.Huawei.AppID == "" {
|
||||
return errors.New("Missing Huawei App ID")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendNotification send notification
|
||||
func SendNotification(cfg config.ConfYaml, req PushNotification) {
|
||||
defer func() {
|
||||
req.WaitDone()
|
||||
}()
|
||||
|
||||
switch req.Platform {
|
||||
case core.PlatFormIos:
|
||||
PushToIOS(cfg, req)
|
||||
case core.PlatFormAndroid:
|
||||
PushToAndroid(cfg, req)
|
||||
case core.PlatFormHuawei:
|
||||
PushToHuawei(cfg, req)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/status"
|
||||
|
@ -50,23 +51,23 @@ type Sound struct {
|
|||
}
|
||||
|
||||
// InitAPNSClient use for initialize APNs Client.
|
||||
func InitAPNSClient() error {
|
||||
if PushConf.Ios.Enabled {
|
||||
func InitAPNSClient(cfg config.ConfYaml) error {
|
||||
if cfg.Ios.Enabled {
|
||||
var err error
|
||||
var authKey *ecdsa.PrivateKey
|
||||
var certificateKey tls.Certificate
|
||||
var ext string
|
||||
|
||||
if PushConf.Ios.KeyPath != "" {
|
||||
ext = filepath.Ext(PushConf.Ios.KeyPath)
|
||||
if cfg.Ios.KeyPath != "" {
|
||||
ext = filepath.Ext(cfg.Ios.KeyPath)
|
||||
|
||||
switch ext {
|
||||
case ".p12":
|
||||
certificateKey, err = certificate.FromP12File(PushConf.Ios.KeyPath, PushConf.Ios.Password)
|
||||
certificateKey, err = certificate.FromP12File(cfg.Ios.KeyPath, cfg.Ios.Password)
|
||||
case ".pem":
|
||||
certificateKey, err = certificate.FromPemFile(PushConf.Ios.KeyPath, PushConf.Ios.Password)
|
||||
certificateKey, err = certificate.FromPemFile(cfg.Ios.KeyPath, cfg.Ios.Password)
|
||||
case ".p8":
|
||||
authKey, err = token.AuthKeyFromFile(PushConf.Ios.KeyPath)
|
||||
authKey, err = token.AuthKeyFromFile(cfg.Ios.KeyPath)
|
||||
default:
|
||||
err = errors.New("wrong certificate key extension")
|
||||
}
|
||||
|
@ -76,9 +77,9 @@ func InitAPNSClient() error {
|
|||
|
||||
return err
|
||||
}
|
||||
} else if PushConf.Ios.KeyBase64 != "" {
|
||||
ext = "." + PushConf.Ios.KeyType
|
||||
key, err := base64.StdEncoding.DecodeString(PushConf.Ios.KeyBase64)
|
||||
} else if cfg.Ios.KeyBase64 != "" {
|
||||
ext = "." + cfg.Ios.KeyType
|
||||
key, err := base64.StdEncoding.DecodeString(cfg.Ios.KeyBase64)
|
||||
if err != nil {
|
||||
logx.LogError.Error("base64 decode error:", err.Error())
|
||||
|
||||
|
@ -86,9 +87,9 @@ func InitAPNSClient() error {
|
|||
}
|
||||
switch ext {
|
||||
case ".p12":
|
||||
certificateKey, err = certificate.FromP12Bytes(key, PushConf.Ios.Password)
|
||||
certificateKey, err = certificate.FromP12Bytes(key, cfg.Ios.Password)
|
||||
case ".pem":
|
||||
certificateKey, err = certificate.FromPemBytes(key, PushConf.Ios.Password)
|
||||
certificateKey, err = certificate.FromPemBytes(key, cfg.Ios.Password)
|
||||
case ".p8":
|
||||
authKey, err = token.AuthKeyFromBytes(key)
|
||||
default:
|
||||
|
@ -103,7 +104,7 @@ func InitAPNSClient() error {
|
|||
}
|
||||
|
||||
if ext == ".p8" {
|
||||
if PushConf.Ios.KeyID == "" || PushConf.Ios.TeamID == "" {
|
||||
if cfg.Ios.KeyID == "" || cfg.Ios.TeamID == "" {
|
||||
msg := "You should provide ios.KeyID and ios.TeamID for P8 token"
|
||||
logx.LogError.Error(msg)
|
||||
return errors.New(msg)
|
||||
|
@ -111,14 +112,14 @@ func InitAPNSClient() error {
|
|||
token := &token.Token{
|
||||
AuthKey: authKey,
|
||||
// KeyID from developer account (Certificates, Identifiers & Profiles -> Keys)
|
||||
KeyID: PushConf.Ios.KeyID,
|
||||
KeyID: cfg.Ios.KeyID,
|
||||
// TeamID from developer account (View Account -> Membership)
|
||||
TeamID: PushConf.Ios.TeamID,
|
||||
TeamID: cfg.Ios.TeamID,
|
||||
}
|
||||
|
||||
ApnsClient, err = newApnsTokenClient(token)
|
||||
ApnsClient, err = newApnsTokenClient(cfg, token)
|
||||
} else {
|
||||
ApnsClient, err = newApnsClient(certificateKey)
|
||||
ApnsClient, err = newApnsClient(cfg, certificateKey)
|
||||
}
|
||||
|
||||
if h2Transport, ok := ApnsClient.HTTPClient.Transport.(*http2.Transport); ok {
|
||||
|
@ -130,21 +131,23 @@ func InitAPNSClient() error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
MaxConcurrentIOSPushes = make(chan struct{}, cfg.Ios.MaxConcurrentPushes)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newApnsClient(certificate tls.Certificate) (*apns2.Client, error) {
|
||||
func newApnsClient(cfg config.ConfYaml, certificate tls.Certificate) (*apns2.Client, error) {
|
||||
var client *apns2.Client
|
||||
|
||||
if PushConf.Ios.Production {
|
||||
if cfg.Ios.Production {
|
||||
client = apns2.NewClient(certificate).Production()
|
||||
} else {
|
||||
client = apns2.NewClient(certificate).Development()
|
||||
}
|
||||
|
||||
if PushConf.Core.HTTPProxy == "" {
|
||||
if cfg.Core.HTTPProxy == "" {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
|
@ -175,16 +178,16 @@ func newApnsClient(certificate tls.Certificate) (*apns2.Client, error) {
|
|||
return client, nil
|
||||
}
|
||||
|
||||
func newApnsTokenClient(token *token.Token) (*apns2.Client, error) {
|
||||
func newApnsTokenClient(cfg config.ConfYaml, token *token.Token) (*apns2.Client, error) {
|
||||
var client *apns2.Client
|
||||
|
||||
if PushConf.Ios.Production {
|
||||
if cfg.Ios.Production {
|
||||
client = apns2.NewTokenClient(token).Production()
|
||||
} else {
|
||||
client = apns2.NewTokenClient(token).Development()
|
||||
}
|
||||
|
||||
if PushConf.Core.HTTPProxy == "" {
|
||||
if cfg.Core.HTTPProxy == "" {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
|
@ -365,13 +368,13 @@ func GetIOSNotification(req PushNotification) *apns2.Notification {
|
|||
return notification
|
||||
}
|
||||
|
||||
func getApnsClient(req PushNotification) (client *apns2.Client) {
|
||||
func getApnsClient(cfg config.ConfYaml, req PushNotification) (client *apns2.Client) {
|
||||
if req.Production {
|
||||
client = ApnsClient.Production()
|
||||
} else if req.Development {
|
||||
client = ApnsClient.Development()
|
||||
} else {
|
||||
if PushConf.Ios.Production {
|
||||
if cfg.Ios.Production {
|
||||
client = ApnsClient.Production()
|
||||
} else {
|
||||
client = ApnsClient.Development()
|
||||
|
@ -381,12 +384,12 @@ func getApnsClient(req PushNotification) (client *apns2.Client) {
|
|||
}
|
||||
|
||||
// PushToIOS provide send notification to APNs server.
|
||||
func PushToIOS(req PushNotification) {
|
||||
func PushToIOS(cfg config.ConfYaml, req PushNotification) {
|
||||
logx.LogAccess.Debug("Start push notification for iOS")
|
||||
|
||||
var (
|
||||
retryCount = 0
|
||||
maxRetry = PushConf.Ios.MaxRetry
|
||||
maxRetry = cfg.Ios.MaxRetry
|
||||
)
|
||||
|
||||
if req.Retry > 0 && req.Retry < maxRetry {
|
||||
|
@ -397,7 +400,7 @@ Retry:
|
|||
var newTokens []string
|
||||
|
||||
notification := GetIOSNotification(req)
|
||||
client := getApnsClient(req)
|
||||
client := getApnsClient(cfg, req)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, token := range req.Tokens {
|
||||
|
@ -416,17 +419,17 @@ Retry:
|
|||
err = errors.New(res.Reason)
|
||||
}
|
||||
// apns server error
|
||||
logPush(core.FailedPush, token, req, err)
|
||||
logPush(cfg, core.FailedPush, token, req, err)
|
||||
|
||||
if PushConf.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(core.FailedPush, token, req, err))
|
||||
} else if PushConf.Core.FeedbackURL != "" {
|
||||
if cfg.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(cfg, core.FailedPush, token, req, err))
|
||||
} else if cfg.Core.FeedbackURL != "" {
|
||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||
err := DispatchFeedback(log, url, timeout)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
}(logx.LogError, createLogPushEntry(core.FailedPush, token, req, err), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
||||
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, token, req, err), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
}
|
||||
|
||||
status.StatStorage.AddIosError(1)
|
||||
|
@ -438,7 +441,7 @@ Retry:
|
|||
}
|
||||
|
||||
if res != nil && res.Sent() {
|
||||
logPush(core.SucceededPush, token, req, nil)
|
||||
logPush(cfg, core.SucceededPush, token, req, nil)
|
||||
status.StatStorage.AddIosSuccess(1)
|
||||
}
|
||||
// free push slot
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/status"
|
||||
"github.com/buger/jsonparser"
|
||||
"github.com/sideshow/apns2"
|
||||
|
@ -27,29 +24,29 @@ const authkeyInvalidP8 = `TUlHSEFnRUFNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQkcwd2
|
|||
const authkeyValidP8 = `LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ0ViVnpmUG5aUHhmQXl4cUUKWlYwNWxhQW9KQWwrLzZYdDJPNG1PQjYxMXNPaFJBTkNBQVNnRlRLandKQUFVOTVnKysvdnpLV0hrekFWbU5NSQp0QjV2VGpaT09Jd25FYjcwTXNXWkZJeVVGRDFQOUd3c3R6NCtha0hYN3ZJOEJINmhIbUJtZmVRbAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==`
|
||||
|
||||
func TestDisabledAndroidIosConf(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
PushConf.Android.Enabled = false
|
||||
PushConf.Huawei.Enabled = false
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Android.Enabled = false
|
||||
cfg.Huawei.Enabled = false
|
||||
|
||||
err := CheckPushConf()
|
||||
err := CheckPushConf(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Please enable iOS, Android or Huawei config in yml config", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingIOSCertificate(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = ""
|
||||
PushConf.Ios.KeyBase64 = ""
|
||||
err := CheckPushConf()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = ""
|
||||
cfg.Ios.KeyBase64 = ""
|
||||
err := CheckPushConf(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing iOS certificate key", err.Error())
|
||||
|
||||
PushConf.Ios.KeyPath = "test.pem"
|
||||
err = CheckPushConf()
|
||||
cfg.Ios.KeyPath = "test.pem"
|
||||
err = CheckPushConf(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "certificate file does not exist", err.Error())
|
||||
|
@ -566,166 +563,130 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
|
|||
assert.Contains(t, locArgs, "b")
|
||||
}
|
||||
|
||||
func TestDisabledIosNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Ios.Enabled = false
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
assert.Nil(t, err)
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := RequestPush{
|
||||
Notifications: []PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, androidToken + "_"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := HandleNotification(ctx, req)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Equal(t, 0, len(logs))
|
||||
}
|
||||
|
||||
func TestWrongIosCertificateExt(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "test"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "test"
|
||||
err := InitAPNSClient(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "wrong certificate key extension", err.Error())
|
||||
|
||||
PushConf.Ios.KeyPath = ""
|
||||
PushConf.Ios.KeyBase64 = "abcd"
|
||||
PushConf.Ios.KeyType = "abcd"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyPath = ""
|
||||
cfg.Ios.KeyBase64 = "abcd"
|
||||
cfg.Ios.KeyType = "abcd"
|
||||
err = InitAPNSClient(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "wrong certificate key type", err.Error())
|
||||
}
|
||||
|
||||
func TestAPNSClientDevHost(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||
|
||||
PushConf.Ios.KeyPath = ""
|
||||
PushConf.Ios.KeyBase64 = certificateValidP12
|
||||
PushConf.Ios.KeyType = "p12"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyPath = ""
|
||||
cfg.Ios.KeyBase64 = certificateValidP12
|
||||
cfg.Ios.KeyType = "p12"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||
}
|
||||
|
||||
func TestAPNSClientProdHost(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.Production = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.Production = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||
|
||||
PushConf.Ios.KeyPath = ""
|
||||
PushConf.Ios.KeyBase64 = certificateValidPEM
|
||||
PushConf.Ios.KeyType = "pem"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyPath = ""
|
||||
cfg.Ios.KeyBase64 = certificateValidPEM
|
||||
cfg.Ios.KeyType = "pem"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||
}
|
||||
|
||||
func TestAPNSClientInvaildToken(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/authkey-invalid.p8"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/authkey-invalid.p8"
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.Error(t, err)
|
||||
|
||||
PushConf.Ios.KeyPath = ""
|
||||
PushConf.Ios.KeyBase64 = authkeyInvalidP8
|
||||
PushConf.Ios.KeyType = "p8"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyPath = ""
|
||||
cfg.Ios.KeyBase64 = authkeyInvalidP8
|
||||
cfg.Ios.KeyType = "p8"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Error(t, err)
|
||||
|
||||
// empty key-id or team-id
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Error(t, err)
|
||||
|
||||
PushConf.Ios.KeyID = "key-id"
|
||||
PushConf.Ios.TeamID = ""
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyID = "key-id"
|
||||
cfg.Ios.TeamID = ""
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Error(t, err)
|
||||
|
||||
PushConf.Ios.KeyID = ""
|
||||
PushConf.Ios.TeamID = "team-id"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyID = ""
|
||||
cfg.Ios.TeamID = "team-id"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAPNSClientVaildToken(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||
PushConf.Ios.KeyID = "key-id"
|
||||
PushConf.Ios.TeamID = "team-id"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||
cfg.Ios.KeyID = "key-id"
|
||||
cfg.Ios.TeamID = "team-id"
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||
|
||||
PushConf.Ios.Production = true
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.Production = true
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||
|
||||
// test base64
|
||||
PushConf.Ios.Production = false
|
||||
PushConf.Ios.KeyPath = ""
|
||||
PushConf.Ios.KeyBase64 = authkeyValidP8
|
||||
PushConf.Ios.KeyType = "p8"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.Production = false
|
||||
cfg.Ios.KeyPath = ""
|
||||
cfg.Ios.KeyBase64 = authkeyValidP8
|
||||
cfg.Ios.KeyType = "p8"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||
|
||||
PushConf.Ios.Production = true
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.Production = true
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||
}
|
||||
|
||||
func TestAPNSClientUseProxy(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
||||
PushConf.Core.HTTPProxy = "http://127.0.0.1:8080"
|
||||
_ = SetProxy(PushConf.Core.HTTPProxy)
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
||||
cfg.Core.HTTPProxy = "http://127.0.0.1:8080"
|
||||
_ = SetProxy(cfg.Core.HTTPProxy)
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||
|
||||
|
@ -733,13 +694,13 @@ func TestAPNSClientUseProxy(t *testing.T) {
|
|||
actualProxyURL, err := ApnsClient.HTTPClient.Transport.(*http.Transport).Proxy(req)
|
||||
assert.Nil(t, err)
|
||||
|
||||
expectedProxyURL, _ := url.ParseRequestURI(PushConf.Core.HTTPProxy)
|
||||
expectedProxyURL, _ := url.ParseRequestURI(cfg.Core.HTTPProxy)
|
||||
assert.Equal(t, expectedProxyURL, actualProxyURL)
|
||||
|
||||
PushConf.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||
PushConf.Ios.TeamID = "example.team"
|
||||
PushConf.Ios.KeyID = "example.key"
|
||||
err = InitAPNSClient()
|
||||
cfg.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||
cfg.Ios.TeamID = "example.team"
|
||||
cfg.Ios.KeyID = "example.key"
|
||||
err = InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||
assert.NotNil(t, ApnsClient.Token)
|
||||
|
@ -748,21 +709,21 @@ func TestAPNSClientUseProxy(t *testing.T) {
|
|||
actualProxyURL, err = ApnsClient.HTTPClient.Transport.(*http.Transport).Proxy(req)
|
||||
assert.Nil(t, err)
|
||||
|
||||
expectedProxyURL, _ = url.ParseRequestURI(PushConf.Core.HTTPProxy)
|
||||
expectedProxyURL, _ = url.ParseRequestURI(cfg.Core.HTTPProxy)
|
||||
assert.Equal(t, expectedProxyURL, actualProxyURL)
|
||||
|
||||
http.DefaultTransport.(*http.Transport).Proxy = nil
|
||||
}
|
||||
|
||||
func TestPushToIOS(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
MaxConcurrentIOSPushes = make(chan struct{}, PushConf.Ios.MaxConcurrentPushes)
|
||||
cfg, _ := config.LoadConf()
|
||||
MaxConcurrentIOSPushes = make(chan struct{}, cfg.Ios.MaxConcurrentPushes)
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
err = status.InitAppStatus(PushConf)
|
||||
err = status.InitAppStatus(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
req := PushNotification{
|
||||
|
@ -772,37 +733,37 @@ func TestPushToIOS(t *testing.T) {
|
|||
}
|
||||
|
||||
// send fail
|
||||
PushToIOS(req)
|
||||
PushToIOS(cfg, req)
|
||||
}
|
||||
|
||||
func TestApnsHostFromRequest(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
err = status.InitAppStatus(PushConf)
|
||||
err = status.InitAppStatus(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
req := PushNotification{
|
||||
Production: true,
|
||||
}
|
||||
client := getApnsClient(req)
|
||||
client := getApnsClient(cfg, req)
|
||||
assert.Equal(t, apns2.HostProduction, client.Host)
|
||||
|
||||
req = PushNotification{
|
||||
Development: true,
|
||||
}
|
||||
client = getApnsClient(req)
|
||||
client = getApnsClient(cfg, req)
|
||||
assert.Equal(t, apns2.HostDevelopment, client.Host)
|
||||
|
||||
req = PushNotification{}
|
||||
PushConf.Ios.Production = true
|
||||
client = getApnsClient(req)
|
||||
cfg.Ios.Production = true
|
||||
client = getApnsClient(cfg, req)
|
||||
assert.Equal(t, apns2.HostProduction, client.Host)
|
||||
|
||||
PushConf.Ios.Production = false
|
||||
client = getApnsClient(req)
|
||||
cfg.Ios.Production = false
|
||||
client = getApnsClient(cfg, req)
|
||||
assert.Equal(t, apns2.HostDevelopment, client.Host)
|
||||
}
|
||||
|
|
|
@ -4,27 +4,29 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/appleboy/go-fcm"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/status"
|
||||
|
||||
"github.com/appleboy/go-fcm"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// InitFCMClient use for initialize FCM Client.
|
||||
func InitFCMClient(key string) (*fcm.Client, error) {
|
||||
func InitFCMClient(cfg config.ConfYaml, key string) (*fcm.Client, error) {
|
||||
var err error
|
||||
|
||||
if key == "" {
|
||||
if key == "" && cfg.Android.APIKey == "" {
|
||||
return nil, errors.New("Missing Android API Key")
|
||||
}
|
||||
|
||||
if key != PushConf.Android.APIKey {
|
||||
if key != "" && key != cfg.Android.APIKey {
|
||||
return fcm.NewClient(key)
|
||||
}
|
||||
|
||||
if FCMClient == nil {
|
||||
FCMClient, err = fcm.NewClient(key)
|
||||
FCMClient, err = fcm.NewClient(cfg.Android.APIKey)
|
||||
return FCMClient, err
|
||||
}
|
||||
|
||||
|
@ -104,13 +106,13 @@ func GetAndroidNotification(req PushNotification) *fcm.Message {
|
|||
}
|
||||
|
||||
// PushToAndroid provide send notification to Android server.
|
||||
func PushToAndroid(req PushNotification) {
|
||||
func PushToAndroid(cfg config.ConfYaml, req PushNotification) {
|
||||
logx.LogAccess.Debug("Start push notification for Android")
|
||||
|
||||
var (
|
||||
client *fcm.Client
|
||||
retryCount = 0
|
||||
maxRetry = PushConf.Android.MaxRetry
|
||||
maxRetry = cfg.Android.MaxRetry
|
||||
)
|
||||
|
||||
if req.Retry > 0 && req.Retry < maxRetry {
|
||||
|
@ -128,9 +130,9 @@ Retry:
|
|||
notification := GetAndroidNotification(req)
|
||||
|
||||
if req.APIKey != "" {
|
||||
client, err = InitFCMClient(req.APIKey)
|
||||
client, err = InitFCMClient(cfg, req.APIKey)
|
||||
} else {
|
||||
client, err = InitFCMClient(PushConf.Android.APIKey)
|
||||
client, err = InitFCMClient(cfg, cfg.Android.APIKey)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -145,28 +147,28 @@ Retry:
|
|||
logx.LogError.Error("FCM server send message error: " + err.Error())
|
||||
|
||||
if req.IsTopic() {
|
||||
if PushConf.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(core.FailedPush, req.To, req, err))
|
||||
} else if PushConf.Core.FeedbackURL != "" {
|
||||
if cfg.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(cfg, core.FailedPush, req.To, req, err))
|
||||
} else if cfg.Core.FeedbackURL != "" {
|
||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||
err := DispatchFeedback(log, url, timeout)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
}(logx.LogError, createLogPushEntry(core.FailedPush, req.To, req, err), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
||||
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, req.To, req, err), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
}
|
||||
status.StatStorage.AddAndroidError(1)
|
||||
} else {
|
||||
for _, token := range req.Tokens {
|
||||
if PushConf.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(core.FailedPush, token, req, err))
|
||||
} else if PushConf.Core.FeedbackURL != "" {
|
||||
if cfg.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(cfg, core.FailedPush, token, req, err))
|
||||
} else if cfg.Core.FeedbackURL != "" {
|
||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||
err := DispatchFeedback(log, url, timeout)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
}(logx.LogError, createLogPushEntry(core.FailedPush, token, req, err), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
||||
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, token, req, err), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
}
|
||||
}
|
||||
status.StatStorage.AddAndroidError(int64(len(req.Tokens)))
|
||||
|
@ -198,21 +200,21 @@ Retry:
|
|||
newTokens = append(newTokens, to)
|
||||
}
|
||||
|
||||
logPush(core.FailedPush, to, req, result.Error)
|
||||
if PushConf.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(core.FailedPush, to, req, result.Error))
|
||||
} else if PushConf.Core.FeedbackURL != "" {
|
||||
logPush(cfg, core.FailedPush, to, req, result.Error)
|
||||
if cfg.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(cfg, core.FailedPush, to, req, result.Error))
|
||||
} else if cfg.Core.FeedbackURL != "" {
|
||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||
err := DispatchFeedback(log, url, timeout)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
}(logx.LogError, createLogPushEntry(core.FailedPush, to, req, result.Error), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
||||
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, to, req, result.Error), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
logPush(core.SucceededPush, to, req, nil)
|
||||
logPush(cfg, core.SucceededPush, to, req, nil)
|
||||
}
|
||||
|
||||
// result from Send messages to topics
|
||||
|
@ -226,12 +228,12 @@ Retry:
|
|||
logx.LogAccess.Debug("Send Topic Message: ", to)
|
||||
// Success
|
||||
if res.MessageID != 0 {
|
||||
logPush(core.SucceededPush, to, req, nil)
|
||||
logPush(cfg, core.SucceededPush, to, req, nil)
|
||||
} else {
|
||||
// failure
|
||||
logPush(core.FailedPush, to, req, res.Error)
|
||||
if PushConf.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(core.FailedPush, to, req, res.Error))
|
||||
logPush(cfg, core.FailedPush, to, req, res.Error)
|
||||
if cfg.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(cfg, core.FailedPush, to, req, res.Error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,9 +242,9 @@ Retry:
|
|||
if len(res.FailedRegistrationIDs) > 0 {
|
||||
newTokens = append(newTokens, res.FailedRegistrationIDs...)
|
||||
|
||||
logPush(core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails"))
|
||||
if PushConf.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails")))
|
||||
logPush(cfg, core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails"))
|
||||
if cfg.Core.Sync {
|
||||
req.AddLog(createLogPushEntry(cfg, core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails")))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +257,7 @@ Retry:
|
|||
}
|
||||
}
|
||||
|
||||
func createLogPushEntry(status, token string, req PushNotification, err error) logx.LogPushEntry {
|
||||
func createLogPushEntry(cfg config.ConfYaml, status, token string, req PushNotification, err error) logx.LogPushEntry {
|
||||
return logx.GetLogPushEntry(&logx.InputLog{
|
||||
ID: req.ID,
|
||||
Status: status,
|
||||
|
@ -263,12 +265,12 @@ func createLogPushEntry(status, token string, req PushNotification, err error) l
|
|||
Message: req.Message,
|
||||
Platform: req.Platform,
|
||||
Error: err,
|
||||
HideToken: PushConf.Log.HideToken,
|
||||
Format: PushConf.Log.Format,
|
||||
HideToken: cfg.Log.HideToken,
|
||||
Format: cfg.Log.Format,
|
||||
})
|
||||
}
|
||||
|
||||
func logPush(status, token string, req PushNotification, err error) {
|
||||
func logPush(cfg config.ConfYaml, status, token string, req PushNotification, err error) {
|
||||
logx.LogPush(&logx.InputLog{
|
||||
ID: req.ID,
|
||||
Status: status,
|
||||
|
@ -276,7 +278,7 @@ func logPush(status, token string, req PushNotification, err error) {
|
|||
Message: req.Message,
|
||||
Platform: req.Platform,
|
||||
Error: err,
|
||||
HideToken: PushConf.Log.HideToken,
|
||||
Format: PushConf.Log.Format,
|
||||
HideToken: cfg.Log.HideToken,
|
||||
Format: cfg.Log.Format,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,19 +13,21 @@ import (
|
|||
)
|
||||
|
||||
func TestMissingAndroidAPIKey(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = ""
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = ""
|
||||
|
||||
err := CheckPushConf()
|
||||
err := CheckPushConf(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Android API Key", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingKeyForInitFCMClient(t *testing.T) {
|
||||
client, err := InitFCMClient("")
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Android.APIKey = ""
|
||||
client, err := InitFCMClient(cfg, "")
|
||||
|
||||
assert.Nil(t, client)
|
||||
assert.Error(t, err)
|
||||
|
@ -33,10 +35,10 @@ func TestMissingKeyForInitFCMClient(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPushToAndroidWrongToken(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
req := PushNotification{
|
||||
Tokens: []string{"aaaaaa", "bbbbb"},
|
||||
|
@ -45,16 +47,16 @@ func TestPushToAndroidWrongToken(t *testing.T) {
|
|||
}
|
||||
|
||||
// Android Success count: 0, Failure count: 2
|
||||
PushToAndroid(req)
|
||||
PushToAndroid(cfg, req)
|
||||
}
|
||||
|
||||
func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
// log for json
|
||||
PushConf.Log.Format = "json"
|
||||
cfg.Log.Format = "json"
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
|
@ -64,14 +66,14 @@ func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
|
|||
Message: "Welcome",
|
||||
}
|
||||
|
||||
PushToAndroid(req)
|
||||
PushToAndroid(cfg, req)
|
||||
}
|
||||
|
||||
func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
|
@ -81,15 +83,15 @@ func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
|
|||
Message: "Welcome",
|
||||
}
|
||||
|
||||
PushToAndroid(req)
|
||||
PushToAndroid(cfg, req)
|
||||
}
|
||||
|
||||
func TestOverwriteAndroidAPIKey(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Core.Sync = true
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Core.Sync = true
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
|
@ -100,13 +102,13 @@ func TestOverwriteAndroidAPIKey(t *testing.T) {
|
|||
// overwrite android api key
|
||||
APIKey: "1234",
|
||||
|
||||
log: &[]logx.LogPushEntry{},
|
||||
Log: &[]logx.LogPushEntry{},
|
||||
}
|
||||
|
||||
// FCM server error: 401 error: 401 Unauthorized (Wrong API Key)
|
||||
PushToAndroid(req)
|
||||
PushToAndroid(cfg, req)
|
||||
|
||||
assert.Len(t, *req.log, 2)
|
||||
assert.Len(t, *req.Log, 2)
|
||||
}
|
||||
|
||||
func TestFCMMessage(t *testing.T) {
|
||||
|
@ -188,10 +190,10 @@ func TestFCMMessage(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCheckAndroidMessage(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
timeToLive := uint(2419201)
|
||||
req := PushNotification{
|
||||
|
@ -201,7 +203,7 @@ func TestCheckAndroidMessage(t *testing.T) {
|
|||
TimeToLive: &timeToLive,
|
||||
}
|
||||
|
||||
PushToAndroid(req)
|
||||
PushToAndroid(cfg, req)
|
||||
}
|
||||
|
||||
func TestAndroidNotificationStructure(t *testing.T) {
|
||||
|
|
|
@ -6,10 +6,11 @@ import (
|
|||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/status"
|
||||
|
||||
"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"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||
)
|
||||
|
@ -21,7 +22,7 @@ var (
|
|||
)
|
||||
|
||||
// GetPushClient use for create HMS Push
|
||||
func GetPushClient(conf *config.Config) (*core.HMSClient, error) {
|
||||
func GetPushClient(conf *c.Config) (*core.HMSClient, error) {
|
||||
once.Do(func() {
|
||||
client, err := core.NewHttpClient(conf)
|
||||
if err != nil {
|
||||
|
@ -35,7 +36,7 @@ func GetPushClient(conf *config.Config) (*core.HMSClient, error) {
|
|||
}
|
||||
|
||||
// InitHMSClient use for initialize HMS Client.
|
||||
func InitHMSClient(appSecret, appID string) (*core.HMSClient, error) {
|
||||
func InitHMSClient(cfg config.ConfYaml, appSecret, appID string) (*core.HMSClient, error) {
|
||||
if appSecret == "" {
|
||||
return nil, errors.New("Missing Huawei App Secret")
|
||||
}
|
||||
|
@ -44,14 +45,14 @@ func InitHMSClient(appSecret, appID string) (*core.HMSClient, error) {
|
|||
return nil, errors.New("Missing Huawei App ID")
|
||||
}
|
||||
|
||||
conf := &config.Config{
|
||||
conf := &c.Config{
|
||||
AppId: appID,
|
||||
AppSecret: appSecret,
|
||||
AuthUrl: "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
|
||||
PushUrl: "https://push-api.cloud.huawei.com",
|
||||
}
|
||||
|
||||
if appSecret != PushConf.Huawei.AppSecret || appID != PushConf.Huawei.AppID {
|
||||
if appSecret != cfg.Huawei.AppSecret || appID != cfg.Huawei.AppID {
|
||||
return GetPushClient(conf)
|
||||
}
|
||||
|
||||
|
@ -165,13 +166,13 @@ func GetHuaweiNotification(req PushNotification) (*model.MessageRequest, error)
|
|||
}
|
||||
|
||||
// PushToHuawei provide send notification to Android server.
|
||||
func PushToHuawei(req PushNotification) bool {
|
||||
func PushToHuawei(cfg config.ConfYaml, req PushNotification) bool {
|
||||
logx.LogAccess.Debug("Start push notification for Huawei")
|
||||
|
||||
var (
|
||||
client *core.HMSClient
|
||||
retryCount = 0
|
||||
maxRetry = PushConf.Huawei.MaxRetry
|
||||
maxRetry = cfg.Huawei.MaxRetry
|
||||
)
|
||||
|
||||
if req.Retry > 0 && req.Retry < maxRetry {
|
||||
|
@ -190,7 +191,7 @@ Retry:
|
|||
|
||||
notification, _ := GetHuaweiNotification(req)
|
||||
|
||||
client, err = InitHMSClient(PushConf.Huawei.AppSecret, PushConf.Huawei.AppID)
|
||||
client, err = InitHMSClient(cfg, cfg.Huawei.AppSecret, cfg.Huawei.AppID)
|
||||
|
||||
if err != nil {
|
||||
// HMS server error
|
||||
|
|
|
@ -8,31 +8,32 @@ import (
|
|||
)
|
||||
|
||||
func TestMissingHuaweiAppSecret(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Huawei.Enabled = true
|
||||
PushConf.Huawei.AppSecret = ""
|
||||
cfg.Huawei.Enabled = true
|
||||
cfg.Huawei.AppSecret = ""
|
||||
|
||||
err := CheckPushConf()
|
||||
err := CheckPushConf(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Huawei App Secret", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingHuaweiAppID(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Huawei.Enabled = true
|
||||
PushConf.Huawei.AppID = ""
|
||||
cfg.Huawei.Enabled = true
|
||||
cfg.Huawei.AppID = ""
|
||||
|
||||
err := CheckPushConf()
|
||||
err := CheckPushConf(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Huawei App ID", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingAppSecretForInitHMSClient(t *testing.T) {
|
||||
client, err := InitHMSClient("", "APP_SECRET")
|
||||
cfg, _ := config.LoadConf()
|
||||
client, err := InitHMSClient(cfg, "", "APP_SECRET")
|
||||
|
||||
assert.Nil(t, client)
|
||||
assert.Error(t, err)
|
||||
|
@ -40,7 +41,8 @@ func TestMissingAppSecretForInitHMSClient(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMissingAppIDForInitHMSClient(t *testing.T) {
|
||||
client, err := InitHMSClient("APP_ID", "")
|
||||
cfg, _ := config.LoadConf()
|
||||
client, err := InitHMSClient(cfg, "APP_ID", "")
|
||||
|
||||
assert.Nil(t, client)
|
||||
assert.Error(t, err)
|
||||
|
|
|
@ -1,210 +1,26 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCorrectConf(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = "xxxxx"
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = "xxxxx"
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
|
||||
err := CheckPushConf()
|
||||
err := CheckPushConf(cfg)
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestSenMultipleNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
assert.Nil(t, err)
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := RequestPush{
|
||||
Notifications: []PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, "bbbbb"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := HandleNotification(ctx, req)
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Equal(t, 0, len(logs))
|
||||
}
|
||||
|
||||
func TestDisabledAndroidNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
assert.Nil(t, err)
|
||||
|
||||
PushConf.Android.Enabled = false
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := RequestPush{
|
||||
Notifications: []PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, "bbbbb"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := HandleNotification(ctx, req)
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Equal(t, 0, len(logs))
|
||||
}
|
||||
|
||||
func TestSyncModeForNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Ios.Enabled = true
|
||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := InitAPNSClient()
|
||||
assert.Nil(t, err)
|
||||
|
||||
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: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, "bbbbb"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := HandleNotification(ctx, req)
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Equal(t, 2, len(logs))
|
||||
}
|
||||
|
||||
func TestSyncModeForTopicNotification(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
PushConf.Log.HideToken = false
|
||||
|
||||
// enable sync mode
|
||||
PushConf.Core.Sync = true
|
||||
|
||||
req := RequestPush{
|
||||
Notifications: []PushNotification{
|
||||
// android
|
||||
{
|
||||
// error:InvalidParameters
|
||||
// Check that the provided parameters have the right name and type.
|
||||
To: "/topics/foo-bar@@@##",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||
},
|
||||
// android
|
||||
{
|
||||
// success
|
||||
To: "/topics/foo-bar",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||
},
|
||||
// android
|
||||
{
|
||||
// success
|
||||
Condition: "'dogs' in topics || 'cats' in topics",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := HandleNotification(ctx, req)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Equal(t, 1, len(logs))
|
||||
}
|
||||
|
||||
func TestSyncModeForDeviceGroupNotification(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Android.Enabled = true
|
||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
PushConf.Log.HideToken = false
|
||||
|
||||
// enable sync mode
|
||||
PushConf.Core.Sync = true
|
||||
|
||||
req := RequestPush{
|
||||
Notifications: []PushNotification{
|
||||
// android
|
||||
{
|
||||
To: "aUniqueKey",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Device Group Message!",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := HandleNotification(ctx, req)
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Equal(t, 1, len(logs))
|
||||
}
|
||||
|
||||
func TestSetProxyURL(t *testing.T) {
|
||||
err := SetProxy("87.236.233.92:8080")
|
||||
assert.Error(t, err)
|
||||
|
|
124
gorush/worker.go
124
gorush/worker.go
|
@ -1,124 +0,0 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/status"
|
||||
)
|
||||
|
||||
// InitWorkers for initialize all workers.
|
||||
func InitWorkers(ctx context.Context, wg *sync.WaitGroup, workerNum, queueNum int64) {
|
||||
logx.LogAccess.Info("worker number is ", workerNum, ", queue number is ", queueNum)
|
||||
QueueNotification = make(chan PushNotification, queueNum)
|
||||
for i := int64(0); i < workerNum; i++ {
|
||||
go startWorker(ctx, wg, i)
|
||||
}
|
||||
}
|
||||
|
||||
// SendNotification is send message to iOS, Android or Huawei
|
||||
func SendNotification(ctx context.Context, req PushNotification) {
|
||||
if PushConf.Core.Sync {
|
||||
defer req.WaitDone()
|
||||
}
|
||||
|
||||
switch req.Platform {
|
||||
case core.PlatFormIos:
|
||||
PushToIOS(req)
|
||||
case core.PlatFormAndroid:
|
||||
PushToAndroid(req)
|
||||
case core.PlatFormHuawei:
|
||||
PushToHuawei(req)
|
||||
}
|
||||
}
|
||||
|
||||
func startWorker(ctx context.Context, wg *sync.WaitGroup, num int64) {
|
||||
defer wg.Done()
|
||||
for notification := range QueueNotification {
|
||||
SendNotification(ctx, notification)
|
||||
}
|
||||
logx.LogAccess.Info("closed the worker num ", num)
|
||||
}
|
||||
|
||||
// markFailedNotification adds failure logs for all tokens in push notification
|
||||
func markFailedNotification(notification *PushNotification, reason string) {
|
||||
logx.LogError.Error(reason)
|
||||
for _, token := range notification.Tokens {
|
||||
notification.AddLog(logx.GetLogPushEntry(&logx.InputLog{
|
||||
ID: notification.ID,
|
||||
Status: core.FailedPush,
|
||||
Token: token,
|
||||
Message: notification.Message,
|
||||
Platform: notification.Platform,
|
||||
Error: errors.New(reason),
|
||||
HideToken: PushConf.Log.HideToken,
|
||||
Format: PushConf.Log.Format,
|
||||
}))
|
||||
}
|
||||
notification.WaitDone()
|
||||
}
|
||||
|
||||
// HandleNotification add notification to queue list.
|
||||
func HandleNotification(ctx context.Context, req RequestPush) (int, []logx.LogPushEntry) {
|
||||
var count int
|
||||
wg := sync.WaitGroup{}
|
||||
newNotification := []*PushNotification{}
|
||||
for i := range req.Notifications {
|
||||
notification := &req.Notifications[i]
|
||||
switch notification.Platform {
|
||||
case core.PlatFormIos:
|
||||
if !PushConf.Ios.Enabled {
|
||||
continue
|
||||
}
|
||||
case core.PlatFormAndroid:
|
||||
if !PushConf.Android.Enabled {
|
||||
continue
|
||||
}
|
||||
case core.PlatFormHuawei:
|
||||
if !PushConf.Huawei.Enabled {
|
||||
continue
|
||||
}
|
||||
}
|
||||
newNotification = append(newNotification, notification)
|
||||
}
|
||||
|
||||
log := make([]logx.LogPushEntry, 0, count)
|
||||
for _, notification := range newNotification {
|
||||
if PushConf.Core.Sync {
|
||||
notification.wg = &wg
|
||||
notification.log = &log
|
||||
notification.AddWaitCount()
|
||||
}
|
||||
if !tryEnqueue(*notification, QueueNotification) {
|
||||
markFailedNotification(notification, "max capacity reached")
|
||||
}
|
||||
count += len(notification.Tokens)
|
||||
// Count topic message
|
||||
if notification.To != "" {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
if PushConf.Core.Sync {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
status.StatStorage.AddTotalCount(int64(count))
|
||||
|
||||
return count, log
|
||||
}
|
||||
|
||||
// tryEnqueue tries to enqueue a job to the given job channel. Returns true if
|
||||
// the operation was successful, and false if enqueuing would not have been
|
||||
// possible without blocking. Job is not enqueued in the latter case.
|
||||
func tryEnqueue(job PushNotification, jobChan chan<- PushNotification) bool {
|
||||
select {
|
||||
case jobChan <- job:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTryEnqueue(t *testing.T) {
|
||||
chn := make(chan PushNotification, 2)
|
||||
assert.True(t, tryEnqueue(PushNotification{}, chn))
|
||||
assert.Equal(t, 1, len(chn))
|
||||
assert.True(t, tryEnqueue(PushNotification{}, chn))
|
||||
assert.Equal(t, 2, len(chn))
|
||||
assert.False(t, tryEnqueue(PushNotification{}, chn))
|
||||
assert.Equal(t, 2, len(chn))
|
||||
}
|
|
@ -38,75 +38,75 @@ func TestSetLogOut(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInitDefaultLog(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
// no errors on default config
|
||||
assert.Nil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
))
|
||||
|
||||
PushConf.Log.AccessLevel = "invalid"
|
||||
cfg.Log.AccessLevel = "invalid"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestAccessLevel(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Log.AccessLevel = "invalid"
|
||||
cfg.Log.AccessLevel = "invalid"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestErrorLevel(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Log.ErrorLevel = "invalid"
|
||||
cfg.Log.ErrorLevel = "invalid"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestAccessLogPath(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Log.AccessLog = "logs/access.log"
|
||||
cfg.Log.AccessLog = "logs/access.log"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestErrorLogPath(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
PushConf.Log.ErrorLog = "logs/error.log"
|
||||
cfg.Log.ErrorLog = "logs/error.log"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
127
main.go
127
main.go
|
@ -11,7 +11,6 @@ import (
|
|||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
|
@ -19,6 +18,7 @@ import (
|
|||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/gorush"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/queue"
|
||||
"github.com/appleboy/gorush/router"
|
||||
"github.com/appleboy/gorush/rpc"
|
||||
"github.com/appleboy/gorush/status"
|
||||
|
@ -105,10 +105,8 @@ func main() {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
// set default parameters.
|
||||
gorush.PushConf, err = config.LoadConf(configFile)
|
||||
cfg, err := config.LoadConf(configFile)
|
||||
if err != nil {
|
||||
log.Printf("Load yaml config file error: '%v'", err)
|
||||
|
||||
|
@ -116,67 +114,67 @@ func main() {
|
|||
}
|
||||
|
||||
// Initialize push slots for concurrent iOS pushes
|
||||
gorush.MaxConcurrentIOSPushes = make(chan struct{}, gorush.PushConf.Ios.MaxConcurrentPushes)
|
||||
gorush.MaxConcurrentIOSPushes = make(chan struct{}, cfg.Ios.MaxConcurrentPushes)
|
||||
|
||||
if opts.Ios.KeyPath != "" {
|
||||
gorush.PushConf.Ios.KeyPath = opts.Ios.KeyPath
|
||||
cfg.Ios.KeyPath = opts.Ios.KeyPath
|
||||
}
|
||||
|
||||
if opts.Ios.KeyID != "" {
|
||||
gorush.PushConf.Ios.KeyID = opts.Ios.KeyID
|
||||
cfg.Ios.KeyID = opts.Ios.KeyID
|
||||
}
|
||||
|
||||
if opts.Ios.TeamID != "" {
|
||||
gorush.PushConf.Ios.TeamID = opts.Ios.TeamID
|
||||
cfg.Ios.TeamID = opts.Ios.TeamID
|
||||
}
|
||||
|
||||
if opts.Ios.Password != "" {
|
||||
gorush.PushConf.Ios.Password = opts.Ios.Password
|
||||
cfg.Ios.Password = opts.Ios.Password
|
||||
}
|
||||
|
||||
if opts.Android.APIKey != "" {
|
||||
gorush.PushConf.Android.APIKey = opts.Android.APIKey
|
||||
cfg.Android.APIKey = opts.Android.APIKey
|
||||
}
|
||||
|
||||
if opts.Huawei.AppSecret != "" {
|
||||
gorush.PushConf.Huawei.AppSecret = opts.Huawei.AppSecret
|
||||
cfg.Huawei.AppSecret = opts.Huawei.AppSecret
|
||||
}
|
||||
|
||||
if opts.Huawei.AppID != "" {
|
||||
gorush.PushConf.Huawei.AppID = opts.Huawei.AppID
|
||||
cfg.Huawei.AppID = opts.Huawei.AppID
|
||||
}
|
||||
|
||||
if opts.Stat.Engine != "" {
|
||||
gorush.PushConf.Stat.Engine = opts.Stat.Engine
|
||||
cfg.Stat.Engine = opts.Stat.Engine
|
||||
}
|
||||
|
||||
if opts.Stat.Redis.Addr != "" {
|
||||
gorush.PushConf.Stat.Redis.Addr = opts.Stat.Redis.Addr
|
||||
cfg.Stat.Redis.Addr = opts.Stat.Redis.Addr
|
||||
}
|
||||
|
||||
// overwrite server port and address
|
||||
if opts.Core.Port != "" {
|
||||
gorush.PushConf.Core.Port = opts.Core.Port
|
||||
cfg.Core.Port = opts.Core.Port
|
||||
}
|
||||
if opts.Core.Address != "" {
|
||||
gorush.PushConf.Core.Address = opts.Core.Address
|
||||
cfg.Core.Address = opts.Core.Address
|
||||
}
|
||||
|
||||
if err = logx.InitLog(
|
||||
gorush.PushConf.Log.AccessLevel,
|
||||
gorush.PushConf.Log.AccessLog,
|
||||
gorush.PushConf.Log.ErrorLevel,
|
||||
gorush.PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
); err != nil {
|
||||
log.Fatalf("Can't load log module, error: %v", err)
|
||||
}
|
||||
|
||||
if opts.Core.HTTPProxy != "" {
|
||||
gorush.PushConf.Core.HTTPProxy = opts.Core.HTTPProxy
|
||||
cfg.Core.HTTPProxy = opts.Core.HTTPProxy
|
||||
}
|
||||
|
||||
if gorush.PushConf.Core.HTTPProxy != "" {
|
||||
err = gorush.SetProxy(gorush.PushConf.Core.HTTPProxy)
|
||||
if cfg.Core.HTTPProxy != "" {
|
||||
err = gorush.SetProxy(cfg.Core.HTTPProxy)
|
||||
|
||||
if err != nil {
|
||||
logx.LogError.Fatalf("Set Proxy error: %v", err)
|
||||
|
@ -184,7 +182,7 @@ func main() {
|
|||
}
|
||||
|
||||
if ping {
|
||||
if err := pinger(); err != nil {
|
||||
if err := pinger(cfg); err != nil {
|
||||
logx.LogError.Warnf("ping server error: %v", err)
|
||||
}
|
||||
return
|
||||
|
@ -192,7 +190,7 @@ func main() {
|
|||
|
||||
// send android notification
|
||||
if opts.Android.Enabled {
|
||||
gorush.PushConf.Android.Enabled = opts.Android.Enabled
|
||||
cfg.Android.Enabled = opts.Android.Enabled
|
||||
req := gorush.PushNotification{
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: message,
|
||||
|
@ -214,18 +212,18 @@ func main() {
|
|||
logx.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if err := status.InitAppStatus(gorush.PushConf); err != nil {
|
||||
if err := status.InitAppStatus(cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
gorush.PushToAndroid(req)
|
||||
gorush.PushToAndroid(cfg, req)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// send huawei notification
|
||||
if opts.Huawei.Enabled {
|
||||
gorush.PushConf.Huawei.Enabled = opts.Huawei.Enabled
|
||||
cfg.Huawei.Enabled = opts.Huawei.Enabled
|
||||
req := gorush.PushNotification{
|
||||
Platform: core.PlatFormHuawei,
|
||||
Message: message,
|
||||
|
@ -247,11 +245,11 @@ func main() {
|
|||
logx.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if err := status.InitAppStatus(gorush.PushConf); err != nil {
|
||||
if err := status.InitAppStatus(cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
gorush.PushToHuawei(req)
|
||||
gorush.PushToHuawei(cfg, req)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -259,10 +257,10 @@ func main() {
|
|||
// send ios notification
|
||||
if opts.Ios.Enabled {
|
||||
if opts.Ios.Production {
|
||||
gorush.PushConf.Ios.Production = opts.Ios.Production
|
||||
cfg.Ios.Production = opts.Ios.Production
|
||||
}
|
||||
|
||||
gorush.PushConf.Ios.Enabled = opts.Ios.Enabled
|
||||
cfg.Ios.Enabled = opts.Ios.Enabled
|
||||
req := gorush.PushNotification{
|
||||
Platform: core.PlatFormIos,
|
||||
Message: message,
|
||||
|
@ -284,68 +282,71 @@ func main() {
|
|||
logx.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if err := status.InitAppStatus(gorush.PushConf); err != nil {
|
||||
if err := status.InitAppStatus(cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := gorush.InitAPNSClient(); err != nil {
|
||||
if err := gorush.InitAPNSClient(cfg); err != nil {
|
||||
return
|
||||
}
|
||||
gorush.PushToIOS(req)
|
||||
gorush.PushToIOS(cfg, req)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err = gorush.CheckPushConf(); err != nil {
|
||||
if err = gorush.CheckPushConf(cfg); err != nil {
|
||||
logx.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if opts.Core.PID.Path != "" {
|
||||
gorush.PushConf.Core.PID.Path = opts.Core.PID.Path
|
||||
gorush.PushConf.Core.PID.Enabled = true
|
||||
gorush.PushConf.Core.PID.Override = true
|
||||
cfg.Core.PID.Path = opts.Core.PID.Path
|
||||
cfg.Core.PID.Enabled = true
|
||||
cfg.Core.PID.Override = true
|
||||
}
|
||||
|
||||
if err = createPIDFile(); err != nil {
|
||||
if err = createPIDFile(cfg); err != nil {
|
||||
logx.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if err = status.InitAppStatus(gorush.PushConf); err != nil {
|
||||
if err = status.InitAppStatus(cfg); err != nil {
|
||||
logx.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
q := queue.NewQueue(cfg)
|
||||
q.Start()
|
||||
|
||||
finished := make(chan struct{})
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(int(gorush.PushConf.Core.WorkerNum))
|
||||
ctx := withContextFunc(context.Background(), func() {
|
||||
logx.LogAccess.Info("close the notification queue channel, current queue len: ", len(gorush.QueueNotification))
|
||||
close(gorush.QueueNotification)
|
||||
wg.Wait()
|
||||
logx.LogAccess.Info("the notification queue has been clear")
|
||||
logx.LogAccess.Info("close the queue system, current queue usage: ", q.Usage())
|
||||
// stop queue system
|
||||
q.Stop()
|
||||
// wait job completed
|
||||
q.Wait()
|
||||
close(finished)
|
||||
// close the connection with storage
|
||||
logx.LogAccess.Info("close the storage connection: ", gorush.PushConf.Stat.Engine)
|
||||
logx.LogAccess.Info("close the storage connection: ", cfg.Stat.Engine)
|
||||
if err := status.StatStorage.Close(); err != nil {
|
||||
logx.LogError.Fatal("can't close the storage connection: ", err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
gorush.InitWorkers(ctx, wg, gorush.PushConf.Core.WorkerNum, gorush.PushConf.Core.QueueNum)
|
||||
// gorush.InitQueue(cfg.Core.WorkerNum, cfg.Core.QueueNum)
|
||||
// gorush.InitWorkers(ctx, wg, cfg.Core.WorkerNum, cfg.Core.QueueNum)
|
||||
|
||||
if gorush.PushConf.Ios.Enabled {
|
||||
if err = gorush.InitAPNSClient(); err != nil {
|
||||
if cfg.Ios.Enabled {
|
||||
if err = gorush.InitAPNSClient(cfg); err != nil {
|
||||
logx.LogError.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if gorush.PushConf.Android.Enabled {
|
||||
if _, err = gorush.InitFCMClient(gorush.PushConf.Android.APIKey); err != nil {
|
||||
if cfg.Android.Enabled {
|
||||
if _, err = gorush.InitFCMClient(cfg, cfg.Android.APIKey); err != nil {
|
||||
logx.LogError.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if gorush.PushConf.Huawei.Enabled {
|
||||
if _, err = gorush.InitHMSClient(gorush.PushConf.Huawei.AppSecret, gorush.PushConf.Huawei.AppID); err != nil {
|
||||
if cfg.Huawei.Enabled {
|
||||
if _, err = gorush.InitHMSClient(cfg, cfg.Huawei.AppSecret, cfg.Huawei.AppID); err != nil {
|
||||
logx.LogError.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -354,12 +355,12 @@ func main() {
|
|||
|
||||
// Run httpd server
|
||||
g.Go(func() error {
|
||||
return router.RunHTTPServer(ctx, gorush.PushConf)
|
||||
return router.RunHTTPServer(ctx, cfg, q)
|
||||
})
|
||||
|
||||
// Run gRPC internal server
|
||||
g.Go(func() error {
|
||||
return rpc.RunGRPCServer(ctx)
|
||||
return rpc.RunGRPCServer(ctx, cfg)
|
||||
})
|
||||
|
||||
// check job completely
|
||||
|
@ -426,7 +427,7 @@ func usage() {
|
|||
|
||||
// handles pinging the endpoint and returns an error if the
|
||||
// agent is in an unhealthy state.
|
||||
func pinger() error {
|
||||
func pinger(cfg config.ConfYaml) error {
|
||||
transport := &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
|
@ -437,7 +438,7 @@ func pinger() error {
|
|||
Timeout: time.Second * 10,
|
||||
Transport: transport,
|
||||
}
|
||||
resp, err := client.Get("http://localhost:" + gorush.PushConf.Core.Port + gorush.PushConf.API.HealthURI)
|
||||
resp, err := client.Get("http://localhost:" + cfg.Core.Port + cfg.API.HealthURI)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -448,14 +449,14 @@ func pinger() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func createPIDFile() error {
|
||||
if !gorush.PushConf.Core.PID.Enabled {
|
||||
func createPIDFile(cfg config.ConfYaml) error {
|
||||
if !cfg.Core.PID.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
pidPath := gorush.PushConf.Core.PID.Path
|
||||
pidPath := cfg.Core.PID.Path
|
||||
_, err := os.Stat(pidPath)
|
||||
if os.IsNotExist(err) || gorush.PushConf.Core.PID.Override {
|
||||
if os.IsNotExist(err) || cfg.Core.PID.Override {
|
||||
currentPid := os.Getpid()
|
||||
if err := os.MkdirAll(filepath.Dir(pidPath), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Can't create PID folder on %v", err)
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package queue
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/queue/simple"
|
||||
)
|
||||
|
||||
type (
|
||||
// A Queue is a message queue.
|
||||
Queue struct {
|
||||
workerCount int
|
||||
queueCount int
|
||||
routineGroup *routineGroup
|
||||
quit chan struct{}
|
||||
worker Worker
|
||||
}
|
||||
)
|
||||
|
||||
// NewQueue returns a Queue.
|
||||
func NewQueue(cfg config.ConfYaml) *Queue {
|
||||
q := &Queue{
|
||||
workerCount: int(cfg.Core.WorkerNum),
|
||||
queueCount: int(cfg.Core.QueueNum),
|
||||
routineGroup: newRoutineGroup(),
|
||||
quit: make(chan struct{}),
|
||||
worker: simple.NewWorker(cfg),
|
||||
}
|
||||
|
||||
if q.workerCount != 0 {
|
||||
q.workerCount = runtime.NumCPU()
|
||||
}
|
||||
|
||||
if q.queueCount == 0 {
|
||||
q.queueCount = runtime.NumCPU() << 1
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
// Capacity for queue max size
|
||||
func (q *Queue) Capacity() int {
|
||||
return q.worker.Capacity()
|
||||
}
|
||||
|
||||
// Usage for count of queue usage
|
||||
func (q *Queue) Usage() int {
|
||||
return q.worker.Usage()
|
||||
}
|
||||
|
||||
// Config update current config
|
||||
func (q *Queue) Config(cfg config.ConfYaml) {
|
||||
q.worker.Config(cfg)
|
||||
}
|
||||
|
||||
// Start to enable all worker
|
||||
func (q *Queue) Start() {
|
||||
q.startWorker()
|
||||
}
|
||||
|
||||
// Stop stops q.
|
||||
func (q *Queue) Stop() {
|
||||
q.worker.Stop()
|
||||
close(q.quit)
|
||||
}
|
||||
|
||||
// Wait all process
|
||||
func (q *Queue) Wait() {
|
||||
q.routineGroup.Wait()
|
||||
}
|
||||
|
||||
// Enqueue queue all job
|
||||
func (q *Queue) Enqueue(job interface{}) error {
|
||||
return q.worker.Enqueue(job)
|
||||
}
|
||||
|
||||
func (q *Queue) startWorker() {
|
||||
for i := 0; i < q.workerCount; i++ {
|
||||
go func(num int) {
|
||||
q.routineGroup.Run(func() {
|
||||
logx.LogAccess.Info("started the worker num ", num)
|
||||
q.worker.Run(q.quit)
|
||||
logx.LogAccess.Info("closed the worker num ", num)
|
||||
})
|
||||
}(i)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package simple
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/gorush"
|
||||
)
|
||||
|
||||
// Worker for simple queue using channel
|
||||
type Worker struct {
|
||||
cfg config.ConfYaml
|
||||
queueNotification chan gorush.PushNotification
|
||||
}
|
||||
|
||||
// Run start the worker
|
||||
func (s *Worker) Run(_ chan struct{}) {
|
||||
for notification := range s.queueNotification {
|
||||
gorush.SendNotification(s.cfg, notification)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop worker
|
||||
func (s *Worker) Stop() {
|
||||
close(s.queueNotification)
|
||||
}
|
||||
|
||||
// Capacity for channel
|
||||
func (s *Worker) Capacity() int {
|
||||
return cap(s.queueNotification)
|
||||
}
|
||||
|
||||
// Usage for count of channel usage
|
||||
func (s *Worker) Usage() int {
|
||||
return len(s.queueNotification)
|
||||
}
|
||||
|
||||
// Enqueue send notification to queue
|
||||
func (s *Worker) Enqueue(job interface{}) error {
|
||||
select {
|
||||
case s.queueNotification <- job.(gorush.PushNotification):
|
||||
return nil
|
||||
default:
|
||||
return errors.New("max capacity reached")
|
||||
}
|
||||
}
|
||||
|
||||
// Config update current config
|
||||
func (s *Worker) Config(cfg config.ConfYaml) {
|
||||
s.cfg = cfg
|
||||
}
|
||||
|
||||
// NewWorker for struct
|
||||
func NewWorker(cfg config.ConfYaml) *Worker {
|
||||
return &Worker{
|
||||
cfg: cfg,
|
||||
queueNotification: make(chan gorush.PushNotification, cfg.Core.QueueNum),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package queue
|
||||
|
||||
import "sync"
|
||||
|
||||
type routineGroup struct {
|
||||
waitGroup sync.WaitGroup
|
||||
}
|
||||
|
||||
func newRoutineGroup() *routineGroup {
|
||||
return new(routineGroup)
|
||||
}
|
||||
|
||||
func (g *routineGroup) Run(fn func()) {
|
||||
g.waitGroup.Add(1)
|
||||
|
||||
go func() {
|
||||
defer g.waitGroup.Done()
|
||||
fn()
|
||||
}()
|
||||
}
|
||||
|
||||
func (g *routineGroup) Wait() {
|
||||
g.waitGroup.Wait()
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package queue
|
||||
|
||||
import "github.com/appleboy/gorush/config"
|
||||
|
||||
// Worker interface
|
||||
type Worker interface {
|
||||
Run(chan struct{})
|
||||
Stop()
|
||||
Enqueue(job interface{}) error
|
||||
Capacity() int
|
||||
Usage() int
|
||||
Config(config.ConfYaml)
|
||||
}
|
134
router/server.go
134
router/server.go
|
@ -3,14 +3,18 @@ package router
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/gorush"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/metric"
|
||||
"github.com/appleboy/gorush/queue"
|
||||
"github.com/appleboy/gorush/status"
|
||||
|
||||
api "github.com/appleboy/gin-status-api"
|
||||
|
@ -26,14 +30,12 @@ import (
|
|||
"golang.org/x/crypto/acme/autocert"
|
||||
)
|
||||
|
||||
var isTerm bool
|
||||
var (
|
||||
isTerm bool
|
||||
doOnce sync.Once
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Support metrics
|
||||
m := metric.NewMetrics(func() int {
|
||||
return len(gorush.QueueNotification)
|
||||
})
|
||||
prometheus.MustRegister(m)
|
||||
isTerm = isatty.IsTerminal(os.Stdout.Fd())
|
||||
}
|
||||
|
||||
|
@ -61,7 +63,7 @@ func versionHandler(c *gin.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
func pushHandler(cfg config.ConfYaml) gin.HandlerFunc {
|
||||
func pushHandler(cfg config.ConfYaml, q *queue.Queue) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var form gorush.RequestPush
|
||||
var msg string
|
||||
|
@ -101,7 +103,7 @@ func pushHandler(cfg config.ConfYaml) gin.HandlerFunc {
|
|||
}
|
||||
}()
|
||||
|
||||
counts, logs := gorush.HandleNotification(ctx, form)
|
||||
counts, logs := handleNotification(ctx, cfg, form, q)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": "ok",
|
||||
|
@ -121,21 +123,23 @@ func metricsHandler(c *gin.Context) {
|
|||
promhttp.Handler().ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
|
||||
func appStatusHandler(c *gin.Context) {
|
||||
result := status.App{}
|
||||
func appStatusHandler(q *queue.Queue) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
result := status.App{}
|
||||
|
||||
result.Version = GetVersion()
|
||||
result.QueueMax = cap(gorush.QueueNotification)
|
||||
result.QueueUsage = len(gorush.QueueNotification)
|
||||
result.TotalCount = status.StatStorage.GetTotalCount()
|
||||
result.Ios.PushSuccess = status.StatStorage.GetIosSuccess()
|
||||
result.Ios.PushError = status.StatStorage.GetIosError()
|
||||
result.Android.PushSuccess = status.StatStorage.GetAndroidSuccess()
|
||||
result.Android.PushError = status.StatStorage.GetAndroidError()
|
||||
result.Huawei.PushSuccess = status.StatStorage.GetHuaweiSuccess()
|
||||
result.Huawei.PushError = status.StatStorage.GetHuaweiError()
|
||||
result.Version = GetVersion()
|
||||
result.QueueMax = q.Capacity()
|
||||
result.QueueUsage = q.Usage()
|
||||
result.TotalCount = status.StatStorage.GetTotalCount()
|
||||
result.Ios.PushSuccess = status.StatStorage.GetIosSuccess()
|
||||
result.Ios.PushError = status.StatStorage.GetIosError()
|
||||
result.Android.PushSuccess = status.StatStorage.GetAndroidSuccess()
|
||||
result.Android.PushError = status.StatStorage.GetAndroidError()
|
||||
result.Huawei.PushSuccess = status.StatStorage.GetHuaweiSuccess()
|
||||
result.Huawei.PushError = status.StatStorage.GetHuaweiError()
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
}
|
||||
|
||||
func sysStatsHandler() gin.HandlerFunc {
|
||||
|
@ -153,7 +157,7 @@ func StatMiddleware() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func autoTLSServer(cfg config.ConfYaml) *http.Server {
|
||||
func autoTLSServer(cfg config.ConfYaml, q *queue.Queue) *http.Server {
|
||||
m := autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
HostPolicy: autocert.HostWhitelist(cfg.Core.AutoTLS.Host),
|
||||
|
@ -163,11 +167,11 @@ func autoTLSServer(cfg config.ConfYaml) *http.Server {
|
|||
return &http.Server{
|
||||
Addr: ":https",
|
||||
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
||||
Handler: routerEngine(cfg),
|
||||
Handler: routerEngine(cfg, q),
|
||||
}
|
||||
}
|
||||
|
||||
func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
||||
func routerEngine(cfg config.ConfYaml, q *queue.Queue) *gin.Engine {
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
if cfg.Core.Mode == "debug" {
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
|
@ -184,6 +188,14 @@ func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
|||
)
|
||||
}
|
||||
|
||||
// Support metrics
|
||||
doOnce.Do(func() {
|
||||
m := metric.NewMetrics(func() int {
|
||||
return q.Usage()
|
||||
})
|
||||
prometheus.MustRegister(m)
|
||||
})
|
||||
|
||||
// set server mode
|
||||
gin.SetMode(cfg.Core.Mode)
|
||||
|
||||
|
@ -202,10 +214,10 @@ func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
|||
r.Use(StatMiddleware())
|
||||
|
||||
r.GET(cfg.API.StatGoURI, api.GinHandler)
|
||||
r.GET(cfg.API.StatAppURI, appStatusHandler)
|
||||
r.GET(cfg.API.StatAppURI, appStatusHandler(q))
|
||||
r.GET(cfg.API.ConfigURI, configHandler(cfg))
|
||||
r.GET(cfg.API.SysStatURI, sysStatsHandler())
|
||||
r.POST(cfg.API.PushURI, pushHandler(cfg))
|
||||
r.POST(cfg.API.PushURI, pushHandler(cfg, q))
|
||||
r.GET(cfg.API.MetricURI, metricsHandler)
|
||||
r.GET(cfg.API.HealthURI, heartbeatHandler)
|
||||
r.HEAD(cfg.API.HealthURI, heartbeatHandler)
|
||||
|
@ -214,3 +226,73 @@ func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
|||
|
||||
return r
|
||||
}
|
||||
|
||||
// markFailedNotification adds failure logs for all tokens in push notification
|
||||
func markFailedNotification(cfg config.ConfYaml, notification *gorush.PushNotification, reason string) {
|
||||
logx.LogError.Error(reason)
|
||||
for _, token := range notification.Tokens {
|
||||
notification.AddLog(logx.GetLogPushEntry(&logx.InputLog{
|
||||
ID: notification.ID,
|
||||
Status: core.FailedPush,
|
||||
Token: token,
|
||||
Message: notification.Message,
|
||||
Platform: notification.Platform,
|
||||
Error: errors.New(reason),
|
||||
HideToken: cfg.Log.HideToken,
|
||||
Format: cfg.Log.Format,
|
||||
}))
|
||||
}
|
||||
notification.WaitDone()
|
||||
}
|
||||
|
||||
// HandleNotification add notification to queue list.
|
||||
func handleNotification(ctx context.Context, cfg config.ConfYaml, req gorush.RequestPush, q *queue.Queue) (int, []logx.LogPushEntry) {
|
||||
var count int
|
||||
wg := sync.WaitGroup{}
|
||||
newNotification := []*gorush.PushNotification{}
|
||||
for i := range req.Notifications {
|
||||
notification := &req.Notifications[i]
|
||||
switch notification.Platform {
|
||||
case core.PlatFormIos:
|
||||
if !cfg.Ios.Enabled {
|
||||
continue
|
||||
}
|
||||
case core.PlatFormAndroid:
|
||||
if !cfg.Android.Enabled {
|
||||
continue
|
||||
}
|
||||
case core.PlatFormHuawei:
|
||||
if !cfg.Huawei.Enabled {
|
||||
continue
|
||||
}
|
||||
}
|
||||
newNotification = append(newNotification, notification)
|
||||
}
|
||||
|
||||
log := make([]logx.LogPushEntry, 0, count)
|
||||
for _, notification := range newNotification {
|
||||
if cfg.Core.Sync {
|
||||
notification.Wg = &wg
|
||||
notification.Log = &log
|
||||
notification.AddWaitCount()
|
||||
}
|
||||
|
||||
if err := q.Enqueue(*notification); err != nil {
|
||||
markFailedNotification(cfg, notification, "max capacity reached")
|
||||
}
|
||||
|
||||
count += len(notification.Tokens)
|
||||
// Count topic message
|
||||
if notification.To != "" {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Core.Sync {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
status.StatStorage.AddTotalCount(int64(count))
|
||||
|
||||
return count, log
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/queue"
|
||||
|
||||
"github.com/apex/gateway"
|
||||
)
|
||||
|
||||
// RunHTTPServer provide run http or https protocol.
|
||||
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server) (err error) {
|
||||
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, q *queue.Queue, s ...*http.Server) (err error) {
|
||||
if !cfg.Core.Enabled {
|
||||
logx.LogAccess.Debug("httpd server is disabled.")
|
||||
return nil
|
||||
|
@ -21,5 +22,5 @@ func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server)
|
|||
|
||||
logx.LogAccess.Info("HTTPD server is running on " + cfg.Core.Port + " port.")
|
||||
|
||||
return gateway.ListenAndServe(cfg.Core.Address+":"+cfg.Core.Port, routerEngine(cfg))
|
||||
return gateway.ListenAndServe(cfg.Core.Address+":"+cfg.Core.Port, routerEngine(cfg, q))
|
||||
}
|
||||
|
|
|
@ -12,12 +12,13 @@ import (
|
|||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/queue"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// RunHTTPServer provide run http or https protocol.
|
||||
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server) (err error) {
|
||||
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, q *queue.Queue, s ...*http.Server) (err error) {
|
||||
var server *http.Server
|
||||
|
||||
if !cfg.Core.Enabled {
|
||||
|
@ -28,7 +29,7 @@ func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server)
|
|||
if len(s) == 0 {
|
||||
server = &http.Server{
|
||||
Addr: cfg.Core.Address + ":" + cfg.Core.Port,
|
||||
Handler: routerEngine(cfg),
|
||||
Handler: routerEngine(cfg, q),
|
||||
}
|
||||
} else {
|
||||
server = s[0]
|
||||
|
@ -36,7 +37,7 @@ func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server)
|
|||
|
||||
logx.LogAccess.Info("HTTPD server is running on " + cfg.Core.Port + " port.")
|
||||
if cfg.Core.AutoTLS.Enabled {
|
||||
return startServer(ctx, autoTLSServer(cfg), cfg)
|
||||
return startServer(ctx, autoTLSServer(cfg, q), cfg)
|
||||
} else if cfg.Core.SSL {
|
||||
config := &tls.Config{
|
||||
MinVersion: tls.VersionTLS10,
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/gorush"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
"github.com/appleboy/gorush/queue"
|
||||
"github.com/appleboy/gorush/status"
|
||||
|
||||
"github.com/appleboy/gofight/v2"
|
||||
|
@ -23,7 +24,10 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var goVersion = runtime.Version()
|
||||
var (
|
||||
goVersion = runtime.Version()
|
||||
q *queue.Queue
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
cfg := initTest()
|
||||
|
@ -40,11 +44,14 @@ func TestMain(m *testing.M) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
q = queue.NewQueue(cfg)
|
||||
q.Start()
|
||||
defer q.Stop()
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func initTest() config.ConfYaml {
|
||||
cfg, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Core.Mode = "test"
|
||||
return cfg
|
||||
}
|
||||
|
@ -88,7 +95,7 @@ func TestRunNormalServer(t *testing.T) {
|
|||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
|
@ -112,7 +119,7 @@ func TestRunTLSServer(t *testing.T) {
|
|||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
|
@ -140,7 +147,7 @@ func TestRunTLSBase64Server(t *testing.T) {
|
|||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
|
@ -159,7 +166,7 @@ func TestRunAutoTLSServer(t *testing.T) {
|
|||
cfg.Core.AutoTLS.Enabled = true
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
||||
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
|
@ -179,7 +186,7 @@ func TestLoadTLSCertError(t *testing.T) {
|
|||
cfg.Core.CertPath = "../config/config.yml"
|
||||
cfg.Core.KeyPath = "../config/config.yml"
|
||||
|
||||
assert.Error(t, RunHTTPServer(context.Background(), cfg))
|
||||
assert.Error(t, RunHTTPServer(context.Background(), cfg, q))
|
||||
}
|
||||
|
||||
func TestMissingTLSCertcfgg(t *testing.T) {
|
||||
|
@ -192,8 +199,8 @@ func TestMissingTLSCertcfgg(t *testing.T) {
|
|||
cfg.Core.CertBase64 = ""
|
||||
cfg.Core.KeyBase64 = ""
|
||||
|
||||
err := RunHTTPServer(context.Background(), cfg)
|
||||
assert.Error(t, RunHTTPServer(context.Background(), cfg))
|
||||
err := RunHTTPServer(context.Background(), cfg, q)
|
||||
assert.Error(t, RunHTTPServer(context.Background(), cfg, q))
|
||||
assert.Equal(t, "missing https cert config", err.Error())
|
||||
}
|
||||
|
||||
|
@ -206,7 +213,7 @@ func TestRootHandler(t *testing.T) {
|
|||
cfg.Log.Format = "json"
|
||||
|
||||
r.GET("/").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
data := r.Body.Bytes()
|
||||
|
||||
value, _ := jsonparser.GetString(data, "text")
|
||||
|
@ -223,7 +230,7 @@ func TestAPIStatusGoHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.GET("/api/stat/go").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
data := r.Body.Bytes()
|
||||
|
||||
value, _ := jsonparser.GetString(data, "go_version")
|
||||
|
@ -242,7 +249,7 @@ func TestAPIStatusAppHandler(t *testing.T) {
|
|||
SetVersion(appVersion)
|
||||
|
||||
r.GET("/api/stat/app").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
data := r.Body.Bytes()
|
||||
|
||||
value, _ := jsonparser.GetString(data, "version")
|
||||
|
@ -258,7 +265,7 @@ func TestAPIConfigHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.GET("/api/config").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusCreated, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -270,7 +277,7 @@ func TestMissingNotificationsParameter(t *testing.T) {
|
|||
|
||||
// missing notifications parameter.
|
||||
r.POST("/api/push").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||
assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
|
||||
})
|
||||
|
@ -286,7 +293,7 @@ func TestEmptyNotifications(t *testing.T) {
|
|||
SetJSON(gofight.D{
|
||||
"notifications": []gorush.PushNotification{},
|
||||
}).
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -314,8 +321,8 @@ func TestMutableContent(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}).
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
// json: cannot unmarshal number into Go struct field PushNotification.mutable_content of type bool
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
// json: cannot unmarshal number into Go struct field gorush.PushNotification.mutable_content of type bool
|
||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -343,7 +350,7 @@ func TestOutOfRangeMaxNotifications(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}).
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -369,7 +376,7 @@ func TestSuccessPushHandler(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}).
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusOK, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -380,7 +387,7 @@ func TestSysStatsHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.GET("/sys/stats").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusOK, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -391,7 +398,7 @@ func TestMetricsHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.GET("/metrics").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusOK, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -402,7 +409,7 @@ func TestGETHeartbeatHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.GET("/healthz").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusOK, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -413,7 +420,7 @@ func TestHEADHeartbeatHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.HEAD("/healthz").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusOK, r.Code)
|
||||
})
|
||||
}
|
||||
|
@ -425,7 +432,7 @@ func TestVersionHandler(t *testing.T) {
|
|||
r := gofight.New()
|
||||
|
||||
r.GET("/version").
|
||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||
assert.Equal(t, http.StatusOK, r.Code)
|
||||
data := r.Body.Bytes()
|
||||
|
||||
|
@ -438,8 +445,231 @@ func TestVersionHandler(t *testing.T) {
|
|||
func TestDisabledHTTPServer(t *testing.T) {
|
||||
cfg := initTest()
|
||||
cfg.Core.Enabled = false
|
||||
err := RunHTTPServer(context.Background(), cfg)
|
||||
err := RunHTTPServer(context.Background(), cfg, q)
|
||||
cfg.Core.Enabled = true
|
||||
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestSenMultipleNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := initTest()
|
||||
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := gorush.InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
q.Config(cfg)
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := gorush.RequestPush{
|
||||
Notifications: []gorush.PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, "bbbbb"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := handleNotification(ctx, cfg, req, q)
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Equal(t, 0, len(logs))
|
||||
}
|
||||
|
||||
func TestDisabledAndroidNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := initTest()
|
||||
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := gorush.InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cfg.Android.Enabled = false
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
q.Config(cfg)
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := gorush.RequestPush{
|
||||
Notifications: []gorush.PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, "bbbbb"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := handleNotification(ctx, cfg, req, q)
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Equal(t, 0, len(logs))
|
||||
}
|
||||
|
||||
func TestSyncModeForNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := initTest()
|
||||
|
||||
cfg.Ios.Enabled = true
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := gorush.InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
|
||||
// enable sync mode
|
||||
cfg.Core.Sync = true
|
||||
q.Config(cfg)
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := gorush.RequestPush{
|
||||
Notifications: []gorush.PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, "bbbbb"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := handleNotification(ctx, cfg, req, q)
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Equal(t, 2, len(logs))
|
||||
}
|
||||
|
||||
func TestSyncModeForTopicNotification(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := initTest()
|
||||
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Log.HideToken = false
|
||||
|
||||
// enable sync mode
|
||||
cfg.Core.Sync = true
|
||||
q.Config(cfg)
|
||||
|
||||
req := gorush.RequestPush{
|
||||
Notifications: []gorush.PushNotification{
|
||||
// android
|
||||
{
|
||||
// error:InvalidParameters
|
||||
// Check that the provided parameters have the right name and type.
|
||||
To: "/topics/foo-bar@@@##",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||
},
|
||||
// android
|
||||
{
|
||||
// success
|
||||
To: "/topics/foo-bar",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||
},
|
||||
// android
|
||||
{
|
||||
// success
|
||||
Condition: "'dogs' in topics || 'cats' in topics",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := handleNotification(ctx, cfg, req, q)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Equal(t, 1, len(logs))
|
||||
}
|
||||
|
||||
func TestSyncModeForDeviceGroupNotification(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := initTest()
|
||||
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
cfg.Log.HideToken = false
|
||||
|
||||
// enable sync mode
|
||||
cfg.Core.Sync = true
|
||||
q.Config(cfg)
|
||||
|
||||
req := gorush.RequestPush{
|
||||
Notifications: []gorush.PushNotification{
|
||||
// android
|
||||
{
|
||||
To: "aUniqueKey",
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "This is a Firebase Cloud Messaging Device Group Message!",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := handleNotification(ctx, cfg, req, q)
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Equal(t, 1, len(logs))
|
||||
}
|
||||
|
||||
func TestDisabledIosNotifications(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := initTest()
|
||||
|
||||
cfg.Ios.Enabled = false
|
||||
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||
err := gorush.InitAPNSClient(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cfg.Android.Enabled = true
|
||||
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||
q.Config(cfg)
|
||||
|
||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||
|
||||
req := gorush.RequestPush{
|
||||
Notifications: []gorush.PushNotification{
|
||||
// ios
|
||||
{
|
||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||
Platform: core.PlatFormIos,
|
||||
Message: "Welcome",
|
||||
},
|
||||
// android
|
||||
{
|
||||
Tokens: []string{androidToken, androidToken + "_"},
|
||||
Platform: core.PlatFormAndroid,
|
||||
Message: "Welcome",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count, logs := handleNotification(ctx, cfg, req, q)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Equal(t, 0, len(logs))
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
"github.com/appleboy/gorush/gorush"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
|
@ -19,14 +20,16 @@ import (
|
|||
|
||||
// Server is used to implement gorush grpc server.
|
||||
type Server struct {
|
||||
mu sync.Mutex
|
||||
cfg config.ConfYaml
|
||||
mu sync.Mutex
|
||||
// statusMap stores the serving status of the services this Server monitors.
|
||||
statusMap map[string]proto.HealthCheckResponse_ServingStatus
|
||||
}
|
||||
|
||||
// NewServer returns a new Server.
|
||||
func NewServer() *Server {
|
||||
func NewServer(cfg config.ConfYaml) *Server {
|
||||
return &Server{
|
||||
cfg: cfg,
|
||||
statusMap: make(map[string]proto.HealthCheckResponse_ServingStatus),
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +101,7 @@ func (s *Server) Send(ctx context.Context, in *proto.NotificationRequest) (*prot
|
|||
}
|
||||
}
|
||||
|
||||
go gorush.SendNotification(ctx, notification)
|
||||
go gorush.SendNotification(s.cfg, notification)
|
||||
|
||||
return &proto.NotificationReply{
|
||||
Success: true,
|
||||
|
@ -107,26 +110,26 @@ func (s *Server) Send(ctx context.Context, in *proto.NotificationRequest) (*prot
|
|||
}
|
||||
|
||||
// RunGRPCServer run gorush grpc server
|
||||
func RunGRPCServer(ctx context.Context) error {
|
||||
if !gorush.PushConf.GRPC.Enabled {
|
||||
func RunGRPCServer(ctx context.Context, cfg config.ConfYaml) error {
|
||||
if !cfg.GRPC.Enabled {
|
||||
logx.LogAccess.Info("gRPC server is disabled.")
|
||||
return nil
|
||||
}
|
||||
|
||||
s := grpc.NewServer()
|
||||
rpcSrv := NewServer()
|
||||
rpcSrv := NewServer(cfg)
|
||||
proto.RegisterGorushServer(s, rpcSrv)
|
||||
proto.RegisterHealthServer(s, rpcSrv)
|
||||
|
||||
// Register reflection service on gRPC server.
|
||||
reflection.Register(s)
|
||||
|
||||
lis, err := net.Listen("tcp", ":"+gorush.PushConf.GRPC.Port)
|
||||
lis, err := net.Listen("tcp", ":"+cfg.GRPC.Port)
|
||||
if err != nil {
|
||||
logx.LogError.Fatalln(err)
|
||||
return err
|
||||
}
|
||||
logx.LogAccess.Info("gRPC server is running on " + gorush.PushConf.GRPC.Port + " port.")
|
||||
logx.LogAccess.Info("gRPC server is running on " + cfg.GRPC.Port + " port.")
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/appleboy/gorush/gorush"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/logx"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
@ -13,22 +13,29 @@ import (
|
|||
|
||||
const gRPCAddr = "localhost:9000"
|
||||
|
||||
func initTest() config.ConfYaml {
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Core.Mode = "test"
|
||||
return cfg
|
||||
}
|
||||
|
||||
func TestGracefulShutDownGRPCServer(t *testing.T) {
|
||||
cfg := initTest()
|
||||
// server configs
|
||||
logx.InitLog(
|
||||
gorush.PushConf.Log.AccessLevel,
|
||||
gorush.PushConf.Log.AccessLog,
|
||||
gorush.PushConf.Log.ErrorLevel,
|
||||
gorush.PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
)
|
||||
gorush.PushConf.GRPC.Enabled = true
|
||||
gorush.PushConf.GRPC.Port = "9000"
|
||||
gorush.PushConf.Log.Format = "json"
|
||||
cfg.GRPC.Enabled = true
|
||||
cfg.GRPC.Port = "9000"
|
||||
cfg.Log.Format = "json"
|
||||
|
||||
// Run gRPC server
|
||||
ctx, gRPCContextCancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
if err := RunGRPCServer(ctx); err != nil {
|
||||
if err := RunGRPCServer(ctx, cfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -12,12 +12,12 @@ import (
|
|||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
if err := logx.InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
cfg.Log.AccessLevel,
|
||||
cfg.Log.AccessLog,
|
||||
cfg.Log.ErrorLevel,
|
||||
cfg.Log.ErrorLog,
|
||||
); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
func TestStorageDriverExist(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
PushConf.Stat.Engine = "Test"
|
||||
err := InitAppStatus(PushConf)
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Engine = "Test"
|
||||
err := InitAppStatus(cfg)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ func TestStatForMemoryEngine(t *testing.T) {
|
|||
time.Sleep(5 * time.Second)
|
||||
|
||||
var val int64
|
||||
PushConf, _ := config.LoadConf("")
|
||||
PushConf.Stat.Engine = "memory"
|
||||
err := InitAppStatus(PushConf)
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Engine = "memory"
|
||||
err := InitAppStatus(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
StatStorage.AddTotalCount(100)
|
||||
|
@ -61,31 +61,31 @@ func TestStatForMemoryEngine(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRedisServerSuccess(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
PushConf.Stat.Engine = "redis"
|
||||
PushConf.Stat.Redis.Addr = "redis:6379"
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Engine = "redis"
|
||||
cfg.Stat.Redis.Addr = "redis:6379"
|
||||
|
||||
err := InitAppStatus(PushConf)
|
||||
err := InitAppStatus(cfg)
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRedisServerError(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
PushConf.Stat.Engine = "redis"
|
||||
PushConf.Stat.Redis.Addr = "redis:6370"
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Engine = "redis"
|
||||
cfg.Stat.Redis.Addr = "redis:6370"
|
||||
|
||||
err := InitAppStatus(PushConf)
|
||||
err := InitAppStatus(cfg)
|
||||
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestStatForRedisEngine(t *testing.T) {
|
||||
var val int64
|
||||
PushConf, _ := config.LoadConf("")
|
||||
PushConf.Stat.Engine = "redis"
|
||||
PushConf.Stat.Redis.Addr = "redis:6379"
|
||||
err := InitAppStatus(PushConf)
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Engine = "redis"
|
||||
cfg.Stat.Redis.Addr = "redis:6379"
|
||||
err := InitAppStatus(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
StatStorage.Init()
|
||||
|
@ -112,8 +112,8 @@ func TestStatForRedisEngine(t *testing.T) {
|
|||
func TestDefaultEngine(t *testing.T) {
|
||||
var val int64
|
||||
// defaul engine as memory
|
||||
PushConf, _ := config.LoadConf("")
|
||||
err := InitAppStatus(PushConf)
|
||||
cfg, _ := config.LoadConf()
|
||||
err := InitAppStatus(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
StatStorage.Reset()
|
||||
|
@ -138,9 +138,9 @@ func TestDefaultEngine(t *testing.T) {
|
|||
|
||||
func TestStatForBoltDBEngine(t *testing.T) {
|
||||
var val int64
|
||||
PushConf, _ := config.LoadConf("")
|
||||
PushConf.Stat.Engine = "boltdb"
|
||||
err := InitAppStatus(PushConf)
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Engine = "boltdb"
|
||||
err := InitAppStatus(cfg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
StatStorage.Reset()
|
||||
|
@ -165,7 +165,7 @@ func TestStatForBoltDBEngine(t *testing.T) {
|
|||
|
||||
// func TestStatForBuntDBEngine(t *testing.T) {
|
||||
// var val int64
|
||||
// PushConf.Stat.Engine = "buntdb"
|
||||
// cfg.Stat.Engine = "buntdb"
|
||||
// err := InitAppStatus()
|
||||
// assert.Nil(t, err)
|
||||
|
||||
|
@ -191,7 +191,7 @@ func TestStatForBoltDBEngine(t *testing.T) {
|
|||
|
||||
// func TestStatForLevelDBEngine(t *testing.T) {
|
||||
// var val int64
|
||||
// PushConf.Stat.Engine = "leveldb"
|
||||
// cfg.Stat.Engine = "leveldb"
|
||||
// err := InitAppStatus()
|
||||
// assert.Nil(t, err)
|
||||
|
||||
|
@ -217,7 +217,7 @@ func TestStatForBoltDBEngine(t *testing.T) {
|
|||
|
||||
// func TestStatForBadgerEngine(t *testing.T) {
|
||||
// var val int64
|
||||
// PushConf.Stat.Engine = "badger"
|
||||
// cfg.Stat.Engine = "badger"
|
||||
// err := InitAppStatus()
|
||||
// assert.Nil(t, err)
|
||||
|
||||
|
|
|
@ -3,16 +3,16 @@ package badger
|
|||
import (
|
||||
"testing"
|
||||
|
||||
c "github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBadgerEngine(t *testing.T) {
|
||||
var val int64
|
||||
|
||||
config, _ := c.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
badger := New(config)
|
||||
badger := New(cfg)
|
||||
err := badger.Init()
|
||||
assert.Nil(t, err)
|
||||
badger.Reset()
|
||||
|
|
|
@ -3,16 +3,16 @@ package boltdb
|
|||
import (
|
||||
"testing"
|
||||
|
||||
c "github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBoltDBEngine(t *testing.T) {
|
||||
var val int64
|
||||
|
||||
config, _ := c.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
boltDB := New(config)
|
||||
boltDB := New(cfg)
|
||||
err := boltDB.Init()
|
||||
assert.Nil(t, err)
|
||||
boltDB.Reset()
|
||||
|
|
|
@ -4,21 +4,21 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
c "github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBuntDBEngine(t *testing.T) {
|
||||
var val int64
|
||||
|
||||
config, _ := c.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
if _, err := os.Stat(config.Stat.BuntDB.Path); os.IsNotExist(err) {
|
||||
err := os.RemoveAll(config.Stat.BuntDB.Path)
|
||||
if _, err := os.Stat(cfg.Stat.BuntDB.Path); os.IsNotExist(err) {
|
||||
err := os.RemoveAll(cfg.Stat.BuntDB.Path)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
buntDB := New(config)
|
||||
buntDB := New(cfg)
|
||||
err := buntDB.Init()
|
||||
assert.Nil(t, err)
|
||||
buntDB.Reset()
|
||||
|
|
|
@ -4,21 +4,21 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
c "github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLevelDBEngine(t *testing.T) {
|
||||
var val int64
|
||||
|
||||
config, _ := c.LoadConf("")
|
||||
cfg, _ := config.LoadConf()
|
||||
|
||||
if _, err := os.Stat(config.Stat.LevelDB.Path); os.IsNotExist(err) {
|
||||
err = os.RemoveAll(config.Stat.LevelDB.Path)
|
||||
if _, err := os.Stat(cfg.Stat.LevelDB.Path); os.IsNotExist(err) {
|
||||
err = os.RemoveAll(cfg.Stat.LevelDB.Path)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
levelDB := New(config)
|
||||
levelDB := New(cfg)
|
||||
err := levelDB.Init()
|
||||
assert.Nil(t, err)
|
||||
levelDB.Reset()
|
||||
|
|
|
@ -4,15 +4,15 @@ import (
|
|||
"sync"
|
||||
"testing"
|
||||
|
||||
c "github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRedisServerError(t *testing.T) {
|
||||
config, _ := c.LoadConf("")
|
||||
config.Stat.Redis.Addr = "redis:6370"
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Redis.Addr = "redis:6370"
|
||||
|
||||
redis := New(config)
|
||||
redis := New(cfg)
|
||||
err := redis.Init()
|
||||
|
||||
assert.Error(t, err)
|
||||
|
@ -21,10 +21,10 @@ func TestRedisServerError(t *testing.T) {
|
|||
func TestRedisEngine(t *testing.T) {
|
||||
var val int64
|
||||
|
||||
config, _ := c.LoadConf("")
|
||||
config.Stat.Redis.Addr = "redis:6379"
|
||||
cfg, _ := config.LoadConf()
|
||||
cfg.Stat.Redis.Addr = "redis:6379"
|
||||
|
||||
redis := New(config)
|
||||
redis := New(cfg)
|
||||
err := redis.Init()
|
||||
assert.Nil(t, err)
|
||||
redis.Reset()
|
||||
|
|
Loading…
Reference in New Issue