Skip to main content

ADR-003: Sync Architecture

Status: Accepted Date: December 17, 2025 Decision Makers: CODITECT Engineering Team


Context

CODITECT needs to stay synchronized with Google Drive changes:

  1. Detect file uploads, modifications, deletions
  2. Update local caches and indexes
  3. Trigger downstream workflows (e.g., transcription)
  4. Maintain consistency across sessions

Decision

Implement hybrid sync with push notifications and polling fallback.

Architecture

                    Push (Primary)           Poll (Fallback)
│ │
Google Drive ────────────┼────────────────────────┤
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Webhook Handler │ │ Poll Service │
│ (Real-time) │ │ (Every 60s) │
└────────┬────────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────────────────────────────────┐
│ Change Processor │
│ - Deduplicate events │
│ - Update local cache │
│ - Trigger workflows │
└─────────────────────────────────────────┘

Push Notification Flow

  1. Register watch channel with Google Drive API
  2. Receive POST to webhook URL on changes
  3. Fetch actual changes via Changes API
  4. Process and route to handlers
  5. Renew channel before expiration (7 days max)

Polling Flow (Fallback)

  1. Store last pageToken
  2. Poll every 60 seconds
  3. Fetch changes since token
  4. Process same as push

Implementation

async def ensure_sync_active():
state = await get_sync_state()

if not state.channel_id or state.channel_expired():
# Start push notifications
await start_watching()

# Always poll as backup
await process_changes()

Consequences

Positive

  • Near real-time updates via push
  • Reliable with polling fallback
  • No missed changes

Negative

  • Push channels require renewal
  • Webhook endpoint must be publicly accessible
  • Some latency on fallback to polling

Document Control:

  • Created: December 17, 2025