feat(sync): configurable sync

This commit is contained in:
Lukas Lihotzki 2020-09-04 13:10:09 +02:00
parent 54a128d2c5
commit e6d96ad8ed

View file

@ -21,7 +21,6 @@ import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:pedantic/pedantic.dart';
import '../encryption.dart'; import '../encryption.dart';
import '../famedlysdk.dart'; import '../famedlysdk.dart';
@ -656,6 +655,7 @@ class Client extends MatrixApi {
'Successfully connected as ${userID.localpart} with ${homeserver.toString()}', 'Successfully connected as ${userID.localpart} with ${homeserver.toString()}',
); );
// Always do a _sync after login, even if backgroundSync is set to off
return _sync(); return _sync();
} }
@ -675,25 +675,48 @@ class Client extends MatrixApi {
onLoginStateChanged.add(LoginState.loggedOut); onLoginStateChanged.add(LoginState.loggedOut);
} }
Future<SyncUpdate> _syncRequest; bool _backgroundSync = true;
Exception _lastSyncError; Future<void> _currentSync, _retryDelay = Future.value();
bool get syncPending => _currentSync != null;
Future<void> _sync() async { /// Controls the background sync (automatically looping forever if turned on).
if (isLogged() == false || _disposed) return; 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<void> oneShotSync() {
return _sync();
}
Future<void> _sync() {
if (_currentSync == null) {
_currentSync = _innerSync();
_currentSync.whenComplete(() {
_currentSync = null;
if (_backgroundSync && isLogged() && !_disposed) {
_sync();
}
});
}
return _currentSync;
}
Future<void> _innerSync() async {
await _retryDelay;
_retryDelay = Future.delayed(Duration(seconds: syncErrorTimeoutSec));
if (!isLogged() || _disposed) return null;
try { try {
_syncRequest = sync( final syncResp = await sync(
filter: syncFilters, filter: syncFilters,
since: prevBatch, since: prevBatch,
timeout: prevBatch != null ? 30000 : null, timeout: prevBatch != null ? 30000 : null,
).catchError((e) { );
_lastSyncError = e;
return null;
});
final hash = _syncRequest.hashCode;
final syncResp = await _syncRequest;
if (_disposed) return; if (_disposed) return;
if (syncResp == null) throw _lastSyncError;
if (hash != _syncRequest.hashCode) return;
if (database != null) { if (database != null) {
_currentTransaction = database.transaction(() async { _currentTransaction = database.transaction(() async {
await handleSync(syncResp); await handleSync(syncResp);
@ -716,18 +739,14 @@ class Client extends MatrixApi {
if (encryptionEnabled) { if (encryptionEnabled) {
encryption.onSync(); encryption.onSync();
} }
if (hash == _syncRequest.hashCode) unawaited(_sync()); _retryDelay = Future.value();
} on MatrixException catch (exception) { } on MatrixException catch (e) {
onError.add(exception); onError.add(e);
await Future.delayed(Duration(seconds: syncErrorTimeoutSec), _sync);
} catch (e, s) { } catch (e, s) {
if (isLogged() == false || _disposed) { if (!isLogged() || _disposed) return;
return;
}
Logs.error('Error during processing events: ' + e.toString(), s); Logs.error('Error during processing events: ' + e.toString(), s);
onSyncError.add(SdkError( onSyncError.add(SdkError(
exception: e is Exception ? e : Exception(e), stackTrace: s)); exception: e is Exception ? e : Exception(e), stackTrace: s));
await Future.delayed(Duration(seconds: syncErrorTimeoutSec), _sync);
} }
} }