fix: close receipt delivery workflows

This commit is contained in:
hectorzhao
2026-07-24 14:40:57 +08:00
parent 2ee39056eb
commit 91f04f5288
22 changed files with 829 additions and 48 deletions
+81
View File
@@ -174,6 +174,8 @@ type downstreamConnectionEvent struct {
type downstreamSession struct {
messageID string
account string
tenantID string
applicationID string
enterpriseCode string
protocol string
srcID string
@@ -188,6 +190,7 @@ type downstreamSession struct {
instanceID string
report func(*downstreamSession, string, string)
deliveryReport func(downstreamDeliveryLifecycleEvent)
protocolLog func(protocolLogEvent)
}
var downstreamRegistry = struct {
@@ -244,6 +247,8 @@ func (s Server) handleLogin(response *cmpp.Response, packet *cmpp.Packet, logger
now := time.Now().UTC()
session := &downstreamSession{
account: strings.TrimSpace(defaultString(auth.Account, account)),
tenantID: strings.TrimSpace(auth.TenantID),
applicationID: strings.TrimSpace(auth.ApplicationID),
enterpriseCode: strings.TrimSpace(auth.EnterpriseCode),
protocol: cmppVersionName(req.Version),
srcID: strings.TrimSpace(auth.Account),
@@ -256,6 +261,7 @@ func (s Server) handleLogin(response *cmpp.Response, packet *cmpp.Packet, logger
instanceID: s.gatewayInstanceID(),
report: s.reportConnection,
deliveryReport: s.reportDownstreamDelivery,
protocolLog: s.emitProtocolLog,
}
if !rememberAccount(session, auth.MaxConnections) {
logger.Printf("cmpp inbound auth failed account=%s remote=%s err=connection limit exceeded max=%d", account, packet.Conn.Conn.RemoteAddr(), auth.MaxConnections)
@@ -372,6 +378,8 @@ func (s Server) handleSubmit(response *cmpp.Response, packet *cmpp.Packet, logge
rememberDownstream(downstreamSession{
messageID: acceptedMessage.MessageID,
account: account,
tenantID: result.TenantID,
applicationID: result.ApplicationID,
enterpriseCode: session.enterpriseCode,
protocol: clientProtocol,
srcID: strings.TrimSpace(req.srcID),
@@ -386,6 +394,7 @@ func (s Server) handleSubmit(response *cmpp.Response, packet *cmpp.Packet, logge
instanceID: s.gatewayInstanceID(),
report: session.report,
deliveryReport: session.deliveryReport,
protocolLog: session.protocolLog,
})
}
if current := findSessionByConn(packet.Conn); current != nil && current.report != nil {
@@ -1282,12 +1291,14 @@ func sendDownstream(session *downstreamSession, deliver cmpp.Packer, deliveryID
tracker := registerDownstreamAck(session, deliveryID, sequenceID, messageID, ackDeadlineAt)
if err := session.conn.SendPkt(deliver, sequenceID); err != nil {
removeDownstreamAck(tracker)
session.recordDownstreamProtocol(deliver, deliveryID, sequenceID, messageID, "failed", "SEND_FAILED", err)
if session.report != nil {
go session.report(session, "disconnected", err.Error())
}
forgetDownstream(session)
return DownstreamSendResult{}, err
}
session.recordDownstreamProtocol(deliver, deliveryID, sequenceID, messageID, "success", "", nil)
result := DownstreamSendResult{
Sent: true, ConnectionID: session.connectionID,
SequenceID: strconv.FormatUint(uint64(sequenceID), 10), MessageID: strconv.FormatUint(messageID, 10),
@@ -1306,6 +1317,56 @@ func sendDownstream(session *downstreamSession, deliver cmpp.Packer, deliveryID
return result, nil
}
func (session *downstreamSession) recordDownstreamProtocol(
deliver cmpp.Packer,
deliveryID string,
sequenceID uint32,
messageID uint64,
status string,
resultCode string,
sendErr error,
) {
if session == nil || session.protocolLog == nil {
return
}
eventType, phone := downstreamDeliverMetadata(deliver)
detail := map[string]any{"sequenceId": sequenceID, "deliveryId": deliveryID}
if sendErr != nil {
detail["error"] = sendErr.Error()
}
session.protocolLog(protocolLogEvent{
Protocol: "cmpp",
Direction: "platform_to_client",
EventType: eventType,
Status: status,
TenantID: session.tenantID,
ApplicationID: session.applicationID,
Account: session.account,
MessageID: session.messageID,
GatewayMessageID: strconv.FormatUint(messageID, 10),
Phone: defaultString(phone, session.phoneNumber),
ResultCode: resultCode,
Detail: detail,
})
}
func downstreamDeliverMetadata(deliver cmpp.Packer) (string, string) {
switch packet := deliver.(type) {
case *cmpp.Cmpp2DeliverReqPkt:
if packet.RegisterDelivery == 1 {
return "deliver_receipt", packet.SrcTerminalId
}
return "deliver_uplink", packet.SrcTerminalId
case *cmpp.Cmpp3DeliverReqPkt:
if packet.RegisterDelivery == 1 {
return "deliver_receipt", packet.SrcTerminalId
}
return "deliver_uplink", packet.SrcTerminalId
default:
return "deliver", ""
}
}
func downstreamDeliverMessageID(deliver cmpp.Packer) uint64 {
switch packet := deliver.(type) {
case *cmpp.Cmpp2DeliverReqPkt:
@@ -1389,6 +1450,26 @@ func handleDownstreamAcknowledgement(conn *cmpp.Conn, sequenceID uint32, message
SequenceID: sequenceID, MessageID: messageID, Result: result, ObservedAt: time.Now().UTC(),
})
}
if tracker.session != nil && tracker.session.protocolLog != nil {
status := "success"
if result != 0 {
status = "failed"
}
tracker.session.protocolLog(protocolLogEvent{
Protocol: "cmpp",
Direction: "client_to_platform",
EventType: "deliver_resp",
Status: status,
TenantID: tracker.session.tenantID,
ApplicationID: tracker.session.applicationID,
Account: tracker.session.account,
MessageID: tracker.session.messageID,
GatewayMessageID: strconv.FormatUint(messageID, 10),
Phone: tracker.session.phoneNumber,
ResultCode: strconv.FormatUint(uint64(result), 10),
Detail: map[string]any{"sequenceId": sequenceID, "deliveryId": tracker.deliveryID},
})
}
}
func downstreamAckTimeout() time.Duration {