fix: expire stale call pushes
This commit is contained in:
@@ -25,7 +25,7 @@ const (
|
||||
defaultAPIDomain = "https://api.jpush.cn"
|
||||
defaultPushPath = "/v3/push"
|
||||
defaultTTL = 86400
|
||||
defaultCallTTL = 60
|
||||
defaultCallTTL = 30
|
||||
)
|
||||
|
||||
var handler Handler
|
||||
@@ -327,6 +327,9 @@ func preparePayloads(rcpt *push.Receipt, config *configType) ([]*jpushPayload, [
|
||||
logs.Warn.Println("jpush: could not build payload:", err)
|
||||
return nil, nil
|
||||
}
|
||||
if pushExpired(data) {
|
||||
return nil, nil
|
||||
}
|
||||
useAlias := true
|
||||
if config.UseAlias != nil {
|
||||
useAlias = *config.UseAlias
|
||||
@@ -399,6 +402,9 @@ func pushData(pl push.Payload) (map[string]string, error) {
|
||||
}
|
||||
if pl.Webrtc != "" {
|
||||
data["webrtc"] = pl.Webrtc
|
||||
if pl.ExpiresAt != nil && !pl.ExpiresAt.IsZero() {
|
||||
data["expires_at"] = pl.ExpiresAt.UTC().Format(time.RFC3339Nano)
|
||||
}
|
||||
if callID := payloadContentString(pl.Content, "callId"); callID != "" {
|
||||
data["call_id"] = callID
|
||||
}
|
||||
@@ -437,11 +443,31 @@ func pushData(pl push.Payload) (map[string]string, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func pushExpired(data map[string]string) bool {
|
||||
expiresAt := data["expires_at"]
|
||||
if expiresAt == "" {
|
||||
return false
|
||||
}
|
||||
parsed, err := time.Parse(time.RFC3339Nano, expiresAt)
|
||||
return err == nil && !time.Now().UTC().Before(parsed)
|
||||
}
|
||||
|
||||
func buildPayload(audience map[string][]string, topic string, data map[string]string, unread int, config *configType) *jpushPayload {
|
||||
alert, title := alertText(data, config)
|
||||
ttl := config.DefaultTTLSeconds
|
||||
if data["type"] == "call_invite" {
|
||||
ttl = config.CallTTLSeconds
|
||||
if expiresAt := data["expires_at"]; expiresAt != "" {
|
||||
if parsed, err := time.Parse(time.RFC3339Nano, expiresAt); err == nil {
|
||||
remaining := int(time.Until(parsed).Seconds())
|
||||
if remaining < ttl {
|
||||
ttl = remaining
|
||||
}
|
||||
}
|
||||
}
|
||||
if ttl < 1 {
|
||||
ttl = 1
|
||||
}
|
||||
}
|
||||
payload := &jpushPayload{
|
||||
Platform: "all",
|
||||
|
||||
@@ -171,14 +171,16 @@ func TestPreparePayloadsDoesNotDropRecipientWithDeliveredSession(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBuildPayloadUsesShortTTLForCalls(t *testing.T) {
|
||||
expiresAt := time.Now().Add(30 * time.Second).UTC().Format(time.RFC3339Nano)
|
||||
config := &configType{Title: "MeetingIM", DefaultTTLSeconds: 86400, CallTTLSeconds: 60}
|
||||
payload := buildPayload(map[string][]string{"alias": {"usr1"}}, "p2pTopic", map[string]string{
|
||||
"type": "call_invite",
|
||||
"topic": "p2pTopic",
|
||||
"seq": "30",
|
||||
"call_type": "audio",
|
||||
"type": "call_invite",
|
||||
"topic": "p2pTopic",
|
||||
"seq": "30",
|
||||
"call_type": "audio",
|
||||
"expires_at": expiresAt,
|
||||
}, 0, config)
|
||||
if payload.Options.TimeToLive != 60 {
|
||||
if payload.Options.TimeToLive > 30 {
|
||||
t.Fatalf("unexpected ttl: %d", payload.Options.TimeToLive)
|
||||
}
|
||||
if payload.Notification.Android.Title != "语音通话" {
|
||||
@@ -187,12 +189,14 @@ func TestBuildPayloadUsesShortTTLForCalls(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPushDataExtractsCallFields(t *testing.T) {
|
||||
expiresAt := time.Date(2026, 9, 4, 10, 0, 30, 0, time.UTC)
|
||||
data, err := pushData(push.Payload{
|
||||
What: push.ActMsg,
|
||||
Topic: "p2pTopic",
|
||||
From: "usrCaller",
|
||||
SeqId: 30,
|
||||
Webrtc: "started",
|
||||
What: push.ActMsg,
|
||||
Topic: "p2pTopic",
|
||||
From: "usrCaller",
|
||||
SeqId: 30,
|
||||
Webrtc: "started",
|
||||
ExpiresAt: &expiresAt,
|
||||
Content: map[string]any{
|
||||
"callId": "call_1",
|
||||
"callType": "audio",
|
||||
@@ -205,6 +209,32 @@ func TestPushDataExtractsCallFields(t *testing.T) {
|
||||
if data["type"] != "call_invite" || data["call_id"] != "call_1" || data["call_type"] != "audio" || data["caller_id"] != "usrCaller" {
|
||||
t.Fatalf("unexpected call data: %#v", data)
|
||||
}
|
||||
if data["expires_at"] != expiresAt.Format(time.RFC3339Nano) {
|
||||
t.Fatalf("unexpected expires_at: %#v", data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparePayloadsDropsExpiredCallInvite(t *testing.T) {
|
||||
uid := types.Uid(42)
|
||||
expiresAt := time.Now().Add(-time.Second)
|
||||
config := &configType{Title: "MeetingIM", DefaultTTLSeconds: 86400, CallTTLSeconds: 30}
|
||||
payloads, uids := preparePayloads(&push.Receipt{
|
||||
TenantID: 7,
|
||||
To: map[types.Uid]push.Recipient{
|
||||
uid: {},
|
||||
},
|
||||
Payload: push.Payload{
|
||||
What: push.ActMsg,
|
||||
Topic: "p2pTopic",
|
||||
SeqId: 30,
|
||||
Webrtc: "started",
|
||||
ExpiresAt: &expiresAt,
|
||||
Timestamp: time.Now().Add(-time.Minute),
|
||||
},
|
||||
}, config)
|
||||
if len(payloads) != 0 || len(uids) != 0 {
|
||||
t.Fatalf("expired call invite should be dropped: payloads=%d uids=%#v", len(payloads), uids)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendPayloadUsesBasicAuth(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user