Files
tasq/lib/brick/cache_helpers.dart
T
2026-04-27 06:20:39 +08:00

64 lines
2.1 KiB
Dart

import 'package:flutter/foundation.dart' show debugPrint;
import 'repository.dart';
/// Returns the locally cached list of [T] from Brick SQLite, or `[]` if Brick
/// isn't configured or the read fails. Never throws.
///
/// Use this as `onOfflineData` for [StreamRecoveryWrapper] so that screens
/// render data from the local cache when the device is offline:
///
/// ```dart
/// onOfflineData: () => cachedListFromBrick<Task>(),
/// ```
Future<List<T>> cachedListFromBrick<T extends OfflineFirstWithSupabaseModel>() async {
if (!AppRepository.isConfigured) {
debugPrint('[cachedListFromBrick<$T>] BRICK NOT CONFIGURED — returning []');
return const [];
}
try {
final rows = await AppRepository.instance.get<T>(
policy: OfflineFirstGetPolicy.localOnly,
);
if (rows.isEmpty) {
debugPrint('[cachedListFromBrick<$T>] empty cache (0 rows)');
}
return rows;
} catch (e) {
debugPrint('[cachedListFromBrick<$T>] failed: $e');
return const [];
}
}
/// Mirrors a batch of model rows into Brick's local SQLite cache as a
/// fire-and-forget side effect. Errors are caught and logged.
///
/// Use this as `onCacheMirror` for [StreamRecoveryWrapper] so that every
/// realtime emission keeps the local cache fresh — required for the cold-
/// launch-offline experience.
///
/// ```dart
/// onCacheMirror: (rows) => mirrorBatchToBrick<Task>(rows, tag: 'tasks'),
/// ```
void mirrorBatchToBrick<T extends OfflineFirstWithSupabaseModel>(
List<T> rows, {
String tag = 'mirror',
}) {
if (!AppRepository.isConfigured) return;
// Use sqliteProvider directly (local-only write). AppRepository.upsert is
// bidirectional — it re-POSTs rows to Supabase, which triggers RLS
// violations for other users' records and deadlocks from concurrent writes.
// Sequential processing prevents SQLite lock contention across providers.
// ignore: discarded_futures
Future(() async {
for (final row in rows) {
try {
await AppRepository.instance.sqliteProvider
.upsert<T>(row, repository: AppRepository.instance);
} catch (e) {
debugPrint('[$tag] mirror upsert<$T> failed: $e');
}
}
});
}