feat: add report material workflows and gateway safeguards

This commit is contained in:
hectorzhao
2026-07-15 18:23:48 +08:00
parent cf9f4ce4cd
commit 7091a8bed4
41 changed files with 3606 additions and 71 deletions
+52 -2
View File
@@ -10,10 +10,57 @@ import (
"time"
"cmpp-platform/gateway/internal/inbound"
"cmpp-platform/gateway/internal/queue"
)
type controlRecordingLimiter struct {
channelID string
rate int
configuredChannelID string
configuredRate int
}
func (l *controlRecordingLimiter) Wait(_ context.Context, channelID string, rate int) (time.Duration, error) {
l.channelID = channelID
l.rate = rate
return 0, nil
}
func (l *controlRecordingLimiter) Configure(_ context.Context, channelID string, rate int) error {
l.configuredChannelID = channelID
l.configuredRate = rate
return nil
}
func TestUpstreamSubmitUsesGatewayChannelLimiter(t *testing.T) {
limiter := &controlRecordingLimiter{}
handler := handlerWithServer(Server{
Limiter: limiter,
Submit: func(_ context.Context, command queue.SubmitCommand) (queue.SubmitResult, error) {
return queue.SubmitResult{Envelope: command.Envelope, SubmitStatus: "accepted"}, nil
},
})
resp := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/upstream/submit", strings.NewReader(`{
"schemaVersion":"v1","messageType":"SubmitCommand","messageId":"msg-1","channelId":"channel-1",
"submitId":"submit-1","tenantId":"tenant-1","applicationId":"app-1","phoneNumber":"13800138000","content":"hello",
"route":{"channelCode":"CMPP-A","cmppAccountCode":"sp","rateLimitPerSecond":100},
"cmpp":{"serviceId":"SMS","srcId":"10690000","registeredDelivery":1,"msgFmt":8},
"upstream":{"gatewayHost":"127.0.0.1","gatewayPort":17890,"account":"sp","passwordCipher":"secret","cmppVersion":"3.0"},
"retry":{"attempt":0,"maxAttempts":1}
}`))
handler.ServeHTTP(resp, req)
if resp.Code != http.StatusOK {
t.Fatalf("unexpected response status: %d body=%s", resp.Code, resp.Body.String())
}
if limiter.channelID != "channel-1" || limiter.rate != 100 {
t.Fatalf("unexpected limiter call: %+v", limiter)
}
}
func TestConnectChannelCallbacksConnectedState(t *testing.T) {
handler := handlerWithConnect(func(context.Context, ConnectChannelCommand) (ConnectionStateCallback, error) {
limiter := &controlRecordingLimiter{}
handler := handlerWithServer(Server{Limiter: limiter, Connect: func(context.Context, ConnectChannelCommand) (ConnectionStateCallback, error) {
return ConnectionStateCallback{
ChannelID: "channel-1",
ConnectionID: "channel-1:primary",
@@ -23,7 +70,7 @@ func TestConnectChannelCallbacksConnectedState(t *testing.T) {
LastConnectedAt: time.Now().UTC().Format(time.RFC3339Nano),
LastHeartbeatAt: time.Now().UTC().Format(time.RFC3339Nano),
}, nil
})
}})
resp := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/connections/connect", strings.NewReader(validConnectCommand()))
@@ -45,6 +92,9 @@ func TestConnectChannelCallbacksConnectedState(t *testing.T) {
if callback.LastConnectedAt == "" || callback.LastHeartbeatAt == "" {
t.Fatalf("expected connection timestamps: %+v", callback)
}
if limiter.configuredChannelID != "channel-1" || limiter.configuredRate != 100 {
t.Fatalf("unexpected configured limiter: %+v", limiter)
}
}
func TestConnectChannelCallbacksFailedState(t *testing.T) {