fix: 作废投递走统一终态函数并写回执收尾

This commit is contained in:
Nixevol
2026-09-30 16:21:05 +08:00
parent 91e887ba46
commit f139b9ed9b
10 changed files with 365 additions and 166 deletions
+20 -33
View File
@@ -5,6 +5,7 @@ import (
"database/sql"
"strings"
"git.asio.asia/nixevol/NixMsg/internal/app/message"
"git.asio.asia/nixevol/NixMsg/internal/app/port"
"git.asio.asia/nixevol/NixMsg/internal/protocol"
)
@@ -19,7 +20,7 @@ type revokeItem struct {
// voidMemberDeliveriesTx rejects pending deliveries for a leaving member; records revokes for pushed ones.
func voidMemberDeliveriesTx(tx *sql.Tx, groupID, endpointID, reason string, nowMs int64, revokes *[]revokeItem) error {
rows, err := tx.Query(`
SELECT d.seq, d.pushed_at, m.id, m.sender_id
SELECT d.seq, m.id, m.sender_id
FROM deliveries d
JOIN messages m ON m.seq = d.seq
WHERE d.endpoint_id = ? AND d.state = 'pending'
@@ -30,14 +31,13 @@ WHERE d.endpoint_id = ? AND d.state = 'pending'
defer func() { _ = rows.Close() }()
type row struct {
seq int64
pushed sql.NullInt64
msgID string
senderID string
}
var list []row
for rows.Next() {
var r row
if scanErr := rows.Scan(&r.seq, &r.pushed, &r.msgID, &r.senderID); scanErr != nil {
if scanErr := rows.Scan(&r.seq, &r.msgID, &r.senderID); scanErr != nil {
return scanErr
}
list = append(list, r)
@@ -46,16 +46,18 @@ WHERE d.endpoint_id = ? AND d.state = 'pending'
return err
}
for _, r := range list {
if _, execErr := tx.Exec(`
UPDATE deliveries SET state = 'rejected', reason = ?, updated_at = ? WHERE seq = ? AND endpoint_id = ? AND state = 'pending'`,
reason, nowMs, r.seq, endpointID); execErr != nil {
pushed, execErr := message.RejectPendingTx(tx, r.seq, endpointID, reason, nowMs)
if execErr != nil {
return execErr
}
if r.pushed.Valid && revokes != nil {
if pushed && revokes != nil {
*revokes = append(*revokes, revokeItem{
endpointID: endpointID, msgID: r.msgID, fromID: r.senderID, reason: reason,
})
}
if e := message.TryFinalizeTx(tx, r.seq, nowMs, message.DefaultVoidRetentionDays); e != nil {
return e
}
}
return nil
}
@@ -63,7 +65,7 @@ UPDATE deliveries SET state = 'rejected', reason = ?, updated_at = ? WHERE seq =
// voidGroupAllTx rejects all pending group deliveries and completes scheduled messages.
func voidGroupAllTx(tx *sql.Tx, groupID string, nowMs int64, revokes *[]revokeItem) error {
rows, err := tx.Query(`
SELECT d.seq, d.endpoint_id, d.pushed_at, m.id, m.sender_id
SELECT d.seq, d.endpoint_id, m.id, m.sender_id
FROM deliveries d
JOIN messages m ON m.seq = d.seq
WHERE d.state = 'pending' AND m.dest_kind = 'group' AND m.dest_id = ?`, groupID)
@@ -73,14 +75,13 @@ WHERE d.state = 'pending' AND m.dest_kind = 'group' AND m.dest_id = ?`, groupID)
type drow struct {
seq int64
endpointID string
pushed sql.NullInt64
msgID string
senderID string
}
var dlist []drow
for rows.Next() {
var r drow
if scanErr := rows.Scan(&r.seq, &r.endpointID, &r.pushed, &r.msgID, &r.senderID); scanErr != nil {
if scanErr := rows.Scan(&r.seq, &r.endpointID, &r.msgID, &r.senderID); scanErr != nil {
_ = rows.Close()
return scanErr
}
@@ -91,35 +92,35 @@ WHERE d.state = 'pending' AND m.dest_kind = 'group' AND m.dest_id = ?`, groupID)
return err
}
for _, r := range dlist {
if _, execErr := tx.Exec(`
UPDATE deliveries SET state = 'rejected', reason = ?, updated_at = ?
WHERE seq = ? AND endpoint_id = ? AND state = 'pending'`,
reasonGroupDissolved, nowMs, r.seq, r.endpointID); execErr != nil {
pushed, execErr := message.RejectPendingTx(tx, r.seq, r.endpointID, reasonGroupDissolved, nowMs)
if execErr != nil {
return execErr
}
if r.pushed.Valid && revokes != nil {
if pushed && revokes != nil {
*revokes = append(*revokes, revokeItem{
endpointID: r.endpointID, msgID: r.msgID, fromID: r.senderID, reason: reasonGroupDissolved,
})
}
if e := message.TryFinalizeTx(tx, r.seq, nowMs, message.DefaultVoidRetentionDays); e != nil {
return e
}
}
srows, err := tx.Query(`
SELECT seq, id, sender_id, receipt FROM messages
SELECT seq, sender_id, receipt FROM messages
WHERE dest_kind = 'group' AND dest_id = ? AND state = 'scheduled'`, groupID)
if err != nil {
return err
}
type srow struct {
seq int64
msgID string
senderID string
receipt int
}
var slist []srow
for srows.Next() {
var r srow
if scanErr := srows.Scan(&r.seq, &r.msgID, &r.senderID, &r.receipt); scanErr != nil {
if scanErr := srows.Scan(&r.seq, &r.senderID, &r.receipt); scanErr != nil {
_ = srows.Close()
return scanErr
}
@@ -130,23 +131,9 @@ WHERE dest_kind = 'group' AND dest_id = ? AND state = 'scheduled'`, groupID)
return err
}
for _, r := range slist {
if _, execErr := tx.Exec(`
UPDATE messages SET state = 'completed', reason = ? WHERE seq = ? AND state = 'scheduled'`,
reasonGroupDissolved, r.seq); execErr != nil {
if execErr := message.FinalizeMessageTx(tx, r.seq, r.receipt != 0, r.senderID, "", reasonGroupDissolved, nowMs, message.DefaultVoidRetentionDays); execErr != nil {
return execErr
}
if _, execErr := tx.Exec(`DELETE FROM message_bodies WHERE seq = ?`, r.seq); execErr != nil {
return execErr
}
if r.receipt != 0 {
// 消息级作废回执:endpoint_id 空,state=rejected(DEVELOPMENT 6.4);消息行仍为 completed
if _, execErr := tx.Exec(`
INSERT INTO receipts(sender_id, msg_id, endpoint_id, state, reason, created_at, acked)
VALUES(?,?,?,?,?,?,0)`,
r.senderID, r.msgID, "", "rejected", reasonGroupDissolved, nowMs); execErr != nil {
return execErr
}
}
}
return nil
}