mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-10-01 06:55:46 -04:00
better handling of subkeys for spine
This commit is contained in:
parent
0b9835b23d
commit
2c3d4dce93
@ -36,161 +36,161 @@ void main() {
|
|||||||
setUpAll(veilidFixture.attach);
|
setUpAll(veilidFixture.attach);
|
||||||
tearDownAll(veilidFixture.detach);
|
tearDownAll(veilidFixture.detach);
|
||||||
|
|
||||||
// group('TableDB Tests', () {
|
group('TableDB Tests', () {
|
||||||
// group('TableDBArray Tests', () {
|
group('TableDBArray Tests', () {
|
||||||
// // test('create/delete TableDBArray', testTableDBArrayCreateDelete);
|
// test('create/delete TableDBArray', testTableDBArrayCreateDelete);
|
||||||
|
|
||||||
// group('TableDBArray Add/Get Tests', () {
|
group('TableDBArray Add/Get Tests', () {
|
||||||
// for (final params in [
|
for (final params in [
|
||||||
// //
|
//
|
||||||
// (99, 3, 15),
|
(99, 3, 15),
|
||||||
// (100, 4, 16),
|
(100, 4, 16),
|
||||||
// (101, 5, 17),
|
(101, 5, 17),
|
||||||
// //
|
//
|
||||||
// (511, 3, 127),
|
(511, 3, 127),
|
||||||
// (512, 4, 128),
|
(512, 4, 128),
|
||||||
// (513, 5, 129),
|
(513, 5, 129),
|
||||||
// //
|
//
|
||||||
// (4095, 3, 1023),
|
(4095, 3, 1023),
|
||||||
// (4096, 4, 1024),
|
(4096, 4, 1024),
|
||||||
// (4097, 5, 1025),
|
(4097, 5, 1025),
|
||||||
// //
|
//
|
||||||
// (65535, 3, 16383),
|
(65535, 3, 16383),
|
||||||
// (65536, 4, 16384),
|
(65536, 4, 16384),
|
||||||
// (65537, 5, 16385),
|
(65537, 5, 16385),
|
||||||
// ]) {
|
]) {
|
||||||
// final count = params.$1;
|
final count = params.$1;
|
||||||
// final singles = params.$2;
|
final singles = params.$2;
|
||||||
// final batchSize = params.$3;
|
final batchSize = params.$3;
|
||||||
|
|
||||||
// test(
|
test(
|
||||||
// timeout: const Timeout(Duration(seconds: 480)),
|
timeout: const Timeout(Duration(seconds: 480)),
|
||||||
// 'add/remove TableDBArray count = $count batchSize=$batchSize',
|
'add/remove TableDBArray count = $count batchSize=$batchSize',
|
||||||
// makeTestTableDBArrayAddGetClear(
|
makeTestTableDBArrayAddGetClear(
|
||||||
// count: count,
|
count: count,
|
||||||
// singles: singles,
|
singles: singles,
|
||||||
// batchSize: batchSize,
|
batchSize: batchSize,
|
||||||
// crypto: const VeilidCryptoPublic()),
|
crypto: const VeilidCryptoPublic()),
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
|
|
||||||
// group('TableDBArray Insert Tests', () {
|
group('TableDBArray Insert Tests', () {
|
||||||
// for (final params in [
|
for (final params in [
|
||||||
// //
|
//
|
||||||
// (99, 3, 15),
|
(99, 3, 15),
|
||||||
// (100, 4, 16),
|
(100, 4, 16),
|
||||||
// (101, 5, 17),
|
(101, 5, 17),
|
||||||
// //
|
//
|
||||||
// (511, 3, 127),
|
(511, 3, 127),
|
||||||
// (512, 4, 128),
|
(512, 4, 128),
|
||||||
// (513, 5, 129),
|
(513, 5, 129),
|
||||||
// //
|
//
|
||||||
// (4095, 3, 1023),
|
(4095, 3, 1023),
|
||||||
// (4096, 4, 1024),
|
(4096, 4, 1024),
|
||||||
// (4097, 5, 1025),
|
(4097, 5, 1025),
|
||||||
// //
|
//
|
||||||
// (65535, 3, 16383),
|
(65535, 3, 16383),
|
||||||
// (65536, 4, 16384),
|
(65536, 4, 16384),
|
||||||
// (65537, 5, 16385),
|
(65537, 5, 16385),
|
||||||
// ]) {
|
]) {
|
||||||
// final count = params.$1;
|
final count = params.$1;
|
||||||
// final singles = params.$2;
|
final singles = params.$2;
|
||||||
// final batchSize = params.$3;
|
final batchSize = params.$3;
|
||||||
|
|
||||||
// test(
|
test(
|
||||||
// timeout: const Timeout(Duration(seconds: 480)),
|
timeout: const Timeout(Duration(seconds: 480)),
|
||||||
// 'insert TableDBArray count=$count singles=$singles batchSize=$batchSize',
|
'insert TableDBArray count=$count singles=$singles batchSize=$batchSize',
|
||||||
// makeTestTableDBArrayInsert(
|
makeTestTableDBArrayInsert(
|
||||||
// count: count,
|
count: count,
|
||||||
// singles: singles,
|
singles: singles,
|
||||||
// batchSize: batchSize,
|
batchSize: batchSize,
|
||||||
// crypto: const VeilidCryptoPublic()),
|
crypto: const VeilidCryptoPublic()),
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
|
|
||||||
// group('TableDBArray Remove Tests', () {
|
group('TableDBArray Remove Tests', () {
|
||||||
// for (final params in [
|
for (final params in [
|
||||||
// //
|
//
|
||||||
// (99, 3, 15),
|
(99, 3, 15),
|
||||||
// (100, 4, 16),
|
(100, 4, 16),
|
||||||
// (101, 5, 17),
|
(101, 5, 17),
|
||||||
// //
|
//
|
||||||
// (511, 3, 127),
|
(511, 3, 127),
|
||||||
// (512, 4, 128),
|
(512, 4, 128),
|
||||||
// (513, 5, 129),
|
(513, 5, 129),
|
||||||
// //
|
//
|
||||||
// (4095, 3, 1023),
|
(4095, 3, 1023),
|
||||||
// (4096, 4, 1024),
|
(4096, 4, 1024),
|
||||||
// (4097, 5, 1025),
|
(4097, 5, 1025),
|
||||||
// //
|
//
|
||||||
// (16383, 3, 4095),
|
(16383, 3, 4095),
|
||||||
// (16384, 4, 4096),
|
(16384, 4, 4096),
|
||||||
// (16385, 5, 4097),
|
(16385, 5, 4097),
|
||||||
// ]) {
|
]) {
|
||||||
// final count = params.$1;
|
final count = params.$1;
|
||||||
// final singles = params.$2;
|
final singles = params.$2;
|
||||||
// final batchSize = params.$3;
|
final batchSize = params.$3;
|
||||||
|
|
||||||
// test(
|
test(
|
||||||
// timeout: const Timeout(Duration(seconds: 480)),
|
timeout: const Timeout(Duration(seconds: 480)),
|
||||||
// 'remove TableDBArray count=$count singles=$singles batchSize=$batchSize',
|
'remove TableDBArray count=$count singles=$singles batchSize=$batchSize',
|
||||||
// makeTestTableDBArrayRemove(
|
makeTestTableDBArrayRemove(
|
||||||
// count: count,
|
count: count,
|
||||||
// singles: singles,
|
singles: singles,
|
||||||
// batchSize: batchSize,
|
batchSize: batchSize,
|
||||||
// crypto: const VeilidCryptoPublic()),
|
crypto: const VeilidCryptoPublic()),
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
group('DHT Support Tests', () {
|
|
||||||
setUpAll(updateProcessorFixture.setUp);
|
|
||||||
setUpAll(tickerFixture.setUp);
|
|
||||||
tearDownAll(tickerFixture.tearDown);
|
|
||||||
tearDownAll(updateProcessorFixture.tearDown);
|
|
||||||
|
|
||||||
test('create pool', testDHTRecordPoolCreate);
|
|
||||||
|
|
||||||
group('DHTRecordPool Tests', () {
|
|
||||||
setUpAll(dhtRecordPoolFixture.setUp);
|
|
||||||
tearDownAll(dhtRecordPoolFixture.tearDown);
|
|
||||||
|
|
||||||
test('create/delete record', testDHTRecordCreateDelete);
|
|
||||||
test('record scopes', testDHTRecordScopes);
|
|
||||||
test('create/delete deep record', testDHTRecordDeepCreateDelete);
|
|
||||||
});
|
|
||||||
|
|
||||||
group('DHTShortArray Tests', () {
|
|
||||||
setUpAll(dhtRecordPoolFixture.setUp);
|
|
||||||
tearDownAll(dhtRecordPoolFixture.tearDown);
|
|
||||||
|
|
||||||
for (final stride in [256, 16 /*64, 32, 16, 8, 4, 2, 1 */]) {
|
|
||||||
test('create shortarray stride=$stride',
|
|
||||||
makeTestDHTShortArrayCreateDelete(stride: stride));
|
|
||||||
test('add shortarray stride=$stride',
|
|
||||||
makeTestDHTShortArrayAdd(stride: stride));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
group('DHTLog Tests', () {
|
|
||||||
setUpAll(dhtRecordPoolFixture.setUp);
|
|
||||||
tearDownAll(dhtRecordPoolFixture.tearDown);
|
|
||||||
|
|
||||||
for (final stride in [256, 16 /*64, 32, 16, 8, 4, 2, 1 */]) {
|
|
||||||
test('create log stride=$stride',
|
|
||||||
makeTestDHTLogCreateDelete(stride: stride));
|
|
||||||
test(
|
|
||||||
timeout: const Timeout(Duration(seconds: 480)),
|
|
||||||
'add/truncate log stride=$stride',
|
|
||||||
makeTestDHTLogAddTruncate(stride: stride),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// group('DHT Support Tests', () {
|
||||||
|
// setUpAll(updateProcessorFixture.setUp);
|
||||||
|
// setUpAll(tickerFixture.setUp);
|
||||||
|
// tearDownAll(tickerFixture.tearDown);
|
||||||
|
// tearDownAll(updateProcessorFixture.tearDown);
|
||||||
|
|
||||||
|
// test('create pool', testDHTRecordPoolCreate);
|
||||||
|
|
||||||
|
// group('DHTRecordPool Tests', () {
|
||||||
|
// setUpAll(dhtRecordPoolFixture.setUp);
|
||||||
|
// tearDownAll(dhtRecordPoolFixture.tearDown);
|
||||||
|
|
||||||
|
// test('create/delete record', testDHTRecordCreateDelete);
|
||||||
|
// test('record scopes', testDHTRecordScopes);
|
||||||
|
// test('create/delete deep record', testDHTRecordDeepCreateDelete);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// group('DHTShortArray Tests', () {
|
||||||
|
// setUpAll(dhtRecordPoolFixture.setUp);
|
||||||
|
// tearDownAll(dhtRecordPoolFixture.tearDown);
|
||||||
|
|
||||||
|
// for (final stride in [256, 16 /*64, 32, 16, 8, 4, 2, 1 */]) {
|
||||||
|
// test('create shortarray stride=$stride',
|
||||||
|
// makeTestDHTShortArrayCreateDelete(stride: stride));
|
||||||
|
// test('add shortarray stride=$stride',
|
||||||
|
// makeTestDHTShortArrayAdd(stride: stride));
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// group('DHTLog Tests', () {
|
||||||
|
// setUpAll(dhtRecordPoolFixture.setUp);
|
||||||
|
// tearDownAll(dhtRecordPoolFixture.tearDown);
|
||||||
|
|
||||||
|
// for (final stride in [256, 16 /*64, 32, 16, 8, 4, 2, 1 */]) {
|
||||||
|
// test('create log stride=$stride',
|
||||||
|
// makeTestDHTLogCreateDelete(stride: stride));
|
||||||
|
// test(
|
||||||
|
// timeout: const Timeout(Duration(seconds: 480)),
|
||||||
|
// 'add/truncate log stride=$stride',
|
||||||
|
// makeTestDHTLogAddTruncate(stride: stride),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,9 @@ class DHTLog implements DHTDeleteable<DHTLog> {
|
|||||||
/// Get the record key for this log
|
/// Get the record key for this log
|
||||||
TypedKey get recordKey => _spine.recordKey;
|
TypedKey get recordKey => _spine.recordKey;
|
||||||
|
|
||||||
|
/// Get the writer for the log
|
||||||
|
KeyPair? get writer => _spine._spineRecord.writer;
|
||||||
|
|
||||||
/// Get the record pointer foir this log
|
/// Get the record pointer foir this log
|
||||||
OwnedDHTRecordPointer get recordPointer => _spine.recordPointer;
|
OwnedDHTRecordPointer get recordPointer => _spine.recordPointer;
|
||||||
|
|
||||||
|
@ -126,13 +126,22 @@ class DHTLogCubit<T> extends Cubit<DHTLogBusyState<T>>
|
|||||||
final end = ((tail - 1) % length) + 1;
|
final end = ((tail - 1) % length) + 1;
|
||||||
final start = (count < end) ? end - count : 0;
|
final start = (count < end) ? end - count : 0;
|
||||||
|
|
||||||
final offlinePositions = await reader.getOfflinePositions();
|
// If this is writeable get the offline positions
|
||||||
|
Set<int>? offlinePositions;
|
||||||
|
if (_log.writer != null) {
|
||||||
|
offlinePositions = await reader.getOfflinePositions();
|
||||||
|
if (offlinePositions == null) {
|
||||||
|
return const AsyncValue.loading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the items
|
||||||
final allItems = (await reader.getRange(start,
|
final allItems = (await reader.getRange(start,
|
||||||
length: end - start, forceRefresh: forceRefresh))
|
length: end - start, forceRefresh: forceRefresh))
|
||||||
?.indexed
|
?.indexed
|
||||||
.map((x) => OnlineElementState(
|
.map((x) => OnlineElementState(
|
||||||
value: _decodeElement(x.$2),
|
value: _decodeElement(x.$2),
|
||||||
isOffline: offlinePositions.contains(x.$1)))
|
isOffline: offlinePositions?.contains(x.$1) ?? false))
|
||||||
.toIList();
|
.toIList();
|
||||||
if (allItems == null) {
|
if (allItems == null) {
|
||||||
return const AsyncValue.loading();
|
return const AsyncValue.loading();
|
||||||
|
@ -61,20 +61,23 @@ class _DHTLogRead implements DHTLogReadOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Set<int>> getOfflinePositions() async {
|
Future<Set<int>?> getOfflinePositions() async {
|
||||||
final positionOffline = <int>{};
|
final positionOffline = <int>{};
|
||||||
|
|
||||||
// Iterate positions backward from most recent
|
// Iterate positions backward from most recent
|
||||||
for (var pos = _spine.length - 1; pos >= 0; pos--) {
|
for (var pos = _spine.length - 1; pos >= 0; pos--) {
|
||||||
final lookup = await _spine.lookupPosition(pos);
|
final lookup = await _spine.lookupPosition(pos);
|
||||||
if (lookup == null) {
|
if (lookup == null) {
|
||||||
throw StateError('Unable to look up position');
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check each segment for offline positions
|
// Check each segment for offline positions
|
||||||
var foundOffline = false;
|
var foundOffline = false;
|
||||||
await lookup.scope((sa) => sa.operate((read) async {
|
final success = await lookup.scope((sa) => sa.operate((read) async {
|
||||||
final segmentOffline = await read.getOfflinePositions();
|
final segmentOffline = await read.getOfflinePositions();
|
||||||
|
if (segmentOffline == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// For each shortarray segment go through their segment positions
|
// For each shortarray segment go through their segment positions
|
||||||
// in reverse order and see if they are offline
|
// in reverse order and see if they are offline
|
||||||
@ -88,8 +91,11 @@ class _DHTLogRead implements DHTLogReadOperations {
|
|||||||
foundOffline = true;
|
foundOffline = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}));
|
}));
|
||||||
|
if (!success) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// If we found nothing offline in this segment then we can stop
|
// If we found nothing offline in this segment then we can stop
|
||||||
if (!foundOffline) {
|
if (!foundOffline) {
|
||||||
break;
|
break;
|
||||||
|
@ -354,13 +354,24 @@ class _DHTLogSpine {
|
|||||||
final subkey = l.subkey;
|
final subkey = l.subkey;
|
||||||
final segment = l.segment;
|
final segment = l.segment;
|
||||||
|
|
||||||
final subkeyData = await _spineRecord.get(subkey: subkey);
|
// See if we have the segment key locally
|
||||||
if (subkeyData == null) {
|
TypedKey? segmentKey;
|
||||||
return null;
|
var subkeyData = await _spineRecord.get(
|
||||||
|
subkey: subkey, refreshMode: DHTRecordRefreshMode.local);
|
||||||
|
if (subkeyData != null) {
|
||||||
|
segmentKey = _getSegmentKey(subkeyData, segment);
|
||||||
}
|
}
|
||||||
final segmentKey = _getSegmentKey(subkeyData, segment);
|
|
||||||
if (segmentKey == null) {
|
if (segmentKey == null) {
|
||||||
return null;
|
// If not, try from the network
|
||||||
|
subkeyData = await _spineRecord.get(
|
||||||
|
subkey: subkey, refreshMode: DHTRecordRefreshMode.network);
|
||||||
|
if (subkeyData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
segmentKey = _getSegmentKey(subkeyData, segment);
|
||||||
|
if (segmentKey == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a shortarray segment
|
// Open a shortarray segment
|
||||||
|
@ -16,7 +16,7 @@ class DHTRecordWatchChange extends Equatable {
|
|||||||
/// Refresh mode for DHT record 'get'
|
/// Refresh mode for DHT record 'get'
|
||||||
enum DHTRecordRefreshMode {
|
enum DHTRecordRefreshMode {
|
||||||
/// Return existing subkey values if they exist locally already
|
/// Return existing subkey values if they exist locally already
|
||||||
/// And then check the network for a newer value
|
/// If not, check the network for a value
|
||||||
/// This is the default refresh mode
|
/// This is the default refresh mode
|
||||||
cached,
|
cached,
|
||||||
|
|
||||||
|
@ -182,6 +182,9 @@ class DHTShortArray implements DHTDeleteable<DHTShortArray> {
|
|||||||
/// Get the record key for this shortarray
|
/// Get the record key for this shortarray
|
||||||
TypedKey get recordKey => _head.recordKey;
|
TypedKey get recordKey => _head.recordKey;
|
||||||
|
|
||||||
|
/// Get the writer for the log
|
||||||
|
KeyPair? get writer => _head._headRecord.writer;
|
||||||
|
|
||||||
/// Get the record pointer foir this shortarray
|
/// Get the record pointer foir this shortarray
|
||||||
OwnedDHTRecordPointer get recordPointer => _head.recordPointer;
|
OwnedDHTRecordPointer get recordPointer => _head.recordPointer;
|
||||||
|
|
||||||
|
@ -53,12 +53,21 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
|
|||||||
{bool forceRefresh = false}) async {
|
{bool forceRefresh = false}) async {
|
||||||
try {
|
try {
|
||||||
final newState = await _shortArray.operate((reader) async {
|
final newState = await _shortArray.operate((reader) async {
|
||||||
final offlinePositions = await reader.getOfflinePositions();
|
// If this is writeable get the offline positions
|
||||||
|
Set<int>? offlinePositions;
|
||||||
|
if (_shortArray.writer != null) {
|
||||||
|
offlinePositions = await reader.getOfflinePositions();
|
||||||
|
if (offlinePositions == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the items
|
||||||
final allItems = (await reader.getRange(0, forceRefresh: forceRefresh))
|
final allItems = (await reader.getRange(0, forceRefresh: forceRefresh))
|
||||||
?.indexed
|
?.indexed
|
||||||
.map((x) => DHTShortArrayElementState(
|
.map((x) => DHTShortArrayElementState(
|
||||||
value: _decodeElement(x.$2),
|
value: _decodeElement(x.$2),
|
||||||
isOffline: offlinePositions.contains(x.$1)))
|
isOffline: offlinePositions?.contains(x.$1) ?? false))
|
||||||
.toIList();
|
.toIList();
|
||||||
return allItems;
|
return allItems;
|
||||||
});
|
});
|
||||||
|
@ -26,7 +26,7 @@ abstract class DHTRandomRead {
|
|||||||
{int? length, bool forceRefresh = false});
|
{int? length, bool forceRefresh = false});
|
||||||
|
|
||||||
/// Get a list of the positions that were written offline and not flushed yet
|
/// Get a list of the positions that were written offline and not flushed yet
|
||||||
Future<Set<int>> getOfflinePositions();
|
Future<Set<int>?> getOfflinePositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DHTRandomReadExt on DHTRandomRead {
|
extension DHTRandomReadExt on DHTRandomRead {
|
||||||
|
Loading…
Reference in New Issue
Block a user