refactor(arch): decouple private imports, enforce contracts and comply with cordis architecture

This commit is contained in:
ryan
2026-09-03 10:40:02 +08:00
parent dbcf485d8a
commit 953a224245
107 changed files with 2028 additions and 1263 deletions
@@ -11,7 +11,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/credential"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"gorm.io/gorm"
@@ -60,8 +59,8 @@ func setupCloudflareLogicDB(t *testing.T) (context.Context, uint) {
); err != nil {
t.Fatalf("AutoMigrate() error = %v", err)
}
db.SetDB(conn)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(conn)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
sealed, err := credential.Seal(`{"api_token":"test-token"}`)
if err != nil {
@@ -143,11 +142,11 @@ func TestCreateMemberCopiesGroupDefaultProxied(t *testing.T) {
t.Fatalf("GetCFPointingGroup() error = %v", err)
}
zone := model.Zone{Domain: "example.net"}
if err := db.DB(ctx).Create(&zone).Error; err != nil {
if err := repository.DB(ctx).Create(&zone).Error; err != nil {
t.Fatalf("Create(zone) error = %v", err)
}
domain := model.ZoneDomain{ZoneID: zone.ID, Domain: "www.example.net"}
if err := db.DB(ctx).Create(&domain).Error; err != nil {
if err := repository.DB(ctx).Create(&domain).Error; err != nil {
t.Fatalf("Create(domain) error = %v", err)
}
restore := SetDispatchTaskForTest(func(context.Context, string, []byte, string) (string, error) { return "task-1", nil })
@@ -11,7 +11,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/pkg/response"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
)
@@ -58,7 +57,7 @@ func TestGetGroupWithOrphanedMemberHealsAndSucceeds(t *testing.T) {
}
// Simulate orphaned member by deleting the ZoneDomain directly
if err := db.DB(ctx).Exec("DELETE FROM of_zone_domains WHERE id = ?", member.ZoneDomainID).Error; err != nil {
if err := repository.DB(ctx).Exec("DELETE FROM of_zone_domains WHERE id = ?", member.ZoneDomainID).Error; err != nil {
t.Fatalf("DELETE FROM of_zone_domains error = %v", err)
}
@@ -12,7 +12,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/testhelper"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -28,10 +27,10 @@ func setupDashboardTestDB(t *testing.T) func() {
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.OpenFlareNode{}))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
testhelper.SetupLogStoresForTest(t)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -43,7 +42,7 @@ func TestGetOverviewStructure(t *testing.T) {
now := time.Now().UTC()
lastSeen := now.Add(-15 * time.Second) // within default 60s offline threshold
require.NoError(t, db.DB(ctx).Create(&model.OpenFlareNode{
require.NoError(t, repository.DB(ctx).Create(&model.OpenFlareNode{
NodeID: "node-dashboard-1",
Name: "Edge 1",
IP: "10.0.0.1",
@@ -52,7 +51,7 @@ func TestGetOverviewStructure(t *testing.T) {
CurrentVersion: "v1.0.0",
LastSeenAt: &lastSeen,
}).Error)
require.NoError(t, db.DB(ctx).Create(&model.OpenFlareNode{
require.NoError(t, repository.DB(ctx).Create(&model.OpenFlareNode{
NodeID: "node-dashboard-2",
Name: "Edge 2",
IP: "10.0.0.2",
@@ -15,7 +15,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/testhelper"
"Wavelet/pkg/response"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
@@ -36,11 +35,11 @@ func setupAgentAuthTestDB(t *testing.T) func() {
&model.SystemConfig{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
tokenCache.reset()
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
tokenCache.reset()
}
}
@@ -51,7 +50,7 @@ func TestAuthenticateAccessToken(t *testing.T) {
ctx := context.Background()
now := time.Now()
require.NoError(t, db.DB(ctx).Create(&model.OpenFlareNode{
require.NoError(t, repository.DB(ctx).Create(&model.OpenFlareNode{
NodeID: "node-auth-1",
Name: "edge",
AccessToken: "valid-agent-token",
@@ -98,7 +97,7 @@ func TestAgentAuthMiddleware(t *testing.T) {
ctx := context.Background()
now := time.Now()
require.NoError(t, db.DB(ctx).Create(&model.OpenFlareNode{
require.NoError(t, repository.DB(ctx).Create(&model.OpenFlareNode{
NodeID: "node-mw-1",
Name: "edge",
AccessToken: "middleware-token",
@@ -145,7 +144,7 @@ func TestAgentRegisterAuthMiddleware(t *testing.T) {
ctx := context.Background()
now := time.Now()
require.NoError(t, db.DB(ctx).Create(&model.OpenFlareNode{
require.NoError(t, repository.DB(ctx).Create(&model.OpenFlareNode{
NodeID: "node-register-1",
Name: "edge",
AccessToken: "existing-node-token",
@@ -14,7 +14,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/share/protocol"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -34,9 +33,9 @@ func setupWAFIPGroupTestDB(t *testing.T) func() {
&model.ConfigVersion{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -60,7 +59,7 @@ func seedActiveConfigWithWAFIPGroup(t *testing.T, ctx context.Context, ipGroupID
snapshotJSON, err := json.Marshal(snapshot)
require.NoError(t, err)
require.NoError(t, db.DB(ctx).Create(&model.ConfigVersion{
require.NoError(t, repository.DB(ctx).Create(&model.ConfigVersion{
Version: "20260618-001",
SnapshotJSON: string(snapshotJSON),
Checksum: "test-checksum",
@@ -108,7 +107,7 @@ func seedActiveConfigWithWAFGraphIPGroup(t *testing.T, ctx context.Context, ipGr
snapshotJSON, err := json.Marshal(snapshot)
require.NoError(t, err)
require.NoError(t, db.DB(ctx).Create(&model.ConfigVersion{
require.NoError(t, repository.DB(ctx).Create(&model.ConfigVersion{
Version: "20260713-graph-001",
SnapshotJSON: string(snapshotJSON),
Checksum: "graph-test-checksum",
@@ -142,7 +141,7 @@ func TestChangedWAFIPGroupsForAgentRejectsMalformedIPMatchConfig(t *testing.T) {
defer cleanup()
ctx := context.Background()
require.NoError(t, db.DB(ctx).Create(&model.ConfigVersion{
require.NoError(t, repository.DB(ctx).Create(&model.ConfigVersion{
Version: "20260713-malformed-001",
SnapshotJSON: `{"waf":{"rule_groups":[{"id":7,"graph":{"entry":"match","nodes":{` +
`"match":{"type":"ip_match","config":{"ip_group_ids":"not-an-array"}}}}}],"bindings":[]}}`,
@@ -9,7 +9,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -23,8 +22,8 @@ func TestUptimeKumaSyncHandlerSkipsWhenDisabled(t *testing.T) {
})
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.SystemConfig{}))
db.SetDB(sqliteDB)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(sqliteDB)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
require.NoError(t, repository.SaveOrUpdateSystemConfig(ctx, model.ConfigKeyUptimeKumaEnabled, "false"))
@@ -13,7 +13,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/pkg/response"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
@@ -30,10 +29,10 @@ func setupFlaredMiddlewareTestDB(t *testing.T) func() {
})
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.OpenFlareNode{}))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -11,7 +11,6 @@ import (
"Wavelet/openflare/plugins/server/domain/fleet/agent"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -33,11 +32,11 @@ func setupFlaredObservabilityTestDB(t *testing.T) func() {
&model.ConfigVersion{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
agent.ResetAuthCacheForTest()
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
agent.ResetAuthCacheForTest()
}
}
@@ -54,7 +53,7 @@ func TestHeartbeatFlaredEmitsHealthEventOnUnhealthy(t *testing.T) {
Status: "pending",
NodeType: "tunnel_client",
}
require.NoError(t, db.DB(ctx).Create(node).Error)
require.NoError(t, repository.DB(ctx).Create(node).Error)
_, err := Heartbeat(ctx, node, HeartbeatPayload{
ClientVersion: "v0.2.0",
@@ -14,7 +14,6 @@ import (
ofnode "Wavelet/openflare/plugins/server/domain/fleet/node"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/testhelper"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
@@ -39,7 +38,7 @@ func setupProtocolTestEnv(t *testing.T) (*gin.Engine, func()) {
&model.ConfigVersion{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
agent.ResetAuthCacheForTest()
testhelper.SetupLogStoresForTest(t)
@@ -47,7 +46,7 @@ func setupProtocolTestEnv(t *testing.T) (*gin.Engine, func()) {
mountOpenFlareTestRoutes(engine)
cleanup := func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
agent.ResetAuthCacheForTest()
}
return engine, cleanup
@@ -11,8 +11,8 @@ import (
"Wavelet/openflare/plugins/server/domain/fleet/agent"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/testhelper"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
@@ -55,7 +55,7 @@ func setupCoreChainTest(t *testing.T) (*gin.Engine, adminSeed, func()) {
&model.ZoneDomain{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
agent.ResetAuthCacheForTest()
seed, err := seedAdminWithAccessToken(sqliteDB)
@@ -65,7 +65,7 @@ func setupCoreChainTest(t *testing.T) (*gin.Engine, adminSeed, func()) {
mountOpenFlareTestRoutes(engine)
cleanup := func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
agent.ResetAuthCacheForTest()
}
@@ -144,12 +144,12 @@ func TestCoreChainMigrationFlow(t *testing.T) {
t.Run("create proxy route linked to origin", func(t *testing.T) {
// Create Zone and ZoneDomain directly in the DB
zone := model.Zone{Domain: "example.com"}
require.NoError(t, db.DB(context.Background()).Create(&zone).Error)
require.NoError(t, repository.DB(context.Background()).Create(&zone).Error)
zoneDomain := model.ZoneDomain{
ZoneID: zone.ID,
Domain: "core-chain.example.com",
}
require.NoError(t, db.DB(context.Background()).Create(&zoneDomain).Error)
require.NoError(t, repository.DB(context.Background()).Create(&zoneDomain).Error)
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/proxy-routes/"), map[string]any{
"site_name": "core-chain-site",
@@ -17,9 +17,9 @@ import (
"time"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/runtimeconfig"
"Wavelet/openflare/plugins/server/kernel/testhelper"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
@@ -51,7 +51,7 @@ func setupSecurityTest(t *testing.T) (*gin.Engine, adminSeed, func()) {
&model.SystemConfig{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
seed, err := seedAdminWithAccessToken(sqliteDB)
require.NoError(t, err)
@@ -64,7 +64,7 @@ func setupSecurityTest(t *testing.T) (*gin.Engine, adminSeed, func()) {
cleanup := func() {
runtimeconfig.Set(previous)
db.SetDB(nil)
repository.SetDBForTest(nil)
}
return engine, seed, cleanup
@@ -205,12 +205,12 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
t.Run("create proxy route for WAF binding", func(t *testing.T) {
// Create Zone and ZoneDomain directly in the DB
routeZone := model.Zone{Domain: "example-route.com"}
require.NoError(t, db.DB(context.Background()).Create(&routeZone).Error)
require.NoError(t, repository.DB(context.Background()).Create(&routeZone).Error)
routeZoneDomain := model.ZoneDomain{
ZoneID: routeZone.ID,
Domain: "route.example-route.com",
}
require.NoError(t, db.DB(context.Background()).Create(&routeZoneDomain).Error)
require.NoError(t, repository.DB(context.Background()).Create(&routeZoneDomain).Error)
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/proxy-routes/"), map[string]any{
"site_name": "security-site",
@@ -15,7 +15,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/testhelper"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -40,13 +39,15 @@ func setupNodeTestDB(t *testing.T) func() {
&model.OpenFlareNode{},
&model.SystemConfig{},
&model.OpenFlareApplyLog{},
&model.OpenFlareNodeSystemProfile{},
&model.OpenFlareHealthEvent{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
testhelper.SetupLogStoresForTest(t)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -174,7 +175,7 @@ func TestListNodesWithApplyLogMetadata(t *testing.T) {
require.NoError(t, err)
applyAt := time.Now().UTC().Truncate(time.Second)
require.NoError(t, db.DB(ctx).Create(&model.OpenFlareApplyLog{
require.NoError(t, repository.DB(ctx).Create(&model.OpenFlareApplyLog{
NodeID: created.NodeID,
Version: "20260618-001",
Result: "success",
@@ -280,7 +281,7 @@ func TestRequestOpenrestyRestart(t *testing.T) {
func seedActiveConfigVersion(t *testing.T, ctx context.Context) {
t.Helper()
conn := db.DB(ctx)
conn := repository.DB(ctx)
require.NotNil(t, conn)
require.NoError(t, conn.AutoMigrate(&model.ConfigVersion{}))
require.NoError(t, conn.Create(&model.ConfigVersion{
@@ -311,7 +312,7 @@ func TestRequestForceSyncRequiresActiveConfig(t *testing.T) {
cleanup := setupNodeTestDB(t)
defer cleanup()
ctx := context.Background()
conn := db.DB(ctx)
conn := repository.DB(ctx)
require.NotNil(t, conn)
require.NoError(t, conn.AutoMigrate(&model.ConfigVersion{}))
@@ -14,7 +14,6 @@ import (
"Wavelet/openflare/plugins/server/domain/fleet/agent"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -38,12 +37,12 @@ func setupRelayTestDB(t *testing.T) func() {
&model.OpenFlareNodeObservationFrps{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
agent.ResetAuthCacheForTest()
testhelper.SetupLogStoresForTest(t)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
agent.ResetAuthCacheForTest()
}
}
@@ -63,7 +62,7 @@ func TestHeartbeatPayloadBindingAndFrpsObservationInsert(t *testing.T) {
NodeType: "tunnel_relay",
RelayStatus: "unknown",
}
require.NoError(t, db.DB(ctx).Create(node).Error)
require.NoError(t, repository.DB(ctx).Create(node).Error)
proxies := []ProxyStat{
{
@@ -103,7 +102,7 @@ func TestHeartbeatPayloadBindingAndFrpsObservationInsert(t *testing.T) {
require.NoError(t, err)
var stored model.OpenFlareNode
require.NoError(t, db.DB(ctx).Where("node_id = ?", node.NodeID).First(&stored).Error)
require.NoError(t, repository.DB(ctx).Where("node_id = ?", node.NodeID).First(&stored).Error)
assert.Equal(t, "online", stored.Status)
assert.Equal(t, "healthy", stored.RelayStatus)
assert.Equal(t, "203.0.113.9", stored.IP)
@@ -147,7 +146,7 @@ func TestHeartbeatRelayReconcilesFrpsUnhealthyEvent(t *testing.T) {
NodeType: "tunnel_relay",
RelayStatus: "healthy",
}
require.NoError(t, db.DB(ctx).Create(node).Error)
require.NoError(t, repository.DB(ctx).Create(node).Error)
_, err := Heartbeat(ctx, node, HeartbeatPayload{
Version: "v0.1.0",
@@ -13,7 +13,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/pkg/response"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
@@ -30,10 +29,10 @@ func setupRelayMiddlewareTestDB(t *testing.T) func() {
})
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.OpenFlareNode{}))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -14,7 +14,6 @@ import (
"Wavelet/openflare/plugins/server/domain/observability/chwriter"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
)
// Run with Docker ClickHouse + config.yaml:
@@ -23,7 +23,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/repository/logstore"
"Wavelet/openflare/plugins/server/kernel/runtimeconfig"
db "Wavelet/plugins/infra/database"
)
var logDBSwitchDBSeq int64
@@ -57,13 +56,13 @@ func TestCopyAccessLogsPreservesIDs(t *testing.T) {
srcDB := newLogDBSwitchDB(t)
dstDB := newLogDBSwitchDB(t)
db.SetDB(srcDB)
repository.SetDBForTest(srcDB)
src, err := logstore.Active(ctx) // 无 reader 时按 seed 规则解析为 sqlite
require.NoError(t, err)
db.SetDB(dstDB)
repository.SetDBForTest(dstDB)
dst, err := logstore.BuildForMigration(ctx, "sqlite")
require.NoError(t, err)
t.Cleanup(func() { db.SetDB(nil) })
t.Cleanup(func() { repository.SetDBForTest(nil) })
now := time.Now().UTC()
rows := []analyticsmodel.NodeAccessLog{
@@ -103,13 +102,13 @@ func TestCopyUserAccessLogsPreservesIDs(t *testing.T) {
srcDB := newLogDBSwitchDB(t)
dstDB := newLogDBSwitchDB(t)
db.SetDB(srcDB)
repository.SetDBForTest(srcDB)
src, err := logstore.Active(ctx)
require.NoError(t, err)
db.SetDB(dstDB)
repository.SetDBForTest(dstDB)
dst, err := logstore.BuildForMigration(ctx, "sqlite")
require.NoError(t, err)
t.Cleanup(func() { db.SetDB(nil) })
t.Cleanup(func() { repository.SetDBForTest(nil) })
now := time.Now().UTC()
rows := []analyticsmodel.UserAccessLog{
@@ -142,8 +141,8 @@ func TestClearTargetLogTablesClearsUserAccessLogs(t *testing.T) {
ctx := context.Background()
dstDB := newLogDBSwitchDB(t)
db.SetDB(dstDB)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(dstDB)
t.Cleanup(func() { repository.SetDBForTest(nil) })
dst, err := logstore.BuildForMigration(ctx, "sqlite")
require.NoError(t, err)
@@ -168,8 +167,8 @@ func TestClearTargetLogTablesDuringMigration(t *testing.T) {
defer logstore.ResetForTest()
gdb := newLogDBSwitchDB(t)
db.SetDB(gdb)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(gdb)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
logstore.SetConfigReader(func(ctx context.Context, key string) (string, error) {
@@ -205,8 +204,8 @@ func TestValidateSwitch(t *testing.T) {
})
gdb := newLogDBSwitchDB(t)
db.SetDB(gdb)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(gdb)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
setLogDB := func(v string) {
require.NoError(t, repository.SaveOrUpdateSystemConfig(ctx, model.ConfigKeyLogDatabase, v))
@@ -288,8 +287,8 @@ func TestExecuteFailureClearsMigrationFlag(t *testing.T) {
defer logstore.ResetForTest()
gdb := newLogDBSwitchDB(t)
db.SetDB(gdb)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(gdb)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
// FRESH DB:log_db_migration 行不存在(不预置),log_database 预置为 sqlite。
@@ -323,8 +322,8 @@ func TestSetMigrationFlagObservableThroughCache(t *testing.T) {
defer logstore.ResetForTest()
gdb := newLogDBSwitchDB(t)
db.SetDB(gdb)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(gdb)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
// 按 bootstrap 同款注入 repository 读取,走 RAM 缓存路径。
@@ -353,8 +352,8 @@ func TestFlipLogDatabaseRefreshesCachedConfig(t *testing.T) {
defer logstore.ResetForTest()
gdb := newLogDBSwitchDB(t)
db.SetDB(gdb)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(gdb)
t.Cleanup(func() { repository.SetDBForTest(nil) })
ctx := context.Background()
logstore.SetConfigReader(func(ctx context.Context, key string) (string, error) {
@@ -9,7 +9,7 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/testhelper"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -26,7 +26,8 @@ func setupOptionTestDB(t *testing.T) func() {
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.SystemConfig{}))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
repository.SetSystemConfigService(testhelper.NewMockSystemConfigService(sqliteDB))
// 预填充一些业务配置用于测试
seedConfigs := []model.SystemConfig{
@@ -38,14 +39,15 @@ func setupOptionTestDB(t *testing.T) func() {
}
return func() {
db.SetDB(nil)
repository.SetSystemConfigService(nil)
repository.SetDBForTest(nil)
}
}
// setTestConfig 设置测试配置的辅助函数
func setTestConfig(t *testing.T, ctx context.Context, key, value string) {
t.Helper()
require.NoError(t, db.DB(ctx).Model(&model.SystemConfig{}).Where("key = ?", key).Update("value", value).Error)
require.NoError(t, repository.DB(ctx).Model(&model.SystemConfig{}).Where("key = ?", key).Update("value", value).Error)
}
func TestListOptionsFiltersSecretKeys(t *testing.T) {
@@ -89,7 +91,7 @@ func TestUpdateOpenRestyOptionPersistsToSystemConfig(t *testing.T) {
defer cleanup()
ctx := context.Background()
require.NoError(t, db.DB(ctx).Create(&model.SystemConfig{
require.NoError(t, repository.DB(ctx).Create(&model.SystemConfig{
Key: model.ConfigKeyOpenRestyEventsUse,
Value: "epoll",
Type: "business",
@@ -17,7 +17,7 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/testhelper"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -125,17 +125,19 @@ func setupSyncTestDB(t *testing.T) func() {
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.ProxyRoute{}, &model.Zone{}, &model.ZoneDomain{}, &model.SystemConfig{}))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
repository.SetSystemConfigService(testhelper.NewMockSystemConfigService(sqliteDB))
return func() {
db.SetDB(nil)
repository.SetSystemConfigService(nil)
repository.SetDBForTest(nil)
}
}
func createRouteZoneDomain(t *testing.T, ctx context.Context, route *model.ProxyRoute, domain string) {
t.Helper()
zone := &model.Zone{Domain: fmt.Sprintf("zone-%d.example", route.ID)}
require.NoError(t, db.DB(ctx).Create(zone).Error)
require.NoError(t, db.DB(ctx).Create(&model.ZoneDomain{
require.NoError(t, repository.DB(ctx).Create(zone).Error)
require.NoError(t, repository.DB(ctx).Create(&model.ZoneDomain{
ZoneID: zone.ID,
ProxyRouteID: &route.ID,
Domain: domain,
@@ -166,7 +168,7 @@ func backupUptimeKumaConfig(ctx context.Context) func() {
return func() {
// 恢复所有配置
for key, value := range oldValues {
_ = db.DB(ctx).Model(&model.SystemConfig{}).Where("key = ?", key).Update("value", value).Error
_ = repository.DB(ctx).Model(&model.SystemConfig{}).Where("key = ?", key).Update("value", value).Error
}
}
}
@@ -197,7 +199,7 @@ func TestSyncToUptimeKumaSuccess(t *testing.T) {
restore := backupUptimeKumaConfig(ctx)
defer restore()
require.NoError(t, db.DB(ctx).Where("1 = 1").Delete(&model.ProxyRoute{}).Error)
require.NoError(t, repository.DB(ctx).Where("1 = 1").Delete(&model.ProxyRoute{}).Error)
routeA := &model.ProxyRoute{
SiteName: "site-a",
@@ -306,7 +308,7 @@ func TestSyncToUptimeKumaSelectedScope(t *testing.T) {
restore := backupUptimeKumaConfig(ctx)
defer restore()
require.NoError(t, db.DB(ctx).Where("1 = 1").Delete(&model.ProxyRoute{}).Error)
require.NoError(t, repository.DB(ctx).Where("1 = 1").Delete(&model.ProxyRoute{}).Error)
routeA := &model.ProxyRoute{
SiteName: "site-a",
@@ -9,7 +9,7 @@ import (
"time"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/repository"
)
func TestGitHubSourceIdentityLengthPrefixesFieldsAndResetsRuntime(t *testing.T) {
@@ -57,7 +57,7 @@ func TestGitHubSourceIdentityLengthPrefixesFieldsAndResetsRuntime(t *testing.T)
syncedAt := time.Now().Add(-30 * time.Second)
nextCheckAt := time.Now().Add(time.Hour)
leaseExpiresAt := time.Now().Add(time.Minute)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", firstSource.ID).
Updates(map[string]any{
"etag": `"old-etag"`,
@@ -20,7 +20,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/task"
"Wavelet/openflare/share/githubrelease"
db "Wavelet/plugins/infra/database"
"github.com/hibiken/asynq"
"gorm.io/gorm"
@@ -62,7 +61,7 @@ func mustConfigureGitHubSourceWithoutDispatch(
if err := validateGitHubSourceInput(input); err != nil {
t.Fatalf("validateGitHubSourceInput(%+v) error = %v, want nil", input, err)
}
if err := db.DB(ctx).Transaction(func(tx *gorm.DB) error {
if err := repository.DB(ctx).Transaction(func(tx *gorm.DB) error {
_, err := updateGitHubSourceTx(tx, projectID, input)
return err
}); err != nil {
@@ -78,11 +77,11 @@ func mustLoadPagesSource(
) (*model.PagesProjectSource, *model.PagesProjectSourceRuntime) {
t.Helper()
var source model.PagesProjectSource
if err := db.DB(ctx).Where("project_id = ?", projectID).First(&source).Error; err != nil {
if err := repository.DB(ctx).Where("project_id = ?", projectID).First(&source).Error; err != nil {
t.Fatalf("load source for project %d error = %v, want nil", projectID, err)
}
var runtime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
t.Fatalf("load runtime for source %d error = %v, want nil", source.ID, err)
}
return &source, &runtime
@@ -136,14 +135,14 @@ func TestGitHubSourceValidationNormalizationAndProviderSwitch(t *testing.T) {
}
var taskCount int64
if err := db.DB(ctx).Model(&model.TaskExecution{}).Count(&taskCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.TaskExecution{}).Count(&taskCount).Error; err != nil {
t.Fatalf("count initial checks error = %v, want nil", err)
}
if _, err := UpdateSourceAs(ctx, project.ID, input, "user:42"); err != nil {
t.Fatalf("UpdateSourceAs(GitHub no-op) error = %v, want nil", err)
}
var noOpTaskCount int64
if err := db.DB(ctx).Model(&model.TaskExecution{}).Count(&noOpTaskCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.TaskExecution{}).Count(&noOpTaskCount).Error; err != nil {
t.Fatalf("count no-op checks error = %v, want nil", err)
}
if noOpTaskCount != taskCount {
@@ -275,7 +274,7 @@ func TestInitialCheckFailureUsesExactConfigFence(t *testing.T) {
RepositoryURL: "https://github.com/a/b",
})
staleVersion := source.ConfigVersion
if err := db.DB(ctx).Model(source).Update("config_version", staleVersion+1).Error; err != nil {
if err := repository.DB(ctx).Model(source).Update("config_version", staleVersion+1).Error; err != nil {
t.Fatalf("increment source config version error = %v, want nil", err)
}
markInitialCheckDispatchFailed(ctx, source.ID, staleVersion)
@@ -294,7 +293,7 @@ func TestGitHubCheckUsesETagAndDetectsSameReleaseReplacement(t *testing.T) {
})
appliedRevision := strings.Repeat("a", 64)
appliedDetail := `{"provider":"github","release_id":"100","asset_id":"1","tag":"release/v1","asset_name":"dist.zip"}`
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
"etag": `"old-etag"`,
"last_applied_revision": appliedRevision,
"last_applied_detail": appliedDetail,
@@ -375,7 +374,7 @@ func TestGitHubCheckNotModifiedRefreshesRuntimeWithoutDeployment(t *testing.T) {
t.Errorf("304 runtime = %+v, want refreshed timestamps/etag and released lease", runtime)
}
var deployments int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).Where("project_id = ?", project.ID).Count(&deployments).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).Where("project_id = ?", project.ID).Count(&deployments).Error; err != nil {
t.Fatalf("count deployments error = %v, want nil", err)
}
if deployments != 0 {
@@ -391,7 +390,7 @@ func TestGitHubTargetMismatchPreservesAttentionAndExpeditesRecheck(t *testing.T)
RepositoryURL: "https://github.com/a/b",
})
appliedRevision := strings.Repeat("a", 64)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
"last_applied_revision": appliedRevision,
"last_applied_detail": `{"provider":"github","release_id":"100","asset_id":"1","tag":"v1","asset_name":"dist.zip"}`,
}).Error; err != nil {
@@ -430,7 +429,7 @@ func TestGitHubTargetMismatchPreservesAttentionAndExpeditesRecheck(t *testing.T)
t.Errorf("target mismatch NextCheckAt = %v, want server deadline >= %v", runtime.NextCheckAt, retryAt)
}
var deployments int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).Where("project_id = ?", project.ID).Count(&deployments).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).Where("project_id = ?", project.ID).Count(&deployments).Error; err != nil {
t.Fatalf("count mismatch deployments error = %v, want nil", err)
}
if deployments != 0 {
@@ -454,7 +453,7 @@ func TestGitHubCheckLostLeaseReturnsStaleWithoutOverwritingRuntime(t *testing.T)
},
})
snapshot, _, _ := acquireSourceLease(ctx, source.ID, source.ConfigVersion, sourceActionCheck)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
"lease_token": "new-owner",
"lease_expires_at": time.Now().Add(time.Minute),
"sync_status": pagesSourceStatusSyncing,
@@ -741,7 +740,7 @@ func TestGitHubSyncActivatesExactConfirmedReplacement(t *testing.T) {
if err != nil {
t.Fatalf("buildGitHubSourceTarget() error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Updates(map[string]any{
"last_seen_revision": target.Revision,
"last_seen_detail": target.DetailJSON,
"last_applied_revision": strings.Repeat("a", 64),
@@ -320,6 +320,7 @@ func removePagesUploadIfUnreferenced(ctx context.Context, projectID uint, upload
if uploadID == 0 {
return nil
}
shouldRemove := false
err := repository.WithPagesTx(ctx, func(tx *gorm.DB) error {
if projectID != 0 {
if _, projectErr := repository.LockPagesProjectByIDTx(tx, projectID); projectErr != nil &&
@@ -350,13 +351,13 @@ func removePagesUploadIfUnreferenced(ctx context.Context, projectID uint, upload
if references > 0 {
return nil
}
_, err := ofupload.RemoveLockedTx(tx, &uploadRecord)
return err
shouldRemove = true
return nil
})
// Always invalidate after transaction completion, including idempotent no-op,
// so a prior post-commit cache interruption can heal on retry.
ofupload.InvalidateUploadMetaCache(ctx, uploadID)
return err
if err != nil || !shouldRemove {
return err
}
return ofupload.Remove(ctx, uploadID)
}
func inspectPagesPackage(packagePath string, format pagesarchive.Format, rootDir string, entryFile string, limits pagesLimits) (*deploymentManifest, error) {
@@ -1020,7 +1020,8 @@ func hydrateLegacyDeploymentUpload(
if deployment.UploadID > 0 {
uploadRecord, err := ofupload.GetActiveUpload(ctx, deployment.UploadID)
if err == nil {
return &uploadRecord, nil
record := model.FromUploadDTO(uploadRecord)
return &record, nil
}
}
@@ -1066,7 +1067,8 @@ func hydrateLegacyDeploymentUpload(
}
deployment.UploadID = winnerUploadID
deployment.ArtifactPath = ""
return &winner, nil
winnerRecord := model.FromUploadDTO(winner)
return &winnerRecord, nil
}
func attachLegacyDeploymentUpload(
@@ -23,8 +23,6 @@ import (
oftask "Wavelet/openflare/plugins/server/kernel/task"
"Wavelet/openflare/plugins/server/kernel/testhelper"
"Wavelet/pkg/idgen"
uploadshared "Wavelet/plugins/domain/upload/shared"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -39,6 +37,9 @@ func setupPagesTestDB(t *testing.T) func() {
DisableForeignKeyConstraintWhenMigrating: true,
})
require.NoError(t, err)
if sqlDB, err := sqliteDB.DB(); err == nil {
sqlDB.SetMaxOpenConns(1)
}
require.NoError(t, sqliteDB.AutoMigrate(
&model.User{},
&model.Upload{},
@@ -74,30 +75,33 @@ func setupPagesTestDB(t *testing.T) func() {
},
}).Error)
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
repository.SetSystemConfigService(testhelper.NewMockSystemConfigService(sqliteDB))
require.NoError(t, idgen.Init(1))
oftask.SetService(&testhelper.NoopTaskService{})
mockStorage := uploadshared.NewMockStorageService()
uploadshared.SetDBService(db.NewService(sqliteDB))
uploadshared.SetStorageService(mockStorage)
noopTask := &testhelper.NoopTaskService{}
oftask.SetService(noopTask)
repository.SetTaskService(noopTask)
mockStorage := testhelper.NewMockStorageService()
ofupload.SetStorage(mockStorage)
ofupload.SetUploadService(testhelper.NewMockUploadService(sqliteDB))
_ = repository.InvalidateSystemConfigCache(context.Background(), model.ConfigKeyPagesMaxPackageSizeMB)
_ = repository.InvalidateSystemConfigCache(context.Background(), model.ConfigKeyPagesMaxHistoryCount)
return func() {
ofupload.SetStorage(nil)
uploadshared.ResetServices()
db.SetDB(nil)
ofupload.SetUploadService(nil)
repository.SetTaskService(nil)
oftask.SetService(nil)
repository.SetSystemConfigService(nil)
repository.SetDBForTest(nil)
}
}
func setupPagesStorageMock(t *testing.T) (restore func(), disable func()) {
t.Helper()
mock := uploadshared.NewMockStorageService()
uploadshared.SetStorageService(mock)
mock := testhelper.NewMockStorageService()
ofupload.SetStorage(mock)
restore = func() {
ofupload.SetStorage(nil)
uploadshared.ResetServices()
}
disable = restore
return restore, disable
@@ -283,10 +287,10 @@ func TestUploadDeploymentStoresPackageInUploadFramework(t *testing.T) {
assert.Empty(t, storedDeployment.ArtifactPath)
var uploadCount int64
require.NoError(t, db.DB(ctx).Model(&model.Upload{}).Count(&uploadCount).Error)
require.NoError(t, repository.DB(ctx).Model(&model.Upload{}).Count(&uploadCount).Error)
assert.Equal(t, int64(1), uploadCount)
var uploadRecord model.Upload
require.NoError(t, db.DB(ctx).First(&uploadRecord, storedDeployment.UploadID).Error)
require.NoError(t, repository.DB(ctx).First(&uploadRecord, storedDeployment.UploadID).Error)
assert.Equal(t, ofupload.ReservedPagesDeploymentType, uploadRecord.Type)
assert.Equal(t, pagesIngestMarkerV2, uploadRecord.Metadata.Extra[pagesIngestMarkerKey])
assert.Equal(t, fmt.Sprint(project.ID), uploadRecord.Metadata.Extra[pagesProjectIDMetadataKey])
@@ -323,8 +327,8 @@ func TestOpenDeploymentPackageHydratesLegacyArtifactPath(t *testing.T) {
TotalSize: 10,
CreatedBy: "test",
}
require.NoError(t, db.DB(ctx).Create(deployment).Error)
require.NoError(t, db.DB(ctx).Create(&model.PagesDeploymentFile{
require.NoError(t, repository.DB(ctx).Create(deployment).Error)
require.NoError(t, repository.DB(ctx).Create(&model.PagesDeploymentFile{
DeploymentID: deployment.ID,
Path: "index.html",
Size: 6,
@@ -334,7 +338,7 @@ func TestOpenDeploymentPackageHydratesLegacyArtifactPath(t *testing.T) {
_, err = ActivateDeployment(ctx, project.ID, deployment.ID)
require.NoError(t, err)
require.NoError(t, db.DB(ctx).Create(&model.ConfigVersion{
require.NoError(t, repository.DB(ctx).Create(&model.ConfigVersion{
Version: "v2026-legacy",
SnapshotJSON: fmt.Sprintf(`{"routes":[{"upstream_type":"pages","pages_deployment":{"deployment_id":%d}}]}`, deployment.ID),
MainConfig: "",
@@ -363,7 +367,7 @@ func TestOpenDeploymentPackageHydratesLegacyArtifactPath(t *testing.T) {
assert.Empty(t, storedDeployment.ArtifactPath)
var uploadCount int64
require.NoError(t, db.DB(ctx).Model(&model.Upload{}).Count(&uploadCount).Error)
require.NoError(t, repository.DB(ctx).Model(&model.Upload{}).Count(&uploadCount).Error)
assert.Equal(t, int64(1), uploadCount)
packageObj2, err := OpenDeploymentPackage(ctx, deployment.ID)
@@ -400,7 +404,7 @@ func TestOpenDeploymentPackageRequiresActiveConfigSnapshot(t *testing.T) {
require.Error(t, err)
assert.Contains(t, err.Error(), "激活配置")
require.NoError(t, db.DB(ctx).Create(&model.ConfigVersion{
require.NoError(t, repository.DB(ctx).Create(&model.ConfigVersion{
Version: "v2026-001",
SnapshotJSON: fmt.Sprintf(`{"routes":[{"upstream_type":"pages","pages_deployment":{"deployment_id":%d}}]}`, deployment.ID),
MainConfig: "",
@@ -454,7 +458,7 @@ func TestProjectLatestRejectsWhenNotOnActiveConfigOrNotActive(t *testing.T) {
_, _, err = GetProjectLatestPackageHash(ctx, project.ID)
require.Error(t, err)
require.NoError(t, db.DB(ctx).Create(&model.ConfigVersion{
require.NoError(t, repository.DB(ctx).Create(&model.ConfigVersion{
Version: "v-gate",
SnapshotJSON: fmt.Sprintf(
`{"routes":[{"upstream_type":"pages","pages_project_id":%d,"pages_deployment":{"project_id":%d,"deployment_id":%d}}]}`,
@@ -476,7 +480,7 @@ func TestProjectLatestRejectsWhenNotOnActiveConfigOrNotActive(t *testing.T) {
assert.NotEmpty(t, hash)
// Disabled project rejects.
require.NoError(t, db.DB(ctx).Model(&model.PagesProject{}).Where("id = ?", project.ID).Update("enabled", false).Error)
require.NoError(t, repository.DB(ctx).Model(&model.PagesProject{}).Where("id = ?", project.ID).Update("enabled", false).Error)
_, _, err = GetProjectLatestPackageHash(ctx, project.ID)
require.Error(t, err)
}
@@ -572,7 +576,7 @@ func TestPruneProjectDeploymentHistory(t *testing.T) {
defer disableStorage()
ctx := context.Background()
require.NoError(t, db.DB(ctx).Model(&model.SystemConfig{}).
require.NoError(t, repository.DB(ctx).Model(&model.SystemConfig{}).
Where("key = ?", model.ConfigKeyPagesMaxHistoryCount).
Update("value", "2").Error)
require.NoError(t, repository.InvalidateSystemConfigCache(ctx, model.ConfigKeyPagesMaxHistoryCount))
@@ -634,7 +638,7 @@ func TestHistoryCountOnePreservesFreshCandidateUntilActivation(t *testing.T) {
defer disableStorage()
ctx := context.Background()
require.NoError(t, db.DB(ctx).Model(&model.SystemConfig{}).
require.NoError(t, repository.DB(ctx).Model(&model.SystemConfig{}).
Where("key = ?", model.ConfigKeyPagesMaxHistoryCount).
Update("value", "1").Error)
require.NoError(t, repository.InvalidateSystemConfigCache(ctx, model.ConfigKeyPagesMaxHistoryCount))
@@ -671,7 +675,7 @@ func TestHistoryCountOnePreservesFreshCandidateUntilActivation(t *testing.T) {
assert.True(t, kept[newCandidate.ID])
assert.False(t, kept[oldCandidate.ID])
var removedUpload model.Upload
require.NoError(t, db.DB(ctx).First(&removedUpload, oldCandidate.UploadID).Error)
require.NoError(t, repository.DB(ctx).First(&removedUpload, oldCandidate.UploadID).Error)
assert.Equal(t, model.UploadStatusDeleted, removedUpload.Status)
_, err = ActivateDeployment(ctx, project.ID, newCandidate.ID)
@@ -741,12 +745,12 @@ func TestDeleteDeploymentAndProjectSoftDeleteUnreferencedArtifacts(t *testing.T)
require.NoError(t, DeleteDeployment(ctx, project.ID, second.ID))
var secondUpload model.Upload
require.NoError(t, db.DB(ctx).First(&secondUpload, second.UploadID).Error)
require.NoError(t, repository.DB(ctx).First(&secondUpload, second.UploadID).Error)
assert.Equal(t, model.UploadStatusDeleted, secondUpload.Status)
require.NoError(t, DeleteProject(ctx, project.ID))
var firstUpload model.Upload
require.NoError(t, db.DB(ctx).First(&firstUpload, first.UploadID).Error)
require.NoError(t, repository.DB(ctx).First(&firstUpload, first.UploadID).Error)
assert.Equal(t, model.UploadStatusDeleted, firstUpload.Status)
_, err = repository.GetPagesProjectByID(ctx, project.ID)
assert.Error(t, err)
@@ -58,7 +58,7 @@ func GetProjectLatestPackageMetadata(ctx context.Context, projectID uint) (*Proj
return &ProjectLatestPackageMetadata{
DeploymentID: deployment.ID,
Hash: hash,
PackageSize: uploadRecord.FileSize,
PackageSize: uploadRecord.Size,
FileCount: deployment.FileCount,
TotalSize: deployment.TotalSize,
}, nil
@@ -11,7 +11,7 @@ import (
"testing"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/repository"
)
func TestGetProjectLatestPackageMetadataPreservesZeroTotalSize(t *testing.T) {
@@ -46,7 +46,7 @@ func TestGetProjectLatestPackageMetadataPreservesZeroTotalSize(t *testing.T) {
if _, err := ActivateDeployment(ctx, project.ID, deployment.ID); err != nil {
t.Fatalf("ActivateDeployment() error = %v", err)
}
if err := db.DB(ctx).Create(&model.ConfigVersion{
if err := repository.DB(ctx).Create(&model.ConfigVersion{
Version: "v-package-metadata",
SnapshotJSON: fmt.Sprintf(
`{"routes":[{"upstream_type":"pages","pages_project_id":%d}]}`,
@@ -9,7 +9,7 @@ import (
"testing"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/repository"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -36,7 +36,7 @@ func TestRebindSnapshotPagesToCurrentActive(t *testing.T) {
Status: model.PagesDeploymentStatusUploaded,
FileCount: 1,
}
require.NoError(t, db.DB(ctx).Create(old).Error)
require.NoError(t, repository.DB(ctx).Create(old).Error)
active := &model.PagesDeployment{
ProjectID: project.ID,
DeploymentNumber: 2,
@@ -44,8 +44,8 @@ func TestRebindSnapshotPagesToCurrentActive(t *testing.T) {
Status: model.PagesDeploymentStatusActive,
FileCount: 1,
}
require.NoError(t, db.DB(ctx).Create(active).Error)
require.NoError(t, db.DB(ctx).Model(&model.PagesProject{}).
require.NoError(t, repository.DB(ctx).Create(active).Error)
require.NoError(t, repository.DB(ctx).Model(&model.PagesProject{}).
Where("id = ?", project.ID).
Update("active_deployment_id", active.ID).Error)
@@ -15,8 +15,8 @@ import (
"Wavelet/core/contracts"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/testhelper"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
)
@@ -117,7 +117,7 @@ func TestPagesSourceHandlersReturnStableActionErrors(t *testing.T) {
false,
)
future := time.Now().Add(time.Minute)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", busySource.ID).
Updates(map[string]any{
"sync_status": pagesSourceStatusSyncing,
@@ -181,7 +181,7 @@ func TestSyncSourceHandlerAcceptsEmptyBodyAndEmptyObject(t *testing.T) {
}
var executions []model.TaskExecution
if err := db.DB(ctx).Where("task_type = ?", TaskTypePagesSourceAction).Order("id asc").Find(&executions).Error; err != nil {
if err := repository.DB(ctx).Where("task_type = ?", TaskTypePagesSourceAction).Order("id asc").Find(&executions).Error; err != nil {
t.Fatalf("list Pages source task executions error = %v, want nil", err)
}
if got, want := len(executions), 2; got != want {
@@ -131,7 +131,6 @@ func reconcilePagesOrphanUploadCandidate(
}
outcome := pagesOrphanCleanupSkipped
uploadLocked := false
err := repository.WithPagesTx(ctx, func(tx *gorm.DB) error {
scopeOutcome, proceed, err := lockPagesOrphanCleanupScope(ctx, tx, candidate.ID, marker)
if err != nil {
@@ -141,7 +140,7 @@ func reconcilePagesOrphanUploadCandidate(
outcome = scopeOutcome
return nil
}
lockedOutcome, locked, err := reconcileLockedPagesOrphanUpload(
lockedOutcome, _, err := reconcileLockedPagesOrphanUpload(
ctx,
tx,
candidate.ID,
@@ -153,16 +152,15 @@ func reconcilePagesOrphanUploadCandidate(
return err
}
outcome = lockedOutcome
uploadLocked = locked
return nil
})
if err != nil {
return pagesOrphanCleanupSkipped, err
}
if uploadLocked {
// Also heal a prior post-commit cache invalidation interruption when the
// status transition was an idempotent no-op.
ofupload.InvalidateUploadMetaCache(ctx, candidate.ID)
if outcome == pagesOrphanCleanupReconciled {
if err := ofupload.Remove(ctx, candidate.ID); err != nil {
return pagesOrphanCleanupSkipped, err
}
}
return outcome, nil
}
@@ -252,14 +250,7 @@ func reconcileLockedPagesOrphanUpload(
return pagesOrphanCleanupReferenced, true, nil
}
transitioned, err := ofupload.RemoveLockedTx(tx, &lockedUpload)
if err != nil {
return pagesOrphanCleanupSkipped, true, err
}
if transitioned {
return pagesOrphanCleanupReconciled, true, nil
}
return pagesOrphanCleanupSkipped, true, nil
return pagesOrphanCleanupReconciled, true, nil
}
func lockOptionalPagesCleanupRecord(
@@ -12,7 +12,7 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/ofupload"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/repository"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -164,7 +164,7 @@ func TestReconcilePagesOrphanUploadsSkipsBusyLeaseAndSourceMismatch(t *testing.T
project := createPagesOrphanProject(t, ctx, "busy-orphan")
source := createPagesOrphanSource(t, ctx, project.ID)
future := realNow.Add(time.Hour)
if err := db.DB(ctx).Create(&model.PagesProjectSourceRuntime{
if err := repository.DB(ctx).Create(&model.PagesProjectSourceRuntime{
SourceID: source.ID,
LeaseToken: "busy-worker",
LeaseExpiresAt: &future,
@@ -213,7 +213,7 @@ func TestReconcilePagesOrphanUploadsRejectsMalformedMarker(t *testing.T) {
metadata := candidate.Metadata
metadata.Extra[pagesProjectIDMetadataKey] = "01"
candidate.Metadata = metadata
if err := db.DB(ctx).Save(candidate).Error; err != nil {
if err := repository.DB(ctx).Save(candidate).Error; err != nil {
t.Fatalf("seed malformed candidate marker error = %v, want nil", err)
}
@@ -239,7 +239,7 @@ func TestPagesOrphanCleanupAndDeploymentCommitInterleavings(t *testing.T) {
if err != nil {
t.Fatalf("parsePagesOrphanMarker() error = %v, want nil", err)
}
if err := db.DB(ctx).Create(&model.PagesDeployment{
if err := repository.DB(ctx).Create(&model.PagesDeployment{
ProjectID: project.ID,
DeploymentNumber: 1,
Checksum: "deployment-first",
@@ -276,7 +276,7 @@ func TestPagesOrphanCleanupAndDeploymentCommitInterleavings(t *testing.T) {
}
target := &model.PagesDeployment{ProjectID: project.ID, UploadID: candidate.ID}
err = db.DB(ctx).Transaction(func(tx *gorm.DB) error {
err = repository.DB(ctx).Transaction(func(tx *gorm.DB) error {
var lockedProject model.PagesProject
if err := tx.Clauses(clause.Locking{Strength: pagesRowLockStrength}).First(&lockedProject, project.ID).Error; err != nil {
return err
@@ -287,7 +287,7 @@ func TestPagesOrphanCleanupAndDeploymentCommitInterleavings(t *testing.T) {
t.Errorf("final deployment upload lock after cleanup error = %v, want %v", err, errSourceFinalFence)
}
var references int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).Where("upload_id = ?", candidate.ID).Count(&references).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).Where("upload_id = ?", candidate.ID).Count(&references).Error; err != nil {
t.Fatalf("count deployment references error = %v, want nil", err)
}
if references != 0 {
@@ -303,7 +303,7 @@ func cleanupOutcomeTotal(summary PagesOrphanCleanupSummary) int {
func createPagesOrphanProject(t *testing.T, ctx context.Context, slug string) *model.PagesProject {
t.Helper()
project := &model.PagesProject{Name: slug, Slug: slug, Enabled: true}
if err := db.DB(ctx).Create(project).Error; err != nil {
if err := repository.DB(ctx).Create(project).Error; err != nil {
t.Fatalf("create Pages orphan project %q error = %v, want nil", slug, err)
}
return project
@@ -317,7 +317,7 @@ func createPagesOrphanSource(t *testing.T, ctx context.Context, projectID uint)
ConfigVersion: 1,
SourceIdentity: "orphan-source-identity",
}
if err := db.DB(ctx).Create(source).Error; err != nil {
if err := repository.DB(ctx).Create(source).Error; err != nil {
t.Fatalf("create Pages orphan source for project %d error = %v, want nil", projectID, err)
}
return source
@@ -339,21 +339,19 @@ func createPagesOrphanUpload(
extra[pagesSourceIDMetadataKey] = strconv.FormatUint(uint64(*sourceID), 10)
}
candidate := &model.Upload{
UserID: 999,
FileName: "site.zip",
FilePath: "pages/orphan-site.zip",
FileSize: 64,
MimeType: "application/zip",
Extension: "zip",
Hash: "orphan-checksum",
Type: ofupload.ReservedPagesDeploymentType,
Status: model.UploadStatusUsed,
AccessMode: 0,
Metadata: model.UploadMetadata{Extra: extra},
CreatedAt: createdAt,
UpdatedAt: createdAt,
UserID: 999,
FileName: "site.zip",
FilePath: "pages/orphan-site.zip",
Size: 64,
MimeType: "application/zip",
Hash: "orphan-checksum",
Type: ofupload.ReservedPagesDeploymentType,
Status: model.UploadStatusUsed,
Metadata: model.UploadMetadata{Extra: extra},
CreatedAt: createdAt,
UpdatedAt: createdAt,
}
if err := db.DB(ctx).Create(candidate).Error; err != nil {
if err := repository.DB(ctx).Table("w_uploads").Create(candidate).Error; err != nil {
t.Fatalf("create Pages orphan upload error = %v, want nil", err)
}
return candidate
@@ -362,7 +360,7 @@ func createPagesOrphanUpload(
func assertPagesCleanupUploadStatus(t *testing.T, ctx context.Context, uploadID uint64, want model.UploadStatus) {
t.Helper()
var got model.Upload
if err := db.DB(ctx).First(&got, uploadID).Error; err != nil {
if err := repository.DB(ctx).Table("w_uploads").First(&got, uploadID).Error; err != nil {
t.Fatalf("load upload %d error = %v, want nil", uploadID, err)
}
if got.Status != want {
@@ -373,10 +371,10 @@ func assertPagesCleanupUploadStatus(t *testing.T, ctx context.Context, uploadID
func assertPagesCleanupTotalStat(t *testing.T, ctx context.Context, want int64) {
t.Helper()
var stat model.UploadStat
if err := db.DB(ctx).Where("dimension = ? AND stat_key = ?", model.UploadStatDimensionTotal, "").First(&stat).Error; err != nil {
if err := repository.DB(ctx).Where("dimension = ?", model.UploadStatDimensionTotal).First(&stat).Error; err != nil {
t.Fatalf("load total upload stat error = %v, want nil", err)
}
if stat.FileCount != want {
if int64(stat.FileCount) != want {
t.Errorf("total upload stat FileCount = %d, want %d", stat.FileCount, want)
}
}
@@ -13,7 +13,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
)
func TestSourceLeaseHeartbeatRenewsAndCancelsOnOwnershipLoss(t *testing.T) {
@@ -38,7 +37,7 @@ func TestSourceLeaseHeartbeatRenewsAndCancelsOnOwnershipLoss(t *testing.T) {
t.Cleanup(func() { _ = heartbeat.stop() })
var initial model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&initial).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&initial).Error; err != nil {
t.Fatalf("load initial heartbeat runtime error = %v, want nil", err)
}
if initial.LeaseExpiresAt == nil {
@@ -47,7 +46,7 @@ func TestSourceLeaseHeartbeatRenewsAndCancelsOnOwnershipLoss(t *testing.T) {
deadline := time.Now().Add(2 * time.Second)
for {
var renewedRuntime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&renewedRuntime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&renewedRuntime).Error; err != nil {
t.Fatalf("load renewed heartbeat runtime error = %v, want nil", err)
}
if renewedRuntime.LeaseExpiresAt != nil && renewedRuntime.LeaseExpiresAt.After(*initial.LeaseExpiresAt) {
@@ -59,7 +58,7 @@ func TestSourceLeaseHeartbeatRenewsAndCancelsOnOwnershipLoss(t *testing.T) {
time.Sleep(10 * time.Millisecond)
}
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Update("lease_token", "replacement-owner").Error; err != nil {
t.Fatalf("replace heartbeat lease owner error = %v, want nil", err)
@@ -166,7 +165,7 @@ func TestAcquireSourceLeaseMutualExclusionExpiryAndTerminalOwnership(t *testing.
}
past := time.Now().Add(-time.Second)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Update("lease_expires_at", &past).Error; err != nil {
t.Fatalf("expire first lease error = %v, want nil", err)
@@ -196,7 +195,7 @@ func TestAcquireSourceLeaseMutualExclusionExpiryAndTerminalOwnership(t *testing.
t.Fatalf("failSourceLease(expired owner) error = %v, want nil", err)
}
var runtime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
t.Fatalf("load runtime after takeover error = %v, want nil", err)
}
if got, want := runtime.LeaseToken, takeover.LeaseToken; got != want {
@@ -217,7 +216,7 @@ func TestAcquireSourceLeaseMutualExclusionExpiryAndTerminalOwnership(t *testing.
t.Fatalf("failSourceLease(current owner) error = %v, want nil", err)
}
var failedRuntime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&failedRuntime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&failedRuntime).Error; err != nil {
t.Fatalf("load failed runtime error = %v, want nil", err)
}
if got, want := failedRuntime.SyncStatus, pagesSourceStatusFailed; got != want {
@@ -258,7 +257,7 @@ func TestSourceConfigAndProjectContentChangesFenceLease(t *testing.T) {
t.Error("renewSourceLease(after source update) = true, want false")
}
var updatedSource model.PagesProjectSource
if err := db.DB(ctx).Where("id = ?", source.ID).First(&updatedSource).Error; err != nil {
if err := repository.DB(ctx).Where("id = ?", source.ID).First(&updatedSource).Error; err != nil {
t.Fatalf("load updated source error = %v, want nil", err)
}
if got, want := updatedSource.ConfigVersion, source.ConfigVersion+1; got != want {
@@ -296,7 +295,7 @@ func TestSourceConfigAndProjectContentChangesFenceLease(t *testing.T) {
t.Errorf("ContentConfigVersion after RootDir update = %d, want %d", got, want)
}
var runtime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
t.Fatalf("load fenced runtime error = %v, want nil", err)
}
if runtime.LeaseToken != "" || runtime.LeaseExpiresAt != nil {
@@ -19,7 +19,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/share/githubrelease"
db "Wavelet/plugins/infra/database"
"gorm.io/gorm"
)
@@ -42,7 +41,7 @@ func TestGitHubLatestAutoConfigPreservesIdentityAndRuntimeCursor(t *testing.T) {
seenRevision := strings.Repeat("a", sourceRevisionHexLength)
appliedRevision := strings.Repeat("b", sourceRevisionHexLength)
future := time.Now().Add(time.Hour)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Updates(map[string]any{
"etag": `"cursor-etag"`,
@@ -67,7 +66,7 @@ func TestGitHubLatestAutoConfigPreservesIdentityAndRuntimeCursor(t *testing.T) {
if err := validateGitHubSourceInput(input); err != nil {
t.Fatalf("validateGitHubSourceInput(auto latest) error = %v, want nil", err)
}
if err := db.DB(ctx).Transaction(func(tx *gorm.DB) error {
if err := repository.DB(ctx).Transaction(func(tx *gorm.DB) error {
changed, err := updateGitHubSourceTx(tx, project.ID, input)
if err == nil && !changed {
return errors.New("auto config update was treated as no-op")
@@ -132,7 +131,7 @@ func TestRecoverExpiredPagesSourceLeaseUsesExactCASAndStableJitter(t *testing.T)
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
usePagesSourceScannerClock(t, now)
expiredAt := now.Add(-time.Minute)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Updates(map[string]any{
"sync_status": pagesSourceStatusChecking,
@@ -167,7 +166,7 @@ func TestRecoverExpiredPagesSourceLeaseUsesExactCASAndStableJitter(t *testing.T)
}
renewedExpiry := now.Add(time.Minute)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Updates(map[string]any{
"sync_status": pagesSourceStatusSyncing,
@@ -274,24 +273,24 @@ func TestPagesSourceScannerSerialBatchIsolation304AndActualBacklog(t *testing.T)
byRepository := make(map[string]int, 22)
for index := 1; index <= 22; index++ {
project := mustCreatePagesSourceProject(t, ctx, fmt.Sprintf("scanner-batch-%02d", index))
repository := fmt.Sprintf("scanner/source-%02d", index)
repoPath := fmt.Sprintf("scanner/source-%02d", index)
source, runtime := mustConfigureGitHubSourceWithoutDispatch(t, ctx, project.ID, SourceUpdateInput{
SourceType: PagesSourceTypeGitHubRelease,
RepositoryURL: "https://github.com/" + repository,
RepositoryURL: "https://github.com/" + repoPath,
AutoUpdateEnabled: index != 4,
CheckIntervalMinutes: 60,
})
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Update("next_check_at", &dueAt).Error; err != nil {
t.Fatalf("mark source %d due error = %v, want nil", source.ID, err)
}
fixtures = append(fixtures, fixture{source: source, runtime: runtime, repository: repository})
byRepository[repository] = index
fixtures = append(fixtures, fixture{source: source, runtime: runtime, repository: repoPath})
byRepository[repoPath] = index
}
busyUntil := now.Add(time.Hour)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", fixtures[0].source.ID).
Updates(map[string]any{
"sync_status": pagesSourceStatusChecking,
@@ -302,7 +301,7 @@ func TestPagesSourceScannerSerialBatchIsolation304AndActualBacklog(t *testing.T)
}
stored304Revision := strings.Repeat("3", sourceRevisionHexLength)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", fixtures[2].source.ID).
Updates(map[string]any{
"etag": `"stored-etag"`,
@@ -313,7 +312,7 @@ func TestPagesSourceScannerSerialBatchIsolation304AndActualBacklog(t *testing.T)
t.Fatalf("seed 304 cursor error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", fixtures[4].source.ID).
Updates(map[string]any{
"last_applied_revision": strings.Repeat("a", sourceRevisionHexLength),
@@ -22,7 +22,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/ofupload"
"Wavelet/openflare/share/pagesarchive"
db "Wavelet/plugins/infra/database"
"gorm.io/gorm"
)
@@ -160,7 +159,7 @@ func TestSyncRemoteSourceAtomicallyActivatesAndReusesChecksum(t *testing.T) {
t.Errorf("deployment provenance = label:%q meta:%q, want no query secret", deployment.SourceLabel, deployment.SourceMeta)
}
var runtime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
t.Fatalf("load source runtime error = %v, want nil", err)
}
if got, want := runtime.SyncStatus, pagesSourceStatusIdle; got != want {
@@ -173,7 +172,7 @@ func TestSyncRemoteSourceAtomicallyActivatesAndReusesChecksum(t *testing.T) {
t.Errorf("runtime lease = (%q, %v), want cleared", runtime.LeaseToken, runtime.LeaseExpiresAt)
}
var uploadRecord model.Upload
if err := db.DB(ctx).First(&uploadRecord, deployment.UploadID).Error; err != nil {
if err := repository.DB(ctx).First(&uploadRecord, deployment.UploadID).Error; err != nil {
t.Fatalf("load deployment upload %d error = %v, want nil", deployment.UploadID, err)
}
if got, want := uploadRecord.Status, model.UploadStatusUsed; got != want {
@@ -198,10 +197,10 @@ func TestSyncRemoteSourceAtomicallyActivatesAndReusesChecksum(t *testing.T) {
t.Errorf("reused deployment ID = %d, want %d", got, want)
}
var deploymentCount, uploadCount int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).Where("project_id = ?", project.ID).Count(&deploymentCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).Where("project_id = ?", project.ID).Count(&deploymentCount).Error; err != nil {
t.Fatalf("count source deployments error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.Upload{}).Count(&uploadCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.Upload{}).Count(&uploadCount).Error; err != nil {
t.Fatalf("count source uploads error = %v, want nil", err)
}
if got, want := deploymentCount, int64(1); got != want {
@@ -267,7 +266,7 @@ func TestSyncRemoteSourceFinalFenceCompensatesIngest(t *testing.T) {
packageBytes := testPagesZip(t, map[string]string{"index.html": "never-activate"})
mutationResult := make(chan error, 1)
server := newPagesArchiveServer(t, http.StatusOK, packageBytes, func() error {
err := db.DB(context.Background()).Model(&model.PagesProject{}).
err := repository.DB(context.Background()).Model(&model.PagesProject{}).
Where("id = ?", project.ID).
Update("content_config_version", gorm.Expr("content_config_version + 1")).Error
mutationResult <- err
@@ -304,14 +303,14 @@ func TestSyncRemoteSourceFinalFenceCompensatesIngest(t *testing.T) {
t.Errorf("ActiveDeploymentID after final fence = %v, want %d", storedProject.ActiveDeploymentID, oldActive.ID)
}
var deployments []model.PagesDeployment
if err := db.DB(ctx).Where("project_id = ?", project.ID).Find(&deployments).Error; err != nil {
if err := repository.DB(ctx).Where("project_id = ?", project.ID).Find(&deployments).Error; err != nil {
t.Fatalf("list deployments after final fence error = %v, want nil", err)
}
if got, want := len(deployments), 1; got != want {
t.Errorf("deployment count after final fence = %d, want %d", got, want)
}
var uploads []model.Upload
if err := db.DB(ctx).Order("id asc").Find(&uploads).Error; err != nil {
if err := repository.DB(ctx).Order("id asc").Find(&uploads).Error; err != nil {
t.Fatalf("list uploads after final fence error = %v, want nil", err)
}
var compensated *model.Upload
@@ -328,7 +327,7 @@ func TestSyncRemoteSourceFinalFenceCompensatesIngest(t *testing.T) {
t.Errorf("compensated upload Status = %q, want %q", got, want)
}
var danglingCount int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).
Where("upload_id = ?", compensated.ID).
Count(&danglingCount).Error; err != nil {
t.Fatalf("count compensated upload references error = %v, want nil", err)
@@ -358,12 +357,12 @@ func TestCommitSourceDeploymentRechecksLeaseAfterUploadLocks(t *testing.T) {
if err != nil {
t.Fatalf("GetPagesDeploymentByID(%d) error = %v, want nil", first.Deployment.ID, err)
}
if err := db.DB(ctx).Model(&model.PagesProject{}).
if err := repository.DB(ctx).Model(&model.PagesProject{}).
Where("id = ?", project.ID).
Update("active_deployment_id", nil).Error; err != nil {
t.Fatalf("clear active deployment error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.PagesDeployment{}).
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).
Where("id = ?", deployment.ID).
Update("status", model.PagesDeploymentStatusUploaded).Error; err != nil {
t.Fatalf("reset deployment status error = %v, want nil", err)
@@ -371,7 +370,7 @@ func TestCommitSourceDeploymentRechecksLeaseAfterUploadLocks(t *testing.T) {
snapshot := mustAcquireRemoteSyncLease(t, ctx, source)
expiresAt := time.Now().Add(time.Hour)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ? AND lease_token = ?", source.ID, snapshot.LeaseToken).
Update("lease_expires_at", &expiresAt).Error; err != nil {
t.Fatalf("set deterministic lease expiry error = %v, want nil", err)
@@ -465,7 +464,7 @@ func TestCompensateSourceIngestSurvivesCanceledParentContext(t *testing.T) {
})
var uploadRecord model.Upload
if err := db.DB(ctx).Where("id = ?", result.Upload.ID).First(&uploadRecord).Error; err != nil {
if err := repository.DB(ctx).Where("id = ?", result.Upload.ID).First(&uploadRecord).Error; err != nil {
t.Fatalf("load compensated upload error = %v, want nil", err)
}
if got, want := uploadRecord.Status, model.UploadStatusDeleted; got != want {
@@ -490,7 +489,7 @@ func assertPagesSyncFailureState(
t.Errorf("project %d ActiveDeploymentID = %v, want %d", projectID, project.ActiveDeploymentID, oldActiveID)
}
var deploymentCount int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).
Where("project_id = ?", projectID).
Count(&deploymentCount).Error; err != nil {
t.Fatalf("count project %d deployments error = %v, want nil", projectID, err)
@@ -499,7 +498,7 @@ func assertPagesSyncFailureState(
t.Errorf("project %d deployment count = %d, want %d", projectID, got, want)
}
var runtime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", sourceID).First(&runtime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", sourceID).First(&runtime).Error; err != nil {
t.Fatalf("load source %d runtime error = %v, want nil", sourceID, err)
}
if got, want := runtime.SyncStatus, pagesSourceStatusFailed; got != want {
@@ -529,19 +528,17 @@ func TestCommitSourceDeploymentRejectsDeletedTargetUpload(t *testing.T) {
identity := source.SourceIdentity
revision := strings.Repeat("d", 64)
uploadRecord := &model.Upload{
ID: 987654321,
UserID: 999,
FileName: "deleted.zip",
FilePath: "deleted.zip",
FileSize: 1,
MimeType: "application/zip",
Extension: "zip",
Hash: revision,
Type: ofupload.ReservedPagesDeploymentType,
Status: model.UploadStatusDeleted,
AccessMode: 0,
ID: 987654321,
UserID: 999,
FileName: "deleted.zip",
FilePath: "deleted.zip",
Size: 1,
MimeType: "application/zip",
Hash: revision,
Type: ofupload.ReservedPagesDeploymentType,
Status: model.UploadStatusDeleted,
}
if err := db.DB(ctx).Create(uploadRecord).Error; err != nil {
if err := repository.DB(ctx).Table("w_uploads").Create(uploadRecord).Error; err != nil {
t.Fatalf("create deleted upload error = %v, want nil", err)
}
deployment := &model.PagesDeployment{
@@ -560,10 +557,10 @@ func TestCommitSourceDeploymentRejectsDeletedTargetUpload(t *testing.T) {
SourceMeta: `{"provider":"remote_url","display_name":"deleted.zip"}`,
TriggerType: pagesSourceTriggerManualSync,
}
if err := db.DB(ctx).Create(deployment).Error; err != nil {
if err := repository.DB(ctx).Create(deployment).Error; err != nil {
t.Fatalf("create source deployment error = %v, want nil", err)
}
if err := db.DB(ctx).Create(&model.PagesDeploymentFile{
if err := repository.DB(ctx).Create(&model.PagesDeploymentFile{
DeploymentID: deployment.ID,
Path: "index.html",
Size: 1,
@@ -600,7 +597,7 @@ func TestCommitSourceDeploymentRejectsDeletedTargetUpload(t *testing.T) {
t.Errorf("ActiveDeploymentID after deleted upload rejection = %v, want nil", storedProject.ActiveDeploymentID)
}
var activeCount int64
if err := db.DB(ctx).Model(&model.PagesDeployment{}).
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).
Where("project_id = ? AND status = ?", project.ID, model.PagesDeploymentStatusActive).
Count(&activeCount).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
t.Fatalf("count active deployments error = %v, want nil", err)
@@ -13,16 +13,15 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
)
func setupPagesSourceTest(t *testing.T) context.Context {
t.Helper()
cleanup := setupPagesTestDB(t)
t.Cleanup(cleanup)
sqlDB, err := db.DB(t.Context()).DB()
sqlDB, err := repository.DB(t.Context()).DB()
if err != nil {
t.Fatalf("db.DB().DB() error = %v, want nil", err)
t.Fatalf("repository.DB().DB() error = %v, want nil", err)
}
// SQLite :memory: is scoped to one connection. Keeping one connection also
// makes lease tests exercise the production CAS without creating empty
@@ -93,11 +92,11 @@ func mustConfigureRemoteSource(
t.Fatalf("UpdateSource(%d, %q) error = %v, want nil", projectID, remoteURL, err)
}
var source model.PagesProjectSource
if err := db.DB(ctx).Where("project_id = ?", projectID).First(&source).Error; err != nil {
if err := repository.DB(ctx).Where("project_id = ?", projectID).First(&source).Error; err != nil {
t.Fatalf("load source for project %d error = %v, want nil", projectID, err)
}
var runtime model.PagesProjectSourceRuntime
if err := db.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
if err := repository.DB(ctx).Where("source_id = ?", source.ID).First(&runtime).Error; err != nil {
t.Fatalf("load runtime for source %d error = %v, want nil", source.ID, err)
}
return &source, &runtime
@@ -187,7 +186,7 @@ func TestRemoteSourceCRUDPreservesSecretAndResetsRuntimeByIdentity(t *testing.T)
t.Fatalf("UpdateSource(%d, no-op) error = %v, want nil", project.ID, err)
}
var unchangedSource model.PagesProjectSource
if err := db.DB(ctx).Where("id = ?", source.ID).First(&unchangedSource).Error; err != nil {
if err := repository.DB(ctx).Where("id = ?", source.ID).First(&unchangedSource).Error; err != nil {
t.Fatalf("load no-op source error = %v, want nil", err)
}
if got, want := unchangedSource.ConfigVersion, source.ConfigVersion; got != want {
@@ -197,7 +196,7 @@ func TestRemoteSourceCRUDPreservesSecretAndResetsRuntimeByIdentity(t *testing.T)
seenRevision := strings.Repeat("a", 64)
appliedRevision := strings.Repeat("b", 64)
future := time.Now().Add(time.Hour)
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).
Where("source_id = ?", source.ID).
Updates(map[string]any{
"last_seen_revision": seenRevision,
@@ -327,10 +326,10 @@ func TestDeleteSourceIsIdempotentAndKeepsDeploymentState(t *testing.T) {
SourceType: "manual_upload",
TriggerType: "manual_upload",
}
if err := db.DB(ctx).Create(deployment).Error; err != nil {
if err := repository.DB(ctx).Create(deployment).Error; err != nil {
t.Fatalf("create deployment error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.PagesProject{}).
if err := repository.DB(ctx).Model(&model.PagesProject{}).
Where("id = ?", project.ID).
Update("active_deployment_id", deployment.ID).Error; err != nil {
t.Fatalf("set active deployment error = %v, want nil", err)
@@ -346,13 +345,13 @@ func TestDeleteSourceIsIdempotentAndKeepsDeploymentState(t *testing.T) {
}
}
var sourceCount, runtimeCount, deploymentCount int64
if err := db.DB(ctx).Model(&model.PagesProjectSource{}).Where("id = ?", source.ID).Count(&sourceCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesProjectSource{}).Where("id = ?", source.ID).Count(&sourceCount).Error; err != nil {
t.Fatalf("count source error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Count(&runtimeCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesProjectSourceRuntime{}).Where("source_id = ?", source.ID).Count(&runtimeCount).Error; err != nil {
t.Fatalf("count runtime error = %v, want nil", err)
}
if err := db.DB(ctx).Model(&model.PagesDeployment{}).Where("id = ?", deployment.ID).Count(&deploymentCount).Error; err != nil {
if err := repository.DB(ctx).Model(&model.PagesDeployment{}).Where("id = ?", deployment.ID).Count(&deploymentCount).Error; err != nil {
t.Fatalf("count deployment error = %v, want nil", err)
}
if sourceCount != 0 || runtimeCount != 0 || deploymentCount != 1 {
@@ -11,7 +11,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -29,10 +28,10 @@ func setupApplyLogTestDB(t *testing.T) func() {
err = sqliteDB.AutoMigrate(&model.OpenFlareApplyLog{})
require.NoError(t, err)
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -49,7 +48,7 @@ func TestListPageAndCleanup(t *testing.T) {
{NodeID: "node-logs", Version: "v3", Result: "success", Message: "3", CreatedAt: now},
}
for i := range logs {
require.NoError(t, db.DB(ctx).Create(&logs[i]).Error)
require.NoError(t, repository.DB(ctx).Create(&logs[i]).Error)
}
pageResult, err := ListPage(ctx, ListQuery{
@@ -20,7 +20,6 @@ import (
oftls "Wavelet/openflare/plugins/server/domain/tls"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/runtimeconfig"
db "Wavelet/plugins/infra/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -29,7 +28,7 @@ import (
func TestBuildCertificateSupportFilesDecryptsSealedPrivateKey(t *testing.T) {
cleanup := setupConfigVersionTestDB(t)
defer cleanup()
require.NoError(t, db.DB(context.Background()).AutoMigrate(&model.TLSCertificate{}))
require.NoError(t, repository.DB(context.Background()).AutoMigrate(&model.TLSCertificate{}))
previous := runtimeconfig.Get()
runtimeconfig.SetSessionSecret("test-session-secret-for-tls-seal")
@@ -65,7 +64,7 @@ func TestBuildSnapshotReadsZoneDomainCertificates(t *testing.T) {
cleanup := setupConfigVersionTestDB(t)
defer cleanup()
ctx := context.Background()
require.NoError(t, db.DB(ctx).AutoMigrate(&model.TLSCertificate{}))
require.NoError(t, repository.DB(ctx).AutoMigrate(&model.TLSCertificate{}))
previous := runtimeconfig.Get()
runtimeconfig.SetSessionSecret("test-session-secret-for-zone-domain-snapshots")
@@ -81,9 +80,9 @@ func TestBuildSnapshotReadsZoneDomainCertificates(t *testing.T) {
route := &model.ProxyRoute{SiteName: "tls-site", OriginURL: "http://origin:8080", Upstreams: `["http://origin:8080"]`, Enabled: true, EnableHTTPS: true}
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
zone := &model.Zone{Domain: "example.com"}
require.NoError(t, db.DB(ctx).Create(zone).Error)
require.NoError(t, db.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, ProxyRouteID: &route.ID, Domain: "one.example.com", CertID: &first.ID}).Error)
require.NoError(t, db.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, ProxyRouteID: &route.ID, Domain: "two.example.com", CertID: &second.ID}).Error)
require.NoError(t, repository.DB(ctx).Create(zone).Error)
require.NoError(t, repository.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, ProxyRouteID: &route.ID, Domain: "one.example.com", CertID: &first.ID}).Error)
require.NoError(t, repository.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, ProxyRouteID: &route.ID, Domain: "two.example.com", CertID: &second.ID}).Error)
bundle, err := buildCurrentConfigBundle(ctx, true)
require.NoError(t, err)
@@ -16,7 +16,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
openrestyrender "Wavelet/openflare/share/render/openresty"
"Wavelet/pkg/cache/ram"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -45,9 +44,9 @@ func setupConfigVersionTestDB(t *testing.T) func() {
&model.SystemConfig{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
ram.ResetForTest()
}
}
@@ -55,9 +54,9 @@ func setupConfigVersionTestDB(t *testing.T) func() {
func createSnapshotZoneDomains(t *testing.T, ctx context.Context, route *model.ProxyRoute, domains ...string) {
t.Helper()
zone := &model.Zone{Domain: fmt.Sprintf("zone-%d.example", route.ID)}
require.NoError(t, db.DB(ctx).Create(zone).Error)
require.NoError(t, repository.DB(ctx).Create(zone).Error)
for _, domain := range domains {
require.NoError(t, db.DB(ctx).Create(&model.ZoneDomain{
require.NoError(t, repository.DB(ctx).Create(&model.ZoneDomain{
ZoneID: zone.ID,
ProxyRouteID: &route.ID,
Domain: domain,
@@ -69,7 +68,7 @@ func TestListConfigVersionsOrdersByCreatedAtDesc(t *testing.T) {
cleanup := setupConfigVersionTestDB(t)
defer cleanup()
ctx := context.Background()
conn := db.DB(ctx)
conn := repository.DB(ctx)
require.NotNil(t, conn)
newer := &model.ConfigVersion{
@@ -220,7 +219,7 @@ func TestBuildCurrentConfigBundleEnablesGlobalPoWWithoutExplicitBinding(t *testi
graphJSON, err := json.Marshal(snapshotPoWGraph())
require.NoError(t, err)
globalGroup.Graph = string(graphJSON)
require.NoError(t, db.DB(ctx).Model(globalGroup).Update("graph", globalGroup.Graph).Error)
require.NoError(t, repository.DB(ctx).Model(globalGroup).Update("graph", globalGroup.Graph).Error)
bundle, err := buildCurrentConfigBundle(ctx, true)
require.NoError(t, err)
@@ -9,13 +9,12 @@ import (
"testing"
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/testhelper"
"Wavelet/pkg/cache/ram"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
func setupOriginErrorPageSnapshotDB(t *testing.T) func() {
@@ -25,15 +24,10 @@ func setupOriginErrorPageSnapshotDB(t *testing.T) func() {
// 重置,否则 shuffle 下先跑的用例会污染后跑的用例。
ram.ResetForTest()
sqliteDB, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
})
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.SystemConfig{}))
db.SetDB(sqliteDB)
_, _, cleanup := testhelper.SetupTestEnvironment(t)
return func() {
db.SetDB(nil)
cleanup()
ram.ResetForTest()
}
}
@@ -58,15 +52,9 @@ func TestBuildOpenRestyConfigSnapshotOriginErrorPageCustom(t *testing.T) {
defer cleanup()
ctx := context.Background()
require.NoError(t, db.DB(ctx).Create(&model.SystemConfig{
Key: model.ConfigKeyOriginErrorPageEnabled, Value: "false", Type: "business",
}).Error)
require.NoError(t, db.DB(ctx).Create(&model.SystemConfig{
Key: model.ConfigKeyOriginErrorPageStatusCodes, Value: `["522","500-502"]`, Type: "business",
}).Error)
require.NoError(t, db.DB(ctx).Create(&model.SystemConfig{
Key: model.ConfigKeyOriginErrorPageHTML, Value: "<h1>{{status}}</h1>", Type: "business",
}).Error)
require.NoError(t, repository.SaveOrUpdateSystemConfig(ctx, model.ConfigKeyOriginErrorPageEnabled, "false"))
require.NoError(t, repository.SaveOrUpdateSystemConfig(ctx, model.ConfigKeyOriginErrorPageStatusCodes, `["522","500-502"]`))
require.NoError(t, repository.SaveOrUpdateSystemConfig(ctx, model.ConfigKeyOriginErrorPageHTML, "<h1>{{status}}</h1>"))
snapshot := buildOpenRestyConfigSnapshot(ctx)
assert.False(t, snapshot.OriginErrorPageEnabled)
@@ -12,7 +12,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
openrestyrender "Wavelet/openflare/share/render/openresty"
db "Wavelet/plugins/infra/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -95,7 +94,7 @@ func TestBuildSnapshotPagesDeploymentRejectsUnsafeStoredPaths(t *testing.T) {
func requireDB(t *testing.T, ctx context.Context) *gorm.DB {
t.Helper()
conn := db.DB(ctx)
conn := repository.DB(ctx)
require.NotNil(t, conn)
require.NoError(t, conn.AutoMigrate(
&model.PagesProject{},
@@ -13,7 +13,6 @@ import (
"Wavelet/openflare/plugins/server/domain/waf"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -38,7 +37,7 @@ func TestBuildSnapshotRejectsOversizedAggregateWAFIPGroups(t *testing.T) {
Enabled: true,
IPList: string(ipList),
}
require.NoError(t, db.DB(ctx).Create(group).Error)
require.NoError(t, repository.DB(ctx).Create(group).Error)
groupIDs = append(groupIDs, group.ID)
}
createSnapshotRule(t, ctx, "oversized-aggregate", snapshotIPMatchGraphForGroups(groupIDs))
@@ -59,8 +58,8 @@ func TestWAFGraphSnapshotPreservesOrderAndGraphReferences(t *testing.T) {
referenced := &model.OpenFlareWAFIPGroup{Name: "referenced", Type: "manual", Enabled: true, IPList: `["192.0.2.1"]`}
unused := &model.OpenFlareWAFIPGroup{Name: "unused", Type: "manual", Enabled: true, IPList: `["198.51.100.1"]`}
require.NoError(t, db.DB(ctx).Create(referenced).Error)
require.NoError(t, db.DB(ctx).Create(unused).Error)
require.NoError(t, repository.DB(ctx).Create(referenced).Error)
require.NoError(t, repository.DB(ctx).Create(unused).Error)
customA := createSnapshotRule(t, ctx, "custom-a", waf.DefaultRuleGraph())
customB := createSnapshotRule(t, ctx, "custom-b", snapshotIPMatchGraph(referenced.ID))
@@ -114,7 +113,7 @@ func TestBuildSnapshotRejectsInvalidWAFGraph(t *testing.T) {
ctx := context.Background()
invalid := &model.OpenFlareWAFRuleGroup{Name: "invalid", Enabled: true, Graph: `{"schema_version":1,"nodes":[],"edges":[]}`, Revision: 1}
require.NoError(t, db.DB(ctx).Create(invalid).Error)
require.NoError(t, repository.DB(ctx).Create(invalid).Error)
_, err := buildSnapshotWAFDocument(ctx, nil)
require.ErrorContains(t, err, "invalid")
}
@@ -124,7 +123,7 @@ func createSnapshotRule(t *testing.T, ctx context.Context, name string, graph wa
raw, err := json.Marshal(graph)
require.NoError(t, err)
rule := &model.OpenFlareWAFRuleGroup{Name: name, Enabled: true, Graph: string(raw), Revision: 1}
require.NoError(t, db.DB(ctx).Create(rule).Error)
require.NoError(t, repository.DB(ctx).Create(rule).Error)
return rule
}
@@ -8,7 +8,7 @@ import (
"testing"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/repository"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -25,9 +25,9 @@ func setupOriginTestDB(t *testing.T) func() {
require.NoError(t, err)
require.NoError(t, sqliteDB.AutoMigrate(&model.Origin{}))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -9,7 +9,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/repository"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -29,21 +28,21 @@ func setupProxyRouteTestDB(t *testing.T) func() {
&model.TLSCertificate{},
&model.PagesProject{},
))
db.SetDB(sqliteDB)
return func() { db.SetDB(nil) }
repository.SetDBForTest(sqliteDB)
return func() { repository.SetDBForTest(nil) }
}
func createZoneDomain(t *testing.T, ctx context.Context, domain string, certID *uint) *model.ZoneDomain {
t.Helper()
zone := &model.Zone{Domain: "example.com"}
var existing model.Zone
if err := db.DB(ctx).Where("domain = ?", zone.Domain).First(&existing).Error; err == nil {
if err := repository.DB(ctx).Where("domain = ?", zone.Domain).First(&existing).Error; err == nil {
zone = &existing
} else {
require.NoError(t, db.DB(ctx).Create(zone).Error)
require.NoError(t, repository.DB(ctx).Create(zone).Error)
}
item := &model.ZoneDomain{ZoneID: zone.ID, Domain: domain, CertID: certID}
require.NoError(t, db.DB(ctx).Create(item).Error)
require.NoError(t, repository.DB(ctx).Create(item).Error)
return item
}
@@ -102,7 +101,7 @@ func TestPagesRouteLocksAndRevalidatesTargetProject(t *testing.T) {
Enabled: true,
ActiveDeploymentID: &activeDeploymentID,
}
require.NoError(t, db.DB(ctx).Create(project).Error)
require.NoError(t, repository.DB(ctx).Create(project).Error)
view, err := CreateProxyRoute(ctx, Input{
SiteName: "pages",
@@ -115,7 +114,7 @@ func TestPagesRouteLocksAndRevalidatesTargetProject(t *testing.T) {
require.NotNil(t, view.PagesProjectID)
assert.Equal(t, project.ID, *view.PagesProjectID)
require.NoError(t, db.DB(ctx).Delete(&model.PagesProject{}, project.ID).Error)
require.NoError(t, repository.DB(ctx).Delete(&model.PagesProject{}, project.ID).Error)
route := &model.ProxyRoute{UpstreamType: proxyRouteUpstreamTypePages, PagesProjectID: &project.ID}
err = repository.WithProxyRouteTx(ctx, func(tx *gorm.DB) error {
return lockPagesProjectsForRouteMutation(tx, 0, route)
@@ -8,7 +8,7 @@ import (
"database/sql"
"testing"
db "Wavelet/plugins/infra/database"
"Wavelet/openflare/plugins/server/kernel/repository"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -65,10 +65,10 @@ func setupLegacyImportDB(t *testing.T) (*sql.DB, func()) {
require.NoError(t, err)
}
previous := db.DB(context.Background())
db.SetDB(gormDB)
previous := repository.DB(context.Background())
repository.SetDBForTest(gormDB)
return sqlDB, func() {
db.SetDB(previous)
repository.SetDBForTest(previous)
_ = sqlDB.Close()
}
}
@@ -12,7 +12,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/testhelper"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/require"
@@ -24,8 +23,8 @@ func setupZoneDB(t *testing.T) context.Context {
conn, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true})
require.NoError(t, err)
require.NoError(t, conn.AutoMigrate(&model.Zone{}, &model.ZoneDomain{}, &model.TLSCertificate{}, &model.CFPointingGroup{}, &model.CFPointingMember{}))
db.SetDB(conn)
t.Cleanup(func() { db.SetDB(nil) })
repository.SetDBForTest(conn)
t.Cleanup(func() { repository.SetDBForTest(nil) })
return context.Background()
}
@@ -24,7 +24,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/openflare/plugins/server/kernel/runtimeconfig"
"Wavelet/pkg/idgen"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -51,7 +50,7 @@ func setupTLSTestDB(t *testing.T) func() {
&model.TaskExecution{}, // 异步任务执行记录也需要 migrate
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
require.NoError(t, idgen.Init(1))
previous := runtimeconfig.Get()
runtimeconfig.SetSessionSecret("test_session_secret_for_tls_encryption")
@@ -59,7 +58,7 @@ func setupTLSTestDB(t *testing.T) func() {
oftask.SetService(&testhelper.NoopTaskService{})
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
runtimeconfig.Set(previous)
credential.SetSessionSecret(previous.SessionSecret)
tlsTestDBMu.Unlock()
@@ -75,8 +74,8 @@ func TestDeleteCertificateRejectsZoneDomainReference(t *testing.T) {
certificate, err := CreateCertificate(ctx, CertificateInput{Name: "api-cert", CertPEM: certPEM, KeyPEM: keyPEM})
require.NoError(t, err)
zone := &model.Zone{Domain: "example.com"}
require.NoError(t, db.DB(ctx).Create(zone).Error)
require.NoError(t, db.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, Domain: "api.example.com", CertID: &certificate.ID}).Error)
require.NoError(t, repository.DB(ctx).Create(zone).Error)
require.NoError(t, repository.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, Domain: "api.example.com", CertID: &certificate.ID}).Error)
err = DeleteCertificate(ctx, certificate.ID)
require.EqualError(t, err, errCertificateDeleteReferenced)
@@ -13,7 +13,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/runtimeconfig"
oftask "Wavelet/openflare/plugins/server/kernel/task"
"Wavelet/openflare/plugins/server/kernel/testhelper"
db "Wavelet/plugins/infra/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -23,7 +22,7 @@ func setupSSLRenewTestDB(t *testing.T) func() {
t.Helper()
_, _, cleanup := testhelper.SetupTestEnvironment(t)
require.NoError(t, db.DB(context.Background()).AutoMigrate(&model.TLSCertificate{}, &model.TaskExecution{}))
require.NoError(t, repository.DB(context.Background()).AutoMigrate(&model.TLSCertificate{}, &model.TaskExecution{}))
previous := runtimeconfig.Get()
runtimeconfig.SetSessionSecret("test_session_secret_for_ssl_renew")
oftask.SetService(&testhelper.NoopTaskService{})
@@ -15,7 +15,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/testhelper"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -35,10 +34,10 @@ func setupIPGroupSyncTestDB(t *testing.T) func() {
&model.OpenFlareWAFIPGroup{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
testhelper.SetupLogStoresForTest(t)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -10,7 +10,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/repository"
"Wavelet/openflare/plugins/server/kernel/model"
db "Wavelet/plugins/infra/database"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
@@ -32,9 +31,9 @@ func setupWAFTestDB(t *testing.T) func() {
&model.OriginProxyRoute{},
))
db.SetDB(sqliteDB)
repository.SetDBForTest(sqliteDB)
return func() {
db.SetDB(nil)
repository.SetDBForTest(nil)
}
}
@@ -16,7 +16,6 @@ import (
"Wavelet/openflare/plugins/server/kernel/model"
"Wavelet/pkg/response"
db "Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
@@ -84,7 +83,7 @@ func TestRuleHandlersMapFailures(t *testing.T) {
require.NoError(t, err)
return cleanup
}, want: http.StatusConflict},
{name: "database failure", method: http.MethodGet, path: "/rules", setup: func(t *testing.T) func() { t.Helper(); db.SetDB(nil); return func() {} }, want: http.StatusInternalServerError},
{name: "database failure", method: http.MethodGet, path: "/rules", setup: func(t *testing.T) func() { t.Helper(); repository.SetDBForTest(nil); return func() {} }, want: http.StatusInternalServerError},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -157,7 +156,7 @@ func TestReplaceSiteRuleGroupsPreservesOrderAndRejectsGlobal(t *testing.T) {
defer cleanup()
ctx := context.Background()
require.NoError(t, db.DB(ctx).Create(&model.OriginProxyRoute{ID: 7, Domain: "example.com"}).Error)
require.NoError(t, repository.DB(ctx).Create(&model.OriginProxyRoute{ID: 7, Domain: "example.com"}).Error)
first, err := CreateRule(ctx, CreateRuleInput{Name: "first"})
require.NoError(t, err)
second, err := CreateRule(ctx, CreateRuleInput{Name: "second"})