fireproof-storage / fireproof-storage/fireproof

avoid pushing stale merges

Open
#1,068 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
973
Forks
58
PR merge metrics
No merged PRs in 30d

Description

## Problem

Currently, when a client is significantly out of date (e.g., 10+ commits behind the remote), it pushes its local changes directly to the remote, forcing the remote and other clients to handle merge conflicts. This creates unnecessary merge complexity on the server side and can lead to performance issues in multi-client scenarios.

## Proposed Solution

Implement a "merge-first" strategy where out-of-date clients:
1. **Detect** when they are significantly behind (10+ commits)
2. **Pull** the latest remote state locally
3. **Merge** their local changes with the remote state client-side
4. **Push** the already-merged result to remote

This reduces server-side merge complexity and improves sync performance for all clients.

## Implementation Plan

### Detection Logic
**File:** `core/base/crdt-clock.ts`
- Add method to compare local head with remote head length
- Determine "out of date" threshold (10+ head length difference)

### Merge Strategy
**File:** `core/base/crdt.ts`
- Modify `applyMeta()` to trigger local merge when out-of-date detected
- Add pre-push merge logic in sync operations

### Sync Coordination
**File:** `core/base/crdt-clock.ts` (in `int_applyHead`)
- Add logic to detect remote head advancement
- Trigger local merge before pushing local changes

## Validation Strategy

### Console.log Diagnostic Points

**1. Out-of-Date Detection** (`core/base/crdt-clock.ts`):
```typescript
console.log('🔍 MERGE_STRATEGY: Checking if client is out of date', {
localHeadLength: this.head.length,
remoteHeadLength: remoteHead.length,
commitsBehind: remoteHead.length - this.head.length,
shouldMergeFirst: (remoteHead.length - this.head.length) >= 10,
dbName: this.opts.name,
timestamp: Date.now()
});
```

**2. Pre-Push Merge Decision** (`core/base/crdt.ts`):
```typescript
console.log('🔄 MERGE_STRATEGY: Executing local merge before push', {
strategy: 'merge-first',
localChanges: localHead.length,
remoteChanges: remoteHead.length,
mergeComplexity: 'low|medium|high',
dbName: this.opts.name,
timestamp: Date.now()
});
```

**3. Merge Completion** (`core/base/crdt-clock.ts`):
```typescript
console.log('✅ MERGE_STRATEGY: Local merge completed', {
originalHeadLength: originalHead.length,
mergedHeadLength: mergedHead.length,
conflictsResolved: conflictCount,
readyForPush: true,
dbName: this.opts.name,
timestamp: Date.now()
});
```

### Testing Strategy

**Test File:** `core/tests/fireproof/merge-first-strategy.test.ts`

**Test Cases:**
1. **Client not out-of-date** (< 10 commits behind)
- Should push directly without local merge
- Verify no merge-first console logs appear

2. **Client significantly out-of-date** (10+ commits behind)
- Should trigger local merge before push
- Verify merge-first console logs appear in correct sequence
- Verify final push contains merged result

3. **Multi-client scenario**
- Multiple clients with different lag levels
- Verify only out-of-date clients trigger merge-first
- Verify reduced merge conflicts on remote

**Validation Commands:**
```bash
# Test out-of-date detection
pnpm test core/tests/fireproof/merge-first-strategy.test.ts -t "should detect out-of-date client" --reporter=verbose

# Test merge-first execution
pnpm test core/tests/fireproof/merge-first-strategy.test.ts -t "should merge locally before push" --reporter=verbose

# Test multi-client coordination
pnpm test core/tests/fireproof/merge-first-strategy.test.ts -t "should coordinate merge-first across clients" --reporter=verbose
```

## Expected Benefits

- **Reduced server-side merge complexity**
- **Better performance** for clients that aren't out-of-date
- **Fewer merge conflicts** propagated to other clients
- **More predictable sync behavior** in multi-client scenarios

## Success Criteria

1. ✅ Out-of-date detection works reliably (console logs confirm)
2. ✅ Local merge executes only when needed (10+ commits behind)
3. ✅ Merged results push successfully without conflicts
4. ✅ Non-out-of-date clients unaffected (no performance regression)
5. ✅ Multi-client scenarios show reduced merge conflicts

---

This enhancement would make Fireproof's sync behavior more intelligent and reduce the burden on remotes and other clients when dealing with significantly out-of-date clients.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.