feat(v2): crypto 预留表冷启动兜底——注入 loader 从 pending attempts 重建 reservation(兜重启丢内存)
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package reconcile
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/wangjia/pay/internal/model"
|
||||
"github.com/wangjia/pay/internal/provider/crypto"
|
||||
"github.com/wangjia/pay/internal/store"
|
||||
)
|
||||
|
||||
// CryptoReservationLoader 装配 crypto 冷启动预留源:读全部 pending attempt,
|
||||
// 过滤 channel=crypto,映射为 crypto.PendingReservation。ReservedAt 取 attempt.CreatedAt
|
||||
// (建单时刻,冷却窗自此算)。crypto 不 import store,故此桥在装配层。
|
||||
func CryptoReservationLoader(orders *store.OrderStore) crypto.ReservationLoader {
|
||||
return func(ctx context.Context) ([]crypto.PendingReservation, error) {
|
||||
atts, err := orders.ListAttemptsByStatus(model.AttemptPending, 200)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]crypto.PendingReservation, 0, len(atts))
|
||||
for i := range atts {
|
||||
a := &atts[i]
|
||||
if a.Channel != "crypto" {
|
||||
continue
|
||||
}
|
||||
out = append(out, crypto.PendingReservation{
|
||||
AccountID: a.AccountID, AmountMinor: a.AmountMinor,
|
||||
ProviderRef: a.ProviderRef, ReservedAt: a.CreatedAt,
|
||||
})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package reconcile_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/wangjia/pay/internal/model"
|
||||
"github.com/wangjia/pay/internal/reconcile"
|
||||
"github.com/wangjia/pay/internal/store"
|
||||
)
|
||||
|
||||
func TestCryptoReservationLoaderFiltersPendingCrypto(t *testing.T) {
|
||||
db := model.OpenTestDB(t)
|
||||
s := store.NewOrderStore(db)
|
||||
// 两条 attempt:crypto pending(要)、alipay pending(不要)。
|
||||
_ = s.CreateAttempt(&model.Attempt{OutTradeNo: "O1", Channel: "crypto", ProviderRef: "CRYPTO-O1-12",
|
||||
AmountMinor: 100, Currency: "USDT", Status: model.AttemptPending})
|
||||
_ = s.CreateAttempt(&model.Attempt{OutTradeNo: "O2", Channel: "alipay", ProviderRef: "AL-O2",
|
||||
AmountMinor: 200, Currency: "CNY", Status: model.AttemptPending})
|
||||
|
||||
loader := reconcile.CryptoReservationLoader(s)
|
||||
items, err := loader(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("loader: %v", err)
|
||||
}
|
||||
if len(items) != 1 || items[0].ProviderRef != "CRYPTO-O1-12" || items[0].AmountMinor != 100 {
|
||||
t.Fatalf("只应含 crypto pending, got %+v", items)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user