From e6d96ad8edd48c3780c9db4811c8f42d29f64166 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 4 Sep 2020 13:10:09 +0200 Subject: [PATCH] feat(sync): configurable sync --- lib/src/client.dart | 63 +++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index 1a458eb..76b38b3 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -21,7 +21,6 @@ import 'dart:convert'; import 'dart:core'; import 'package:http/http.dart' as http; -import 'package:pedantic/pedantic.dart'; import '../encryption.dart'; import '../famedlysdk.dart'; @@ -656,6 +655,7 @@ class Client extends MatrixApi { 'Successfully connected as ${userID.localpart} with ${homeserver.toString()}', ); + // Always do a _sync after login, even if backgroundSync is set to off return _sync(); } @@ -675,25 +675,48 @@ class Client extends MatrixApi { onLoginStateChanged.add(LoginState.loggedOut); } - Future _syncRequest; - Exception _lastSyncError; + bool _backgroundSync = true; + Future _currentSync, _retryDelay = Future.value(); + bool get syncPending => _currentSync != null; - Future _sync() async { - if (isLogged() == false || _disposed) return; + /// Controls the background sync (automatically looping forever if turned on). + set backgroundSync(bool enabled) { + _backgroundSync = enabled; + if (_backgroundSync) { + _sync(); + } + } + + /// Immediately start a sync and wait for completion. + /// If there is an active sync already, wait for the active sync instead. + Future oneShotSync() { + return _sync(); + } + + Future _sync() { + if (_currentSync == null) { + _currentSync = _innerSync(); + _currentSync.whenComplete(() { + _currentSync = null; + if (_backgroundSync && isLogged() && !_disposed) { + _sync(); + } + }); + } + return _currentSync; + } + + Future _innerSync() async { + await _retryDelay; + _retryDelay = Future.delayed(Duration(seconds: syncErrorTimeoutSec)); + if (!isLogged() || _disposed) return null; try { - _syncRequest = sync( + final syncResp = await sync( filter: syncFilters, since: prevBatch, timeout: prevBatch != null ? 30000 : null, - ).catchError((e) { - _lastSyncError = e; - return null; - }); - final hash = _syncRequest.hashCode; - final syncResp = await _syncRequest; + ); if (_disposed) return; - if (syncResp == null) throw _lastSyncError; - if (hash != _syncRequest.hashCode) return; if (database != null) { _currentTransaction = database.transaction(() async { await handleSync(syncResp); @@ -716,18 +739,14 @@ class Client extends MatrixApi { if (encryptionEnabled) { encryption.onSync(); } - if (hash == _syncRequest.hashCode) unawaited(_sync()); - } on MatrixException catch (exception) { - onError.add(exception); - await Future.delayed(Duration(seconds: syncErrorTimeoutSec), _sync); + _retryDelay = Future.value(); + } on MatrixException catch (e) { + onError.add(e); } catch (e, s) { - if (isLogged() == false || _disposed) { - return; - } + if (!isLogged() || _disposed) return; Logs.error('Error during processing events: ' + e.toString(), s); onSyncError.add(SdkError( exception: e is Exception ? e : Exception(e), stackTrace: s)); - await Future.delayed(Duration(seconds: syncErrorTimeoutSec), _sync); } }