# Backup Scheduler Architecture Diagram

> **Status: previous scheduler topology.** Diagrams that show Vercel Cron,
> Neon, or active Fly.io workers preserve the pre-cutover architecture. Current
> production uses one VM Compose cron replica, Compose PostgreSQL, and the VM
> rclone worker. See [Architecture Evolution](../ARCHITECTURE_EVOLUTION.md).

## Current State (Non-Functional)

```
┌─────────────────────────────────────────────────────────────┐
│                         USER                                 │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            │ 1. Selects files & schedule
                            ▼
┌─────────────────────────────────────────────────────────────┐
│              BatchFileTransferDialog.tsx                     │
│  ┌────────────────────────────────────────────────────┐    │
│  │ Schedule Selector:                                  │    │
│  │  ○ Run now                                          │    │
│  │  ○ Daily    ← User selects                         │    │
│  │  ○ Weekly                                           │    │
│  │  ○ Monthly                                          │    │
│  └────────────────────────────────────────────────────┘    │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            │ 2. POST /api/jobs/backup
                            ▼
┌─────────────────────────────────────────────────────────────┐
│                  Next.js API Route                           │
│              /api/jobs/backup/route.ts                       │
│                                                               │
│  • Creates job record in database                            │
│  • Sets status = "scheduled"                                 │
│  • Computes nextRunAt (tomorrow, next week, etc.)           │
│  • Returns jobId to user                                     │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            │ 3. Stores in database
                            ▼
┌─────────────────────────────────────────────────────────────┐
│                    PostgreSQL Database                       │
│                                                               │
│  backup_jobs table:                                          │
│  ┌────────────────────────────────────────────────────┐    │
│  │ id: "job_123"                                       │    │
│  │ status: "scheduled"                                 │    │
│  │ schedule: "daily"                                   │    │
│  │ nextRunAt: "2025-10-14T00:00:00Z"  ← No time!     │    │
│  │ payload: {...sources, destination...}              │    │
│  └────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
                            │
                            │
                            ▼
                    ❌ NOTHING HAPPENS
                    Job sits in database forever
                    No scheduler to execute it
```

## Proposed Architecture (Functional)

```
┌─────────────────────────────────────────────────────────────────────────┐
│                              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)         │ │
│  └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```

## Data Flow Sequence

```
┌──────┐     ┌──────┐     ┌──────┐     ┌──────┐     ┌──────┐
│ 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 ──>            │            │            │
   │            │            │            │            │
```

## Key Components

### 1. Time Picker Component (NEW)
- **Location:** `src/components/ui/time-picker.tsx` (to be created).
- **Purpose:** Allow users to select specific time for scheduled backups.
- **Features:** 12/24 hour format, timezone selector, validation.

### 2. Vercel Cron Job (NEW)
- **Location:** `vercel.json` configuration.
- **Purpose:** Trigger periodic checks for due jobs.
- **Frequency:** Every 5 minutes (configurable).

### 3. Cron API Endpoint (NEW)
- **Location:** `src/app/api/cron/execute-backups/route.ts`.
- **Purpose:** Find and trigger execution of due jobs.
- **Security:** Authenticated with cron secret token.

### 4. Fly.io Job Executor (NEW)
- **Location:** `fly-rclone/src/services/job-executor.js`.
- **Purpose:** Execute backup jobs using rclone.
- **Features:** Progress tracking, error handling, status updates.

### 5. Progress API (NEW)
- **Location:** `src/app/api/jobs/[id]/items/[itemId]/progress/route.ts`.
- **Purpose:** Receive and store progress updates from Fly.io.
- **Updates:** Per-item progress, speed, ETA.

### 6. Enhanced Jobs Page
- **Location:** `src/app/user/jobs/page.tsx` (to be enhanced).
- **New Features:** Detailed progress view, item-level status, real-time updates.

## Security Considerations

1. **Cron Authentication:** Vercel cron secret token validation
2. **Fly.io Communication:** Shared secret for API calls
3. **User Authorization:** Verify user owns job before execution
4. **Rate Limiting:** Prevent abuse of job creation
5. **Quota Enforcement:** Check subscription tier limits

## Scalability Considerations

1. **Database Indexes:** On `nextRunAt`, `status`, `userId` for efficient queries
2. **Job Batching:** Execute multiple due jobs in parallel (with limits)
3. **Progress Updates:** Batch updates to reduce database writes
4. **Cleanup:** Archive old completed jobs to separate table
5. **Monitoring:** Track execution times, failure rates, resource usage

