feat: 金额 decimal 精确计费、failover 按失败类型封顶、渠道小时桶预聚合、分层守护测试
- 计费:19 个金额字段 float64→decimal.Decimal,DB 列保持 numeric(20,8) 零迁移; API 金额仍为 JSON number(MarshalJSONWithoutQuotes),前端零改动 - failover:保留时间预算,新增 OT_PROXY_FAILOVER_CAPS_NET/SERVER/RATE/QUOTA 按失败类型封顶换渠道次数(429/配额类瞬时失败时间预算形同虚设) - 预聚合:新增 usage_channel_hourlies(schema v10),记账事务内同步 upsert, 长窗口渠道统计走桶不再扫明细,spent_last_30d 改扫 usage_daily,v10 一次性回填幂等 - 守护:internal/arch_test.go 用 go/parser 强制分层依赖(fail-closed)
This commit is contained in:
1 parent
5d6e5bdb04
commit
b2e500ff51
25 files changed
+841
-253
No files matched your search
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/openteam/server/internal/api/middleware"
|
||||
"github.com/openteam/server/internal/app"
|
||||
"github.com/openteam/server/internal/store"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,7 @@ func newKeysTestEnv(t *testing.T) *keysTestEnv {
|
||||
sqlDB.Close()
|
||||
})
|
||||
u := store.User{Username: "u1", Email: "u1@x.com", PasswordHash: "x",
|
||||
Role: store.RoleUser, Balance: 100, Status: store.UserStatusActive}
|
||||
Role: store.RoleUser, Balance: decimal.NewFromInt(100), Status: store.UserStatusActive}
|
||||
if err := db.Create(&u).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -126,7 +127,7 @@ func TestKeysLifecycle(t *testing.T) {
|
||||
func TestKeysUserIsolation(t *testing.T) {
|
||||
e := newKeysTestEnv(t)
|
||||
other := store.User{Username: "u2", Email: "u2@x.com", PasswordHash: "x",
|
||||
Role: store.RoleUser, Balance: 0, Status: store.UserStatusActive}
|
||||
Role: store.RoleUser, Balance: decimal.Zero, Status: store.UserStatusActive}
|
||||
e.db.Create(&other)
|
||||
var k store.APIKey
|
||||
k = store.APIKey{UserID: other.ID, Name: "theirs", KeyHash: "h2", KeyPrefix: "pre",
|
||||
|
||||
Reference in new issue
Block a user