writeWithSync<T extends dynamic> method

T writeWithSync<T extends dynamic>(
  1. T obj, {
  2. required String userId,
  3. required String collectionName,
  4. required void writeCallback(),
})

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;
  });
}