forked from trent_larson/crowd-funder-for-time-pwa
- Remove USE_DEXIE_DB import from app.ts constants - Update InviteOneAcceptView to use PlatformServiceMixin pattern - Remove legacy Dexie database access code - Move WORKER_ONLY_DATABASE_IMPLEMENTATION.md to doc/ directory - Remerge changes from master router/index.ts Fixes Electron build failure caused by missing USE_DEXIE_DB export.
382 lines
11 KiB
Markdown
382 lines
11 KiB
Markdown
# Worker-Only Database Implementation for Web Platform
|
|
|
|
## Overview
|
|
|
|
This implementation fixes the double migration issue in the TimeSafari web platform by implementing worker-only database access, similar to the Capacitor platform architecture.
|
|
|
|
## Problem Solved
|
|
|
|
**Before:** Web platform had dual database contexts:
|
|
|
|
- Worker thread: `registerSQLWorker.js` → `AbsurdSqlDatabaseService.initialize()` → migrations run
|
|
- Main thread: `WebPlatformService.dbQuery()` → `databaseService.query()` → migrations run **AGAIN**
|
|
|
|
**After:** Single database context:
|
|
|
|
- Worker thread: Handles ALL database operations and initializes once
|
|
- Main thread: Sends messages to worker, no direct database access
|
|
|
|
## Architecture Changes
|
|
|
|
### 1. Message-Based Communication
|
|
|
|
```typescript
|
|
// Main Thread (WebPlatformService)
|
|
await this.sendWorkerMessage<QueryResult>({
|
|
type: "query",
|
|
sql: "SELECT * FROM users",
|
|
params: []
|
|
});
|
|
|
|
// Worker Thread (registerSQLWorker.js)
|
|
onmessage = async (event) => {
|
|
const { id, type, sql, params } = event.data;
|
|
if (type === "query") {
|
|
const result = await databaseService.query(sql, params);
|
|
postMessage({ id, type: "success", data: { result } });
|
|
}
|
|
};
|
|
```
|
|
|
|
### 2. Type-Safe Worker Messages
|
|
|
|
```typescript
|
|
// src/interfaces/worker-messages.ts
|
|
export interface QueryRequest extends BaseWorkerMessage {
|
|
type: "query";
|
|
sql: string;
|
|
params?: unknown[];
|
|
}
|
|
|
|
export type WorkerRequest =
|
|
| QueryRequest
|
|
| ExecRequest
|
|
| GetOneRowRequest
|
|
| InitRequest
|
|
| PingRequest;
|
|
```
|
|
|
|
### 3. Circular Dependency Resolution
|
|
|
|
#### 🔥 Critical Fix: Stack Overflow Prevention
|
|
|
|
**Problem**: Circular module dependency caused infinite recursion:
|
|
|
|
- `WebPlatformService` constructor → creates Worker
|
|
- Worker loads `registerSQLWorker.js` → imports `databaseService`
|
|
- Module resolution creates circular dependency → Stack Overflow
|
|
|
|
**Solution**: Lazy Loading in Worker
|
|
|
|
```javascript
|
|
// Before (caused stack overflow)
|
|
import databaseService from "./services/AbsurdSqlDatabaseService";
|
|
|
|
// After (fixed)
|
|
let databaseService = null;
|
|
|
|
async function getDatabaseService() {
|
|
if (!databaseService) {
|
|
// Dynamic import prevents circular dependency
|
|
const { default: service } = await import("./services/AbsurdSqlDatabaseService");
|
|
databaseService = service;
|
|
}
|
|
return databaseService;
|
|
}
|
|
```
|
|
|
|
**Key Changes for Stack Overflow Fix:**
|
|
|
|
- ✅ Removed top-level import of database service
|
|
- ✅ Added lazy loading with dynamic import
|
|
- ✅ Updated all handlers to use `await getDatabaseService()`
|
|
- ✅ Removed auto-initialization that triggered immediate loading
|
|
- ✅ Database service only loads when first database operation occurs
|
|
|
|
## Implementation Details
|
|
|
|
### 1. WebPlatformService Changes
|
|
|
|
- Removed direct database imports
|
|
- Added worker message handling
|
|
- Implemented timeout and error handling
|
|
- All database methods now proxy to worker
|
|
|
|
### 2. Worker Thread Changes
|
|
|
|
- Added message-based operation handling
|
|
- Implemented lazy loading for database service
|
|
- Added proper error handling and response formatting
|
|
- Fixed circular dependency with dynamic imports
|
|
|
|
### 3. Main Thread Changes
|
|
|
|
- Removed duplicate worker creation in `main.web.ts`
|
|
- WebPlatformService now manages single worker instance
|
|
- Added Safari compatibility with `initBackend()`
|
|
|
|
## Files Modified
|
|
|
|
1. **src/interfaces/worker-messages.ts** *(NEW)*
|
|
- Type definitions for worker communication
|
|
- Request and response message interfaces
|
|
|
|
2. **src/registerSQLWorker.js** *(MAJOR REWRITE)*
|
|
- Message-based operation handling
|
|
- **Fixed circular dependency with lazy loading**
|
|
- Proper error handling and response formatting
|
|
|
|
3. **src/services/platforms/WebPlatformService.ts** *(MAJOR REWRITE)*
|
|
- Worker-only database access
|
|
- Message sending and response handling
|
|
- Timeout and error management
|
|
|
|
4. **src/main.web.ts** *(SIMPLIFIED)*
|
|
- Removed duplicate worker creation
|
|
- Simplified initialization flow
|
|
|
|
5. **WORKER_ONLY_DATABASE_IMPLEMENTATION.md** *(NEW)*
|
|
- Complete documentation of changes
|
|
|
|
## Benefits
|
|
|
|
### ✅ Fixes Double Migration Issue
|
|
|
|
- Database migrations now run only once in worker thread
|
|
- No duplicate initialization between main thread and worker
|
|
|
|
### ✅ Prevents Stack Overflow
|
|
|
|
- Circular dependency resolved with lazy loading
|
|
- Worker loads immediately without triggering database import
|
|
- Database service loads on-demand when first operation occurs
|
|
|
|
### ✅ Improved Performance
|
|
|
|
- Single database connection
|
|
- No redundant operations
|
|
- Better resource utilization
|
|
|
|
### ✅ Better Error Handling
|
|
|
|
- Centralized error handling in worker
|
|
- Type-safe message communication
|
|
- Proper timeout handling
|
|
|
|
### ✅ Consistent Architecture
|
|
|
|
- Matches Capacitor platform pattern
|
|
- Single-threaded database access
|
|
- Clear separation of concerns
|
|
|
|
## Testing Verification
|
|
|
|
After implementation, you should see:
|
|
|
|
1. **Worker Loading**:
|
|
|
|
```text
|
|
[SQLWorker] Worker loaded, ready to receive messages
|
|
```
|
|
|
|
2. **Database Initialization** (only on first operation):
|
|
|
|
```text
|
|
[SQLWorker] Starting database initialization...
|
|
[SQLWorker] Database initialization completed successfully
|
|
```
|
|
|
|
3. **No Stack Overflow**: Application starts without infinite recursion
|
|
4. **Single Migration Run**: Database migrations execute only once
|
|
5. **Functional Database**: All queries, inserts, and updates work correctly
|
|
|
|
## Migration from Previous Implementation
|
|
|
|
If upgrading from the dual-context implementation:
|
|
|
|
1. **Remove Direct Database Imports**: No more `import databaseService` in main thread
|
|
2. **Update Database Calls**: Use platform service methods instead of direct database calls
|
|
3. **Handle Async Operations**: All database operations are now async message-based
|
|
4. **Error Handling**: Update error handling to work with worker responses
|
|
|
|
## Security Considerations
|
|
|
|
- Worker thread isolates database operations
|
|
- Message validation prevents malformed requests
|
|
- Timeout handling prevents hanging operations
|
|
- Type safety reduces runtime errors
|
|
|
|
## Performance Notes
|
|
|
|
- Initial worker creation has minimal overhead
|
|
- Database operations have message passing overhead (negligible)
|
|
- Single database connection is more efficient than dual connections
|
|
- Lazy loading reduces startup time
|
|
|
|
## Migration Execution Flow
|
|
|
|
### Before (Problematic)
|
|
|
|
```chart
|
|
┌────────────── ───┐ ┌─────────────────┐
|
|
│ Main Thread │ │ Worker Thread │
|
|
│ │ │ │
|
|
│ WebPlatformService│ │registerSQLWorker│
|
|
│ ↓ │ │ ↓ │
|
|
│ databaseService │ │ databaseService │
|
|
│ (Instance A) │ │ (Instance B) │
|
|
│ ↓ │ │ ↓ │
|
|
│ [Run Migrations] │ │[Run Migrations] │ ← DUPLICATE!
|
|
└─────────────── ──┘ └─────────────────┘
|
|
```
|
|
|
|
### After (Fixed)
|
|
|
|
```text
|
|
┌─────────────── ──┐ ┌─────────────────┐
|
|
│ Main Thread │ │ Worker Thread │
|
|
│ │ │ │
|
|
│ WebPlatformService │───→│registerSQLWorker│
|
|
│ │ │ ↓ │
|
|
│ [Send Messages] │ │ databaseService │
|
|
│ │ │(Single Instance)│
|
|
│ │ │ ↓ │
|
|
│ │ │[Run Migrations] │ ← ONCE ONLY!
|
|
└─────────────── ──┘ └─────────────────┘
|
|
```
|
|
|
|
## New Security Considerations
|
|
|
|
### 1. **Message Validation**
|
|
|
|
- All worker messages validated for required fields
|
|
- Unknown message types rejected with errors
|
|
- Proper error responses prevent information leakage
|
|
|
|
### 2. **Timeout Protection**
|
|
|
|
- 30-second timeout prevents hung operations
|
|
- Automatic cleanup of pending messages
|
|
- Worker health checks via ping/pong
|
|
|
|
### 3. **Error Sanitization**
|
|
|
|
- Error messages logged but not exposed raw to main thread
|
|
- Stack traces included only in development
|
|
- Graceful handling of worker failures
|
|
|
|
## Testing Considerations
|
|
|
|
### 1. **Unit Tests Needed**
|
|
|
|
- Worker message handling
|
|
- WebPlatformService worker communication
|
|
- Error handling and timeouts
|
|
- Migration execution (should run once only)
|
|
|
|
### 2. **Integration Tests**
|
|
|
|
- End-to-end database operations
|
|
- Worker lifecycle management
|
|
- Cross-browser compatibility (especially Safari)
|
|
|
|
### 3. **Performance Tests**
|
|
|
|
- Message passing overhead
|
|
- Database operation throughput
|
|
- Memory usage with worker communication
|
|
|
|
## Browser Compatibility
|
|
|
|
### 1. **Modern Browsers**
|
|
|
|
- Chrome/Edge: Full SharedArrayBuffer support
|
|
- Firefox: Full SharedArrayBuffer support (with headers)
|
|
- Safari: Uses IndexedDB fallback via `initBackend()`
|
|
|
|
### 2. **Required Headers**
|
|
|
|
```text
|
|
Cross-Origin-Opener-Policy: same-origin
|
|
Cross-Origin-Embedder-Policy: require-corp
|
|
```
|
|
|
|
## Deployment Notes
|
|
|
|
### 1. **Development**
|
|
|
|
- Enhanced logging shows worker message flow
|
|
- Clear separation between worker and main thread logs
|
|
- Easy debugging via browser DevTools
|
|
|
|
### 2. **Production**
|
|
|
|
- Reduced logging overhead
|
|
- Optimized message passing
|
|
- Proper error reporting without sensitive data
|
|
|
|
## Future Enhancements
|
|
|
|
### 1. **Potential Optimizations**
|
|
|
|
- Message batching for bulk operations
|
|
- Connection pooling simulation
|
|
- Persistent worker state management
|
|
|
|
### 2. **Additional Features**
|
|
|
|
- Database backup/restore via worker
|
|
- Schema introspection commands
|
|
- Performance monitoring hooks
|
|
|
|
## Rollback Plan
|
|
|
|
If issues arise, rollback involves:
|
|
|
|
1. Restore original `WebPlatformService.ts`
|
|
2. Restore original `registerSQLWorker.js`
|
|
3. Restore original `main.web.ts`
|
|
4. Remove `worker-messages.ts` interface
|
|
|
|
## Commit Messages
|
|
|
|
```bash
|
|
git add src/interfaces/worker-messages.ts
|
|
git commit -m "Add worker message interface for type-safe database communication
|
|
|
|
- Define TypeScript interfaces for worker request/response messages
|
|
- Include query, exec, getOneRow, init, and ping message types
|
|
- Provide type safety for web platform worker messaging"
|
|
|
|
git add src/registerSQLWorker.js
|
|
git commit -m "Implement message-based worker for single-point database access
|
|
|
|
- Replace simple auto-init with comprehensive message handler
|
|
- Add support for query, exec, getOneRow, init, ping operations
|
|
- Implement proper error handling and response management
|
|
- Ensure single database initialization point to prevent double migrations"
|
|
|
|
git add src/services/platforms/WebPlatformService.ts
|
|
git commit -m "Migrate WebPlatformService to worker-only database access
|
|
|
|
- Remove direct databaseService import to prevent dual context issue
|
|
- Implement worker-based messaging for all database operations
|
|
- Add worker lifecycle management with initialization tracking
|
|
- Include message timeout and error handling for reliability
|
|
- Add Safari compatibility with initBackend call"
|
|
|
|
git add src/main.web.ts
|
|
git commit -m "Remove duplicate worker creation from main.web.ts
|
|
|
|
- Worker initialization now handled by WebPlatformService
|
|
- Prevents duplicate worker creation and database contexts
|
|
- Simplifies main thread initialization"
|
|
|
|
git add WORKER_ONLY_DATABASE_IMPLEMENTATION.md
|
|
git commit -m "Document worker-only database implementation
|
|
|
|
- Comprehensive documentation of architecture changes
|
|
- Explain problem solved and benefits achieved
|
|
- Include security considerations and testing requirements"
|
|
```
|