99 lines
3.3 KiB
Go
99 lines
3.3 KiB
Go
package mysql
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"runtime"
|
||
"strings"
|
||
"testing"
|
||
|
||
"hyapp/pkg/walletmq"
|
||
)
|
||
|
||
func TestResourceOutboxEventsUseStableEventIDAsTransactionID(t *testing.T) {
|
||
// 这些是当前所有通过 resourceOutboxEvent 创建的资源事实;helper 对事件类型
|
||
// 本身无分支,因此该约束也自动覆盖以后接入同一入口的新资源事实。
|
||
eventTypes := []string{
|
||
"GiftConfigChanged",
|
||
"ResourceChanged",
|
||
"ResourceGrantRevoked",
|
||
"ResourceGranted",
|
||
"ResourceGroupChanged",
|
||
"ResourceGroupGranted",
|
||
"UserResourceChanged",
|
||
"VipEffectiveChanged",
|
||
"VipTrialCardGranted",
|
||
}
|
||
for _, eventType := range eventTypes {
|
||
t.Run(eventType, func(t *testing.T) {
|
||
first := resourceOutboxEvent(eventType, "command-1", 1001, 2001, map[string]any{"source": "test"}, 1_700_000_000_000)
|
||
second := resourceOutboxEvent(eventType, "command-1", 1001, 2001, map[string]any{"source": "retry"}, 1_700_000_000_999)
|
||
if first.TransactionID == "" || first.TransactionID != first.EventID {
|
||
t.Fatalf("resource correlation ids mismatch: event_id=%q transaction_id=%q", first.EventID, first.TransactionID)
|
||
}
|
||
if second.EventID != first.EventID || second.TransactionID != first.TransactionID {
|
||
t.Fatalf("resource correlation id changed on retry: first=%+v second=%+v", first, second)
|
||
}
|
||
if len(first.TransactionID) > 96 {
|
||
t.Fatalf("resource transaction_id exceeds wallet_outbox column: %d", len(first.TransactionID))
|
||
}
|
||
if _, err := walletmq.EncodeWalletOutboxMessage(walletmq.WalletOutboxMessage{
|
||
AppCode: "lalu",
|
||
EventID: first.EventID,
|
||
EventType: first.EventType,
|
||
TransactionID: first.TransactionID,
|
||
CommandID: first.CommandID,
|
||
UserID: first.UserID,
|
||
AssetType: first.AssetType,
|
||
PayloadJSON: `{"source":"test"}`,
|
||
OccurredAtMS: first.CreatedAtMS,
|
||
}); err != nil {
|
||
t.Fatalf("resource event is still rejected by wallet MQ encoder: %v", err)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
func TestResourceOutboxHistoricalRetryIsOptInAndNarrowlyScoped(t *testing.T) {
|
||
_, file, _, ok := runtime.Caller(0)
|
||
if !ok {
|
||
t.Fatal("resolve test source path")
|
||
}
|
||
path := filepath.Join(filepath.Dir(file), "../../../deploy/mysql/maintenance/20260711_retry_incomplete_resource_outbox.sql")
|
||
body, err := os.ReadFile(path)
|
||
if err != nil {
|
||
t.Fatalf("read resource outbox maintenance SQL: %v", err)
|
||
}
|
||
sql := string(body)
|
||
for _, required := range []string{
|
||
"COALESCE(@execute_wallet_resource_outbox_retry, 0)",
|
||
"WHERE @execute_wallet_resource_outbox_retry = 1",
|
||
"AND wo.asset_type = 'RESOURCE'",
|
||
"AND wo.transaction_id = ''",
|
||
"AND BINARY wo.last_error = BINARY 'wallet outbox message is incomplete'",
|
||
"AND wo.status IN ('failed', 'retryable')",
|
||
"LIMIT 100",
|
||
"SET wo.transaction_id = wo.event_id",
|
||
"wo.status = 'pending'",
|
||
} {
|
||
if !strings.Contains(sql, required) {
|
||
t.Fatalf("maintenance SQL misses safety contract %q", required)
|
||
}
|
||
}
|
||
for _, eventType := range []string{
|
||
"GiftConfigChanged",
|
||
"ResourceChanged",
|
||
"ResourceGrantRevoked",
|
||
"ResourceGranted",
|
||
"ResourceGroupChanged",
|
||
"ResourceGroupGranted",
|
||
"UserResourceChanged",
|
||
"VipEffectiveChanged",
|
||
"VipTrialCardGranted",
|
||
} {
|
||
if !strings.Contains(sql, "'"+eventType+"'") {
|
||
t.Fatalf("maintenance SQL misses resource event type %q", eventType)
|
||
}
|
||
}
|
||
}
|