param( [Parameter(Mandatory = $true)] [string]$Destination ) $ErrorActionPreference = 'Stop' $resolved = [System.IO.Path]::GetFullPath($Destination) New-Item -ItemType Directory -Force -Path $resolved | Out-Null $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $backupDir = Join-Path $resolved "telegram-gateway-$timestamp" New-Item -ItemType Directory -Force -Path $backupDir | Out-Null docker exec tgw-postgres pg_dump -U postgres -d telegram_gateway -Fc -f /tmp/gateway.dump docker cp tgw-postgres:/tmp/gateway.dump (Join-Path $backupDir 'postgres.dump') docker exec tgw-redis redis-cli SAVE | Out-Null docker cp tgw-redis:/data/dump.rdb (Join-Path $backupDir 'redis.rdb') docker run --rm --volumes-from tgw-app -v "${backupDir}:/backup" ` node:20-bookworm-slim ` tar -czf /backup/tdlib-data.tar.gz -C /app tdlib_data uploads $publicTables = [int](docker exec tgw-postgres psql -U postgres -d telegram_gateway -Atc ` "select count(*) from information_schema.tables where table_schema='public';") $tenantRows = [int](docker exec tgw-postgres psql -U postgres -d telegram_gateway -Atc ` 'select count(*) from tenants;') $accountRows = [int](docker exec tgw-postgres psql -U postgres -d telegram_gateway -Atc ` 'select count(*) from tg_accounts;') $redisDbSize = [int](docker exec tgw-redis redis-cli DBSIZE) $tdlibFileCount = [int](docker exec tgw-app sh -c ` "find /app/tdlib_data /app/uploads -type f 2>/dev/null | wc -l") $manifest = @{ createdAt = (Get-Date).ToUniversalTime().ToString('o') postgres = 'postgres.dump' redis = 'redis.rdb' tdlib = 'tdlib-data.tar.gz' sha256 = @{} expected = @{ publicTables = $publicTables tenantRows = $tenantRows accountRows = $accountRows redisDbSize = $redisDbSize tdlibFileCount = $tdlibFileCount } } foreach ($file in @('postgres.dump', 'redis.rdb', 'tdlib-data.tar.gz')) { $manifest.sha256[$file] = (Get-FileHash -Algorithm SHA256 (Join-Path $backupDir $file)).Hash } $manifest | ConvertTo-Json -Depth 4 | Set-Content -Encoding utf8 (Join-Path $backupDir 'manifest.json') Write-Output $backupDir