diff --git a/server/apns/apns.go b/server/apns/apns.go index 1722974f..6da9a841 100644 --- a/server/apns/apns.go +++ b/server/apns/apns.go @@ -2,12 +2,14 @@ package apns import ( "fmt" + "time" + log "github.com/Sirupsen/logrus" + "github.com/cosminrentea/gobbler/protocol" "github.com/cosminrentea/gobbler/server/connector" "github.com/cosminrentea/gobbler/server/metrics" "github.com/cosminrentea/gobbler/server/router" "github.com/sideshow/apns2" - "time" ) const ( @@ -93,6 +95,10 @@ func (a *apns) HandleResponse(request connector.Request, responseIface interface l := logger.WithField("correlation_id", request.Message().CorrelationID()) l.Info("Handle APNS response") if errSend != nil { + if errSend == protocol.ErrMessageExpired { + return nil + } + l.WithFields(log.Fields{ "error": errSend.Error(), "error_type": errSend, diff --git a/server/apns/apns_metrics.go b/server/apns/apns_metrics.go index 5483ec9c..f5ca7a3d 100644 --- a/server/apns/apns_metrics.go +++ b/server/apns/apns_metrics.go @@ -1,13 +1,15 @@ package apns import ( - "github.com/cosminrentea/gobbler/server/metrics" "time" + + "github.com/cosminrentea/gobbler/server/metrics" ) var ( ns = metrics.NS("apns") mTotalSentMessages = ns.NewInt("total_sent_messages") + mTotalExpiredMessages = ns.NewInt("total_expired_messages") mTotalSendErrors = ns.NewInt("total_sent_message_errors") mTotalResponseErrors = ns.NewInt("total_response_errors") mTotalResponseInternalErrors = ns.NewInt("total_response_internal_errors") diff --git a/server/apns/apns_prometheus.go b/server/apns/apns_prometheus.go index 633e55d2..b2d51915 100644 --- a/server/apns/apns_prometheus.go +++ b/server/apns/apns_prometheus.go @@ -10,6 +10,11 @@ var ( Help: "Number of messages sent to APNS", }) + pTotalExpiredMessages = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "apns_expired_messages", + Help: "Number of expired messages when trying to send to APNS", + }) + pSendErrors = prometheus.NewCounter(prometheus.CounterOpts{ Name: "apns_send_errors", Help: "Number of errors when trying to send messages to APNS", @@ -54,6 +59,7 @@ var ( func init() { prometheus.MustRegister( pSentMessages, + pTotalExpiredMessages, pSendErrors, pResponseErrors, pResponseInternalErrors, diff --git a/server/apns/apns_sender.go b/server/apns/apns_sender.go index ef465bca..2954a28a 100644 --- a/server/apns/apns_sender.go +++ b/server/apns/apns_sender.go @@ -2,11 +2,15 @@ package apns import ( "errors" + "net" + "time" + + log "github.com/Sirupsen/logrus" + + "github.com/cosminrentea/gobbler/protocol" "github.com/cosminrentea/gobbler/server/connector" "github.com/jpillora/backoff" "github.com/sideshow/apns2" - "net" - "time" ) const ( @@ -48,6 +52,18 @@ func (s sender) Send(request connector.Request) (interface{}, error) { l := logger.WithField("correlation_id", request.Message().CorrelationID()) deviceToken := request.Subscriber().Route().Get(deviceIDKey) l.WithField("deviceToken", deviceToken).Info("Trying to push a message to APNS") + + if m := request.Message(); m.IsExpired() { + l.WithFields(log.Fields{ + "ID": m.ID, + "Expires": time.Unix(m.Expires, 0).Format(time.RFC3339), + "Created": time.Unix(m.Time, 0).Format(time.RFC3339), + }).Info("Expired message received") + mTotalExpiredMessages.Add(1) + pTotalExpiredMessages.Inc() + return nil, protocol.ErrMessageExpired + } + push := func() (interface{}, error) { return s.client.Push(&apns2.Notification{ Priority: apns2.PriorityHigh, diff --git a/server/apns/apns_sender_test.go b/server/apns/apns_sender_test.go index 9d00577a..992292be 100644 --- a/server/apns/apns_sender_test.go +++ b/server/apns/apns_sender_test.go @@ -2,12 +2,14 @@ package apns import ( "errors" + "testing" + "time" + "github.com/cosminrentea/gobbler/protocol" "github.com/cosminrentea/gobbler/server/router" "github.com/cosminrentea/gobbler/testutil" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "testing" ) func TestNewSender_ErrorBytes(t *testing.T) { @@ -88,6 +90,47 @@ func TestSender_Send(t *testing.T) { a.Nil(rsp) } +func TestSender_SendExpiredMessage(t *testing.T) { + _, finish := testutil.NewMockCtrl(t) + defer finish() + a := assert.New(t) + + // given + routeParams := make(map[string]string) + routeParams["device_id"] = "1234" + routeConfig := router.RouteConfig{ + Path: protocol.Path("path"), + RouteParams: routeParams, + } + route := router.NewRoute(routeConfig) + + msg := &protocol.Message{ + Body: []byte("{}"), + Expires: time.Now().Add(-1 * time.Hour).Unix(), + } + + mSubscriber := NewMockSubscriber(testutil.MockCtrl) + mSubscriber.EXPECT().Route().Return(route).AnyTimes() + + mRequest := NewMockRequest(testutil.MockCtrl) + mRequest.EXPECT().Subscriber().Return(mSubscriber).AnyTimes() + mRequest.EXPECT().Message().Return(msg).AnyTimes() + + mPusher := NewMockPusher(testutil.MockCtrl) + + // and + s, err := NewSenderUsingPusher(mPusher, "com.myapp") + a.NoError(err) + + // when + rsp, err := s.Send(mRequest) + + // then + a.Error(err) + a.Equal(protocol.ErrMessageExpired, err) + a.Nil(rsp) +} + func TestSender_Retry(t *testing.T) { _, finish := testutil.NewMockCtrl(t) defer finish()