项目文件夹

文件
wehub-resource-sync 75f3dd141c
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CI and Release / lint-frontend (push) Has been cancelled
CI and Release / dockerfile-scan (push) Has been cancelled
CI and Release / test-frontend (push) Has been cancelled
CI and Release / lint-verification-agent (push) Has been cancelled
CI and Release / test-verification-agent (push) Has been cancelled
CI and Release / e2e-verification-agent (push) Has been cancelled
CI and Release / test-backend (push) Has been cancelled
CI and Release / build-dev-image (push) Has been cancelled
CI and Release / push-dev-image (push) Has been cancelled
CI and Release / build-image (push) Has been cancelled
CI and Release / build-verification-image (push) Has been cancelled
CI and Release / determine-version (push) Has been cancelled
CI and Release / push-image (push) Has been cancelled
CI and Release / push-verification-image (12) (push) Has been cancelled
CI and Release / lint-backend (push) Has been cancelled
CI and Release / push-verification-image (17) (push) Has been cancelled
CI and Release / push-verification-image (18) (push) Has been cancelled
CI and Release / release (push) Has been cancelled
CI and Release / publish-helm-chart (push) Has been cancelled
CI and Release / push-verification-image (13) (push) Has been cancelled
CI and Release / push-verification-image (14) (push) Has been cancelled
CI and Release / push-verification-image (15) (push) Has been cancelled
CI and Release / push-verification-image (16) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:11:07 +08:00

193 行
5.5 KiB
Go

package restoring
import (
"context"
"sync/atomic"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"databasus-backend/internal/config"
backups_core_logical "databasus-backend/internal/features/backups/backups/core/logical"
backups_services "databasus-backend/internal/features/backups/backups/services"
backups_config_logical "databasus-backend/internal/features/backups/config/logical"
"databasus-backend/internal/features/databases"
postgresql_logical "databasus-backend/internal/features/databases/databases/postgresql/logical"
restores_core "databasus-backend/internal/features/restores/core"
"databasus-backend/internal/features/restores/usecases"
"databasus-backend/internal/features/storages"
tasks_cancellation "databasus-backend/internal/features/tasks/cancellation"
workspaces_controllers "databasus-backend/internal/features/workspaces/controllers"
workspaces_testing "databasus-backend/internal/features/workspaces/testing"
"databasus-backend/internal/util/encryption"
"databasus-backend/internal/util/logger"
)
func CreateTestRouter() *gin.Engine {
router := workspaces_testing.CreateTestRouter(
workspaces_controllers.GetWorkspaceController(),
workspaces_controllers.GetMembershipController(),
databases.GetDatabaseController(),
backups_config_logical.GetBackupConfigController(),
)
return router
}
func CreateTestRestorer() *Restorer {
return &Restorer{
databases.GetDatabaseService(),
backups_services.GetBackupService(),
encryption.GetFieldEncryptor(),
restoreRepository,
backups_config_logical.GetBackupConfigService(),
storages.GetStorageService(),
logger.GetLogger(),
usecases.GetRestoreBackupUsecase(),
restoreDatabaseCache,
tasks_cancellation.GetTaskCancelManager(),
}
}
func CreateTestRestorerWithUsecase(usecase restores_core.RestoreBackupUsecase) *Restorer {
return &Restorer{
databases.GetDatabaseService(),
backups_services.GetBackupService(),
encryption.GetFieldEncryptor(),
restoreRepository,
backups_config_logical.GetBackupConfigService(),
storages.GetStorageService(),
logger.GetLogger(),
usecase,
restoreDatabaseCache,
tasks_cancellation.GetTaskCancelManager(),
}
}
func CreateTestRestoresScheduler() *RestoresScheduler {
return &RestoresScheduler{
restoreRepository,
time.Now().UTC(),
logger.GetLogger(),
restorer,
restoreDatabaseCache,
atomic.Bool{},
}
}
// WaitForRestoreCompletion waits for a restore to be completed (or failed)
func WaitForRestoreCompletion(
t *testing.T,
restoreID uuid.UUID,
timeout time.Duration,
) {
deadline := time.Now().UTC().Add(timeout)
for time.Now().UTC().Before(deadline) {
restore, err := restoreRepository.FindByID(restoreID)
if err != nil {
t.Logf("WaitForRestoreCompletion: error finding restore: %v", err)
time.Sleep(50 * time.Millisecond)
continue
}
t.Logf("WaitForRestoreCompletion: restore status: %s", restore.Status)
if restore.Status == restores_core.RestoreStatusCompleted ||
restore.Status == restores_core.RestoreStatusFailed {
t.Logf(
"WaitForRestoreCompletion: restore finished with status %s",
restore.Status,
)
return
}
time.Sleep(50 * time.Millisecond)
}
t.Logf("WaitForRestoreCompletion: timeout waiting for restore to complete")
}
// StartRestorerForTest installs the given restorer as the DI scheduler's
// in-process executor for the duration of a test, so a test-injected usecase
// (e.g. a blocking or capturing mock) actually runs when StartRestore dispatches.
// Returns a cancel function that restores the original executor.
func StartRestorerForTest(_ *testing.T, restorerForTest *Restorer) context.CancelFunc {
previous := restoresScheduler.restorer
restoresScheduler.restorer = restorerForTest
return func() {
restoresScheduler.restorer = previous
}
}
// StartSchedulerForTest starts the RestoresScheduler in a goroutine for testing.
// Returns a context cancel function that should be deferred to stop the scheduler.
func StartSchedulerForTest(t *testing.T, scheduler *RestoresScheduler) context.CancelFunc {
ctx, cancel := context.WithCancel(context.Background())
done := make(chan struct{})
go func() {
scheduler.Run(ctx)
close(done)
}()
deadline := time.Now().UTC().Add(5 * time.Second)
for time.Now().UTC().Before(deadline) {
if scheduler.IsSchedulerRunning() {
t.Log("RestoresScheduler started")
return func() {
cancel()
select {
case <-done:
t.Log("RestoresScheduler stopped gracefully")
case <-time.After(2 * time.Second):
t.Log("RestoresScheduler stop timeout")
}
}
}
time.Sleep(25 * time.Millisecond)
}
t.Fatal("RestoresScheduler failed to start within timeout")
return nil
}
// StopRestorerForTest restores the DI scheduler's original executor.
func StopRestorerForTest(_ *testing.T, cancel context.CancelFunc, _ *Restorer) {
cancel()
}
// CreateTestRestore creates a test restore with the given backup and status
func CreateTestRestore(
t *testing.T,
backup *backups_core_logical.LogicalBackup,
status restores_core.RestoreStatus,
) *restores_core.Restore {
restore := &restores_core.Restore{
BackupID: backup.ID,
Status: status,
PostgresqlLogicalDatabase: &postgresql_logical.PostgresqlLogicalDatabase{
Host: config.GetEnv().TestLocalhost,
Port: 5432,
Username: "test",
Password: "test",
Database: func() *string { s := "testdb"; return &s }(),
Version: "16",
},
}
err := restoreRepository.Save(restore)
if err != nil {
t.Fatalf("Failed to create test restore: %v", err)
}
return restore
}