updates to worker
This commit is contained in:
parent
7d8bd335fc
commit
02949fb40a
|
|
@ -3,8 +3,18 @@ name: Deploy Worker
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- main # or 'production' depending on your branch name
|
||||
- main # Production deployment
|
||||
- 'automerge/**' # Dev deployment for automerge branches (matches automerge/*, automerge/**/*, etc.)
|
||||
workflow_dispatch: # Allows manual triggering from GitHub UI
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Environment to deploy to'
|
||||
required: true
|
||||
default: 'dev'
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- production
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
|
|
@ -22,7 +32,19 @@ jobs:
|
|||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
- name: Determine Environment
|
||||
id: env
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref }}" == "refs/heads/main" ]; then
|
||||
echo "environment=production" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "environment=dev" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Deploy to Cloudflare Workers (Production)
|
||||
if: steps.env.outputs.environment == 'production'
|
||||
run: |
|
||||
npm install -g wrangler@latest
|
||||
# Uses default wrangler.toml (production config) from root directory
|
||||
|
|
@ -30,3 +52,13 @@ jobs:
|
|||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
|
||||
- name: Deploy to Cloudflare Workers (Dev)
|
||||
if: steps.env.outputs.environment == 'dev'
|
||||
run: |
|
||||
npm install -g wrangler@latest
|
||||
# Uses wrangler.dev.toml for dev environment
|
||||
wrangler deploy --config wrangler.dev.toml
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
# Data Safety Verification: TldrawDurableObject → AutomergeDurableObject Migration
|
||||
|
||||
## Overview
|
||||
|
||||
This document verifies that the migration from `TldrawDurableObject` to `AutomergeDurableObject` is safe and will not result in data loss.
|
||||
|
||||
## R2 Bucket Configuration ✅
|
||||
|
||||
### Production Environment
|
||||
- **Bucket Binding**: `TLDRAW_BUCKET`
|
||||
- **Bucket Name**: `jeffemmett-canvas`
|
||||
- **Storage Path**: `rooms/${roomId}`
|
||||
- **Configuration**: `wrangler.toml` lines 30-32
|
||||
|
||||
### Development Environment
|
||||
- **Bucket Binding**: `TLDRAW_BUCKET`
|
||||
- **Bucket Name**: `jeffemmett-canvas-preview`
|
||||
- **Storage Path**: `rooms/${roomId}`
|
||||
- **Configuration**: `wrangler.toml` lines 72-74
|
||||
|
||||
## Data Storage Architecture
|
||||
|
||||
### Where Data is Stored
|
||||
|
||||
1. **Document Data (R2 Storage)** ✅
|
||||
- **Location**: R2 bucket at path `rooms/${roomId}`
|
||||
- **Format**: JSON document containing the full board state
|
||||
- **Persistence**: Permanent storage, independent of Durable Object instances
|
||||
- **Access**: Both `TldrawDurableObject` and `AutomergeDurableObject` use the same R2 bucket and path
|
||||
|
||||
2. **Room ID (Durable Object Storage)** ⚠️
|
||||
- **Location**: Durable Object's internal storage (`ctx.storage`)
|
||||
- **Purpose**: Cached room ID for the Durable Object instance
|
||||
- **Recovery**: Can be re-initialized from URL path (`/connect/:roomId`)
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ R2 Bucket (TLDRAW_BUCKET) │
|
||||
│ │
|
||||
│ rooms/room-123 ←─── Document Data (PERSISTENT) │
|
||||
│ rooms/room-456 ←─── Document Data (PERSISTENT) │
|
||||
│ rooms/room-789 ←─── Document Data (PERSISTENT) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
▲ ▲
|
||||
│ │
|
||||
┌─────────────────┘ └─────────────────┐
|
||||
│ │
|
||||
┌───────┴────────┐ ┌─────────────┴────────┐
|
||||
│ TldrawDurable │ │ AutomergeDurable │
|
||||
│ Object │ │ Object │
|
||||
│ (DEPRECATED) │ │ (ACTIVE) │
|
||||
└────────────────┘ └──────────────────────┘
|
||||
│ │
|
||||
└─────────────────── Both read/write ─────────────────────┘
|
||||
to the same R2 location
|
||||
```
|
||||
|
||||
## Migration Safety Guarantees
|
||||
|
||||
### ✅ No Data Loss Risk
|
||||
|
||||
1. **R2 Data is Independent**
|
||||
- Document data is stored in R2, not in Durable Object storage
|
||||
- R2 data persists even when Durable Object instances are deleted
|
||||
- Both classes use the same R2 bucket (`TLDRAW_BUCKET`) and path (`rooms/${roomId}`)
|
||||
|
||||
2. **Stub Class Ensures Compatibility**
|
||||
- `TldrawDurableObject` extends `AutomergeDurableObject`
|
||||
- Uses the same R2 bucket and storage path
|
||||
- Existing instances can access their data during migration
|
||||
|
||||
3. **Room ID Recovery**
|
||||
- `roomId` is passed in the URL path (`/connect/:roomId`)
|
||||
- Can be re-initialized if Durable Object storage is lost
|
||||
- Code handles missing `roomId` by reading from URL (see `AutomergeDurableObject.ts` lines 43-49)
|
||||
|
||||
4. **Automatic Format Conversion**
|
||||
- `AutomergeDurableObject` handles multiple data formats:
|
||||
- Automerge Array Format: `[{ state: {...} }, ...]`
|
||||
- Store Format: `{ store: { "recordId": {...}, ... }, schema: {...} }`
|
||||
- Old Documents Format: `{ documents: [{ state: {...} }, ...] }`
|
||||
- Conversion preserves all data, including custom shapes and records
|
||||
|
||||
### Migration Process
|
||||
|
||||
1. **Deployment with Stub**
|
||||
- `TldrawDurableObject` stub class is exported
|
||||
- Cloudflare recognizes the class exists
|
||||
- Existing instances can continue operating
|
||||
|
||||
2. **Delete-Class Migration**
|
||||
- Migration tag `v2` with `deleted_classes = ["TldrawDurableObject"]`
|
||||
- Cloudflare will delete Durable Object instances (not R2 data)
|
||||
- R2 data remains untouched
|
||||
|
||||
3. **Data Access After Migration**
|
||||
- New `AutomergeDurableObject` instances can access the same R2 data
|
||||
- Same bucket (`TLDRAW_BUCKET`) and path (`rooms/${roomId}`)
|
||||
- Automatic format conversion ensures compatibility
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [x] R2 bucket binding is correctly configured (`TLDRAW_BUCKET`)
|
||||
- [x] Both production and dev environments have R2 buckets configured
|
||||
- [x] `AutomergeDurableObject` uses `env.TLDRAW_BUCKET`
|
||||
- [x] Storage path is consistent (`rooms/${roomId}`)
|
||||
- [x] Stub class extends `AutomergeDurableObject` (same R2 access)
|
||||
- [x] Migration includes `delete-class` for `TldrawDurableObject`
|
||||
- [x] Code handles missing `roomId` by reading from URL
|
||||
- [x] Format conversion logic preserves all data types
|
||||
- [x] Custom shapes and records are preserved during conversion
|
||||
|
||||
## Testing Recommendations
|
||||
|
||||
1. **Before Migration**
|
||||
- Verify R2 bucket contains expected room data
|
||||
- List rooms: `wrangler r2 object list TLDRAW_BUCKET --prefix "rooms/"`
|
||||
- Check a sample room's format
|
||||
|
||||
2. **After Migration**
|
||||
- Verify rooms are still accessible
|
||||
- Check that data format is correctly converted
|
||||
- Verify custom shapes and records are preserved
|
||||
- Monitor worker logs for conversion statistics
|
||||
|
||||
3. **Data Integrity Checks**
|
||||
- Shape count matches before/after
|
||||
- Custom shapes (ObsNote, Holon, etc.) have all properties
|
||||
- Custom records (obsidian_vault, etc.) are present
|
||||
- No validation errors in console
|
||||
|
||||
## Conclusion
|
||||
|
||||
✅ **The migration is safe and will not result in data loss.**
|
||||
|
||||
- All document data is stored in R2, which is independent of Durable Object instances
|
||||
- Both classes use the same R2 bucket and storage path
|
||||
- The stub class ensures compatibility during migration
|
||||
- Format conversion logic preserves all data types
|
||||
- Room IDs can be recovered from URL paths if needed
|
||||
|
||||
The only data that will be lost is the cached `roomId` in Durable Object storage, which can be easily re-initialized from the URL path.
|
||||
|
||||
|
|
@ -5,6 +5,25 @@ import { Environment } from "./types"
|
|||
// make sure our sync durable objects are made available to cloudflare
|
||||
export { AutomergeDurableObject } from "./AutomergeDurableObject"
|
||||
|
||||
// Temporary stub for TldrawDurableObject to allow delete-class migration
|
||||
// This extends AutomergeDurableObject so existing instances can be handled during migration
|
||||
//
|
||||
// DATA SAFETY: All document data is stored in R2 at `rooms/${roomId}`, not in Durable Object storage.
|
||||
// When TldrawDurableObject instances are deleted, only the Durable Object instances are removed.
|
||||
// The R2 data remains safe and accessible by AutomergeDurableObject, which uses the same R2 bucket
|
||||
// (TLDRAW_BUCKET) and storage path. The roomId can be re-initialized from the URL path if needed.
|
||||
//
|
||||
// This will be removed after the migration completes
|
||||
import { AutomergeDurableObject as BaseAutomergeDurableObject } from "./AutomergeDurableObject"
|
||||
|
||||
export class TldrawDurableObject extends BaseAutomergeDurableObject {
|
||||
constructor(ctx: DurableObjectState, env: Environment) {
|
||||
// Extends AutomergeDurableObject, so it uses the same R2 bucket (env.TLDRAW_BUCKET)
|
||||
// and storage path (rooms/${roomId}), ensuring no data loss during migration
|
||||
super(ctx, env)
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy load heavy dependencies to avoid startup timeouts
|
||||
let handleUnfurlRequest: any = null
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,9 @@ bindings = [
|
|||
tag = "v1"
|
||||
new_classes = ["AutomergeDurableObject"]
|
||||
|
||||
# Note: TldrawDurableObject → AutomergeDurableObject migration removed
|
||||
# The AutomergeDurableObject class is already in use, so we can't rename to it.
|
||||
# Any remaining TldrawDurableObject instances will be orphaned but won't cause issues.
|
||||
# If you need to clean them up, you can add a delete-class migration in the future.
|
||||
[[migrations]]
|
||||
tag = "v2"
|
||||
deleted_classes = ["TldrawDurableObject"]
|
||||
|
||||
[[r2_buckets]]
|
||||
binding = 'TLDRAW_BUCKET'
|
||||
|
|
@ -66,6 +65,10 @@ bindings = [
|
|||
tag = "v1"
|
||||
new_classes = ["AutomergeDurableObject"]
|
||||
|
||||
[[env.dev.migrations]]
|
||||
tag = "v2"
|
||||
deleted_classes = ["TldrawDurableObject"]
|
||||
|
||||
[[env.dev.r2_buckets]]
|
||||
binding = 'TLDRAW_BUCKET'
|
||||
bucket_name = 'jeffemmett-canvas-preview'
|
||||
|
|
|
|||
Loading…
Reference in New Issue