writeWithSync<T extends dynamic> method
T
writeWithSync<T extends dynamic>(})
Performs a write operation on a specific object and automatically updates its sync_updated_at field, marks it for sync, and creates a DBCache entry with the computed diff.
This ensures SyncHelper can use pre-computed diffs and avoid sending updates when no actual changes were made.
Usage:
realm.writeWithSync(goal, userId: 'user-123', collectionName: 'goals', () {
goal.title = "Updated title";
// sync_updated_at is set, diff is computed and cached
});
Implementation
T writeWithSync<T extends RealmObject>(
T obj, {
required String userId,
required String collectionName,
required void Function() writeCallback,
}) {
return write(() {
// Capture old state before modification
Map<String, dynamic> oldData = {};
try {
oldData = RealmJson.toJsonWith(obj, null);
} catch (e) {
// Serialization failed, skip diff caching
}
// Apply user's modifications
writeCallback();
// Update sync metadata
obj.updateSyncTimestamp();
obj.markForSync();
// Capture new state and compute diff
try {
final newData = RealmJson.toJsonWith(obj, null);
final entityId = _extractEntityId(obj);
if (entityId != null) {
final isInsert = oldData.isEmpty;
// For inserts, store full data; for updates, store diff
final diffData = isInsert ? newData : diff(oldData, newData);
// Only create DBCache if there are actual changes
if (diffData.isNotEmpty) {
final key = '$userId|$collectionName|$entityId';
final dbCache = SyncDBCache(
key,
userId,
collectionName,
entityId,
jsonEncode(canonicalizeMap(diffData)),
jsonEncode(canonicalizeMap(newData)),
isInsert ? 'inserted' : 'modified',
createdAt: DateTime.now(),
);
add<SyncDBCache>(dbCache, update: true);
}
}
} catch (e) {
// Log diff caching failures for debugging
try {
// Avoid importing AppLogger to keep extensions lightweight
// ignore: avoid_print
print(
'DBCache creation failed for $collectionName|${_extractEntityId(obj)}: $e',
);
} catch (_) {}
}
return obj;
});
}