mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-07-20 21:28:41 -04:00
simplify reconciliation
This commit is contained in:
parent
bf38c2c44d
commit
4797184a1a
12 changed files with 512 additions and 345 deletions
|
@ -9,64 +9,68 @@ import '../../../proto/proto.dart' as proto;
|
|||
|
||||
@immutable
|
||||
class InputWindow {
|
||||
const InputWindow(
|
||||
{required this.elements, required this.first, required this.last});
|
||||
const InputWindow({required this.elements, required this.firstPosition})
|
||||
: lastPosition = firstPosition + elements.length - 1,
|
||||
isEmpty = elements.length == 0,
|
||||
length = elements.length;
|
||||
|
||||
final IList<OnlineElementState<proto.Message>> elements;
|
||||
final int first;
|
||||
final int last;
|
||||
final int firstPosition;
|
||||
final int lastPosition;
|
||||
final bool isEmpty;
|
||||
final int length;
|
||||
}
|
||||
|
||||
class AuthorInputSource {
|
||||
AuthorInputSource.fromCubit(
|
||||
{required DHTLogStateData<proto.Message> cubitState,
|
||||
required this.cubit}) {
|
||||
_currentWindow = InputWindow(
|
||||
elements: cubitState.window,
|
||||
first: (cubitState.windowTail - cubitState.window.length) %
|
||||
cubitState.length,
|
||||
last: (cubitState.windowTail - 1) % cubitState.length);
|
||||
}
|
||||
AuthorInputSource.fromDHTLog(DHTLog dhtLog) : _dhtLog = dhtLog;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InputWindow get currentWindow => _currentWindow;
|
||||
Future<int> getTailPosition() async =>
|
||||
_dhtLog.operate((reader) async => reader.length);
|
||||
|
||||
Future<AsyncValue<bool>> updateWindow(
|
||||
int currentPosition, int windowLength) async =>
|
||||
cubit.operate((reader) async {
|
||||
// See if we're beyond the input source
|
||||
if (currentPosition < 0 || currentPosition >= reader.length) {
|
||||
return const AsyncValue.data(false);
|
||||
}
|
||||
|
||||
// Slide the window if we need to
|
||||
var first = _currentWindow.first;
|
||||
var last = _currentWindow.last;
|
||||
if (currentPosition < first) {
|
||||
// Slide it backward, current position is now last
|
||||
first = max((currentPosition - windowLength) + 1, 0);
|
||||
last = currentPosition;
|
||||
} else if (currentPosition > last) {
|
||||
// Slide it forward, current position is now first
|
||||
first = currentPosition;
|
||||
last = min((currentPosition + windowLength) - 1, reader.length - 1);
|
||||
} else {
|
||||
return const AsyncValue.data(true);
|
||||
Future<AsyncValue<InputWindow?>> getWindow(
|
||||
int startPosition, int windowLength) async =>
|
||||
_dhtLog.operate((reader) async {
|
||||
// Don't allow negative length
|
||||
if (windowLength <= 0) {
|
||||
return const AsyncValue.data(null);
|
||||
}
|
||||
// Trim if we're beyond input source
|
||||
var endPosition = startPosition + windowLength - 1;
|
||||
startPosition = max(startPosition, 0);
|
||||
endPosition = max(endPosition, 0);
|
||||
|
||||
// Get another input batch futher back
|
||||
final nextWindow = await cubit.loadElementsFromReader(
|
||||
reader, last + 1, (last + 1) - first);
|
||||
if (nextWindow == null) {
|
||||
return const AsyncValue.loading();
|
||||
try {
|
||||
Set<int>? offlinePositions;
|
||||
if (_dhtLog.writer != null) {
|
||||
offlinePositions = await reader.getOfflinePositions();
|
||||
}
|
||||
|
||||
final messages = await reader.getRangeProtobuf(
|
||||
proto.Message.fromBuffer, startPosition,
|
||||
length: endPosition - startPosition + 1);
|
||||
if (messages == null) {
|
||||
return const AsyncValue.loading();
|
||||
}
|
||||
|
||||
final elements = messages.indexed
|
||||
.map((x) => OnlineElementState(
|
||||
value: x.$2,
|
||||
isOffline: offlinePositions?.contains(x.$1 + startPosition) ??
|
||||
false))
|
||||
.toIList();
|
||||
|
||||
final window =
|
||||
InputWindow(elements: elements, firstPosition: startPosition);
|
||||
|
||||
return AsyncValue.data(window);
|
||||
} on Exception catch (e, st) {
|
||||
return AsyncValue.error(e, st);
|
||||
}
|
||||
_currentWindow =
|
||||
InputWindow(elements: nextWindow, first: first, last: last);
|
||||
return const AsyncValue.data(true);
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
final DHTLogCubit<proto.Message> cubit;
|
||||
|
||||
late InputWindow _currentWindow;
|
||||
final DHTLog _dhtLog;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue