-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathSyncManager.ts
More file actions
65 lines (53 loc) · 2.27 KB
/
SyncManager.ts
File metadata and controls
65 lines (53 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { ConflictResolver, ConflictStrategy } from './ConflictResolver';
import { IncrementalSync } from './IncrementalSync';
import { SyncState } from '../models/SyncState';
export class SyncManager {
private resolver: ConflictResolver;
private incrementalSync: IncrementalSync;
constructor() {
this.resolver = new ConflictResolver(ConflictStrategy.LAST_WRITE_WINS);
this.incrementalSync = new IncrementalSync();
}
async synchronize(userId: string, deviceId: string, clientChanges: any[]): Promise<any> {
// 1. Fetch current server state/version
const currentState = await SyncState.findOne({ userId, deviceId });
const lastSyncVersion = currentState ? currentState.version : 0;
// 2. Identify server-side changes since last sync
const serverChanges = await this.incrementalSync.getChangesSince(lastSyncVersion);
// 3. Process client changes and resolve conflicts
const reconciledChanges = [];
for (const clientChange of clientChanges) {
const conflict = serverChanges.find(sc => sc.entityId === clientChange.entityId);
if (conflict) {
const resolved = this.resolver.resolve(clientChange, conflict);
reconciledChanges.push(resolved);
} else {
reconciledChanges.push(clientChange);
}
}
// 4. Apply changes to database
await this.applyReconciledChanges(reconciledChanges);
// 5. Update sync state
const newVersion = Date.now();
await SyncState.updateOne(
{ userId, deviceId },
{ version: newVersion, lastSyncAt: new Date() },
{ upsert: true }
);
return {
serverChanges: serverChanges.filter(sc => !clientChanges.some(cc => cc.entityId === sc.entityId)),
newVersion
};
}
private async applyReconciledChanges(changes: any[]): Promise<void> {
// Implementation of batch updates to ensure atomicity
for (const change of changes) {
if (change.needsManualResolution) continue;
// Mocking a generic database update
// In a real scenario, this would use a repository or direct DB driver
console.log(`Applying change to entity ${change.entityId}`);
// Update the actual data record
// await db.collection(change.collection).updateOne({ _id: change.entityId }, { $set: change.data });
}
}
}