┌─────────────────────────────────────────────────────────────────────────┐
│ USER │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 1. Selects files, schedule, & TIME
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ BatchFileTransferDialog.tsx (ENHANCED) │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Schedule Selector: │ │
│ │ ○ Run now │ │
│ │ ● Daily at [02:00] [AM] [EST] ← NEW: Time picker + timezone │ │
│ │ ○ Weekly │ │
│ │ ○ Monthly │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 2. POST /api/jobs/backup
│ { schedule: "daily",
│ scheduledTime: "02:00",
│ timezone: "America/New_York" }
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Next.js API Route (ENHANCED) │
│ /api/jobs/backup/route.ts │
│ │
│ • Creates job record with time & timezone │
│ • Sets status = "scheduled" │
│ • Computes nextRunAt with SPECIFIC TIME │
│ (e.g., "2025-10-14T02:00:00-04:00") │
│ • Returns jobId to user │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 3. Stores in database
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ PostgreSQL Database │
│ │
│ backup_jobs table (ENHANCED): │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ id: "job_123" │ │
│ │ status: "scheduled" │ │
│ │ schedule: "daily" │ │
│ │ scheduledTime: "02:00" ← NEW │ │
│ │ timezone: "America/New_York" ← NEW │ │
│ │ nextRunAt: "2025-10-14T02:00:00-04:00" ← Specific time! │ │
│ │ payload: {...sources, destination...} │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 4. Scheduler checks periodically
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ VERCEL CRON JOB │
│ (Runs every 5 minutes) │
│ │
│ vercel.json: │
│ { │
│ "crons": [{ │
│ "path": "/api/cron/execute-backups", │
│ "schedule": "*/5 * * * *" ← Every 5 minutes │
│ }] │
│ } │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 5. Triggers check
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Next.js Cron API Route (NEW) │
│ /api/cron/execute-backups/route.ts │
│ │
│ 1. Authenticate cron request (secret token) │
│ 2. Query database: │
│ SELECT * FROM backup_jobs │
│ WHERE status = 'scheduled' │
│ AND nextRunAt <= NOW() │
│ 3. For each due job: │
│ • Update status to 'running' │
│ • Call Fly.io to execute job │
│ • Handle errors │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 6. POST to Fly.io
│ /api/jobs/execute
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ FLY.IO RCLONE SERVICE (ENHANCED) │
│ │
│ NEW: Job Executor Module │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ fly-rclone/src/services/job-executor.js │ │
│ │ │ │
│ │ 1. Receive job execution request │ │
│ │ 2. Parse job payload (sources, destination) │ │
│ │ 3. For each source item: │ │
│ │ • Resolve file/folder IDs to paths │ │
│ │ • Execute rclone copy operation │ │
│ │ • Send progress updates to Next.js │ │
│ │ • Update item status in database │ │
│ │ 4. Mark job complete/failed │ │
│ │ 5. Compute next run time (for recurring jobs) │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ Existing: rclone Operations │
│ • copy-service.js │
│ • move-service.js │
│ • folder-copy-service.js │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 7. Progress updates
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Next.js Progress API (NEW) │
│ /api/jobs/[id]/items/[itemId]/progress │
│ │
│ • Receives progress updates from Fly.io │
│ • Updates backup_job_items table │
│ • Stores: progress_percent, bytes_transferred, speed, eta │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 8. Updates database
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ PostgreSQL Database │
│ │
│ backup_jobs: │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ id: "job_123" │ │
│ │ status: "running" → "completed" │ │
│ │ lastRunAt: "2025-10-14T02:05:23Z" │ │
│ │ nextRunAt: "2025-10-15T02:00:00-04:00" ← Next occurrence │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ backup_job_items: │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ jobId: "job_123" │ │
│ │ sourceId: "file_abc" │ │
│ │ status: "completed" │ │
│ │ progress_percent: 100 │ │
│ │ bytes_transferred: 1048576 │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 9. User views progress
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Jobs Page (ENHANCED) │
│ /user/jobs/page.tsx │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ Job: Daily Backup to OneDrive │ │
│ │ Status: ✅ Completed │ │
│ │ Last Run: Oct 14, 2025 2:05 AM │ │
│ │ Next Run: Oct 15, 2025 2:00 AM EST │ │
│ │ │ │
│ │ Items (3): │ │
│ │ ✅ file1.pdf [████████████] 100% 1.2 MB │ │
│ │ ✅ file2.docx [████████████] 100% 856 KB │ │
│ │ ✅ folder1/ [████████████] 100% 15.3 MB (12 files) │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ User │ │ UI │ │ API │ │ DB │ │Fly.io│
└──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘
│ │ │ │ │
│ Configure │ │ │ │
│ backup ────> │ │ │
│ │ │ │ │
│ │ Create job │ │ │
│ │ ──────────> │ │
│ │ │ │ │
│ │ │ Store job │ │
│ │ │ ──────────> │
│ │ │ │ │
│ │ │ Job saved │ │
│ │ │ <────────── │
│ │ │ │ │
│ │ Job created│ │ │
│ │ <────────── │ │
│ │ │ │ │
│ Job ID │ │ │ │
│ <────────── │ │ │
│ │ │ │ │
│ │ │ │ │
│ ... Time passes (5 minutes) ... │ │
│ │ │ │ │
│ │ │ │ │
│ │ ┌─────────┴─────────┐ │ │
│ │ │ Vercel Cron Job │ │ │
│ │ │ (every 5 min) │ │ │
│ │ └─────────┬─────────┘ │ │
│ │ │ │ │
│ │ │ Find due │ │
│ │ │ jobs ─────> │
│ │ │ │ │
│ │ │ Due jobs │ │
│ │ │ <────────── │
│ │ │ │ │
│ │ │ Execute │ │
│ │ │ job ───────────────────>
│ │ │ │ │
│ │ │ │ Transfer │
│ │ │ │ files │
│ │ │ │ │
│ │ │ Progress │ │
│ │ │ <───────────────────────
│ │ │ │ │
│ │ │ Update DB │ │
│ │ │ ──────────> │
│ │ │ │ │
│ │ Poll for │ │ │
│ │ updates ──> │ │
│ │ │ │ │
│ │ │ Get status │ │
│ │ │ ──────────> │
│ │ │ │ │
│ │ │ Job status │ │
│ │ │ <────────── │
│ │ │ │ │
│ │ Display │ │ │
│ │ progress │ │ │
│ │ │ │ │
│ View │ │ │ │
│ progress ──> │ │ │
│ │ │ │ │