attempt to fix test txs

This commit is contained in:
davmar
2026-09-10 23:59:00 +02:00
parent f8e293f823
commit 00ab05eefc
6 changed files with 327 additions and 62 deletions
+74 -17
View File
@@ -6,6 +6,7 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import '../models/app_cloud_prefs.dart';
import '../models/bank.dart';
import '../models/home_filter_widget.dart';
import '../models/overview_favourite.dart';
import '../services/pb_sync_service.dart';
@@ -46,6 +47,7 @@ class SyncController extends ChangeNotifier {
_prefs.onAppPrefsPersisted = _scheduleAppPrefsPush;
_auth.addListener(_onAuthChanged);
_bank.onAfterSuccessfulLoad = _onBankDataLoaded;
_bank.onPendingRemoteDeletesChanged = _scheduleBankTxPush;
if (_auth.isLoggedIn) {
unawaited(syncNow());
}
@@ -64,6 +66,7 @@ class SyncController extends ChangeNotifier {
bool _pushFavouritesPending = false;
bool _pushHomeWidgetsPending = false;
bool _pushAppPrefsPending = false;
bool _pushBankPending = false;
Timer? _pushDebounce;
Timer? _progressHold;
Timer? _uiNotifyThrottle;
@@ -198,6 +201,7 @@ class SyncController extends ChangeNotifier {
_pushFavouritesPending = false;
_pushHomeWidgetsPending = false;
_pushAppPrefsPending = false;
_pushBankPending = false;
_lastError = null;
_statusDetail = '';
_showProgressRing = false;
@@ -265,6 +269,28 @@ class SyncController extends ChangeNotifier {
_armPushDebounce();
}
void _scheduleBankTxPush() {
_pushBankPending = true;
_armPushDebounce();
}
/// Removes tombstoned bank txs from PocketBase before pull/push can resurrect them.
Future<void> _flushPendingTxDeletes(PbSyncService service) async {
final pending = List<BankTransaction>.of(_bank.pendingRemoteDeletes);
if (pending.isEmpty) return;
_setStatus('Removing deleted bank txs…');
try {
final matched = await service.deleteTransactionsMatching(pending);
if (matched.isNotEmpty) {
_bank.clearRemoteDeletesMatching(matched);
}
// Do NOT clear unmatched tombstones — they still block pull resurrection
// until pushTransactions GC removes the remote rows.
} catch (error) {
debugPrint('SyncController: tx deletes failed ($error)');
}
}
void _armPushDebounce() {
if (!_auth.isLoggedIn) return;
if (_syncing) {
@@ -297,6 +323,8 @@ class SyncController extends ChangeNotifier {
try {
final service = PbSyncService(_auth.client);
// Delete first — otherwise pull re-merges the row and push recreates it.
await _flushPendingTxDeletes(service);
final remoteMeta = await service.pull(
onProgress: (p) {
_setProgress(p * 0.35);
@@ -408,22 +436,20 @@ class SyncController extends ChangeNotifier {
} catch (error) {
debugPrint('SyncController: app_prefs push skipped ($error)');
}
final pendingDeletes = _bank.takePendingRemoteDeletes();
if (pendingDeletes.isNotEmpty) {
try {
await service.deleteTransactionsByTxIds(pendingDeletes);
} catch (error) {
debugPrint('SyncController: tx deletes skipped ($error)');
_bank.requeueRemoteDeletes(pendingDeletes);
}
}
// Retry deletes in case any were queued during the pull/merge window.
await _flushPendingTxDeletes(service);
_pushBankPending = false;
final tombs = List<BankTransaction>.of(_bank.pendingRemoteDeletes);
final bankSummary = await service.pushTransactions(
_bank.transactions,
deleteTombs: tombs,
progressStart: 0.82,
progressEnd: 1.0,
onProgress: _setProgress,
onStatus: _setStatus,
);
// Push GC removes orphan admin test rows; tombstones are done.
_bank.clearAllPendingRemoteDeletes();
_lastSyncedAt = DateTime.now();
_lastError = null;
_lastSyncSummary = '$metaSummary\n$bankSummary';
@@ -463,11 +489,17 @@ class SyncController extends ChangeNotifier {
final pushFavourites = _pushFavouritesPending;
final pushHomeWidgets = _pushHomeWidgetsPending;
final pushAppPrefs = _pushAppPrefsPending;
final pushBank = _pushBankPending || _bank.pendingRemoteDeletes.isNotEmpty;
_pushMetaPending = false;
_pushFavouritesPending = false;
_pushHomeWidgetsPending = false;
_pushAppPrefsPending = false;
if (!pushMeta && !pushFavourites && !pushHomeWidgets && !pushAppPrefs) {
_pushBankPending = false;
if (!pushMeta &&
!pushFavourites &&
!pushHomeWidgets &&
!pushAppPrefs &&
!pushBank) {
return;
}
@@ -480,13 +512,15 @@ class SyncController extends ChangeNotifier {
pushFavourites,
pushHomeWidgets,
pushAppPrefs,
pushBank,
)) {
(false, false, false, true) => 'App prefs',
(false, false, true, false) => 'Home widgets',
(false, false, true, true) => 'Home layout',
(false, true, false, false) => 'Favourites',
(false, true, true, _) => 'Home layout',
(true, false, false, false) => 'Annotations',
(false, false, false, false, true) => 'Bank txs',
(false, false, false, true, false) => 'App prefs',
(false, false, true, false, false) => 'Home widgets',
(false, false, true, true, _) => 'Home layout',
(false, true, false, false, false) => 'Favourites',
(false, true, true, _, _) => 'Home layout',
(true, false, false, false, false) => 'Annotations',
_ => 'Changes',
};
_statusDetail = 'Pushing $label…';
@@ -500,7 +534,8 @@ class SyncController extends ChangeNotifier {
final total = (pushMeta ? 1 : 0) +
(pushFavourites ? 1 : 0) +
(pushHomeWidgets ? 1 : 0) +
(pushAppPrefs ? 1 : 0);
(pushAppPrefs ? 1 : 0) +
(pushBank ? 1 : 0);
void bump() {
done++;
_setProgress(done / total);
@@ -564,6 +599,27 @@ class SyncController extends ChangeNotifier {
}
bump();
}
if (pushBank) {
_setStatus('Updating bank txs…');
await _flushPendingTxDeletes(service);
try {
final tombs = List<BankTransaction>.of(_bank.pendingRemoteDeletes);
final summary = await service.pushTransactions(
_bank.transactions,
deleteTombs: tombs,
progressStart: done / total,
progressEnd: (done + 1) / total,
onProgress: _setProgress,
onStatus: _setStatus,
);
_bank.clearAllPendingRemoteDeletes();
parts.add(summary);
} catch (error) {
debugPrint('SyncController: bank tx push skipped ($error)');
_pushBankPending = true;
}
bump();
}
_setProgress(1.0);
_lastSyncedAt = DateTime.now();
@@ -597,6 +653,7 @@ class SyncController extends ChangeNotifier {
_uiNotifyThrottle?.cancel();
_auth.removeListener(_onAuthChanged);
_bank.onAfterSuccessfulLoad = null;
_bank.onPendingRemoteDeletesChanged = null;
_meta.onPersisted = null;
_prefs.onFavouritesPersisted = null;
_prefs.onHomeWidgetsPersisted = null;