@@ -302,29 +302,36 @@ class StreamingSyncImplementation implements StreamingSync {
302
302
_statusStreamController.add (newStatus);
303
303
}
304
304
305
- Future <bool > streamingSyncIteration (
306
- {AbortController ? abortController}) async {
307
- adapter.startSession ();
305
+ Future <(List <BucketRequest >, Map <String , BucketDescription >)>
306
+ _collectLocalBucketState () async {
308
307
final bucketEntries = await adapter.getBucketStates ();
309
308
310
- Map <String , String > initialBucketStates = {};
309
+ final initialRequests = [
310
+ for (final entry in bucketEntries) BucketRequest (entry.bucket, entry.opId)
311
+ ];
312
+ final localDescriptions = {
313
+ for (final entry in bucketEntries)
314
+ entry.bucket: (
315
+ name: entry.bucket,
316
+ priority: entry.priority,
317
+ )
318
+ };
311
319
312
- for (final entry in bucketEntries) {
313
- initialBucketStates[entry.bucket] = entry.opId;
314
- }
320
+ return (initialRequests, localDescriptions);
321
+ }
315
322
316
- final List <BucketRequest > buckets = [];
317
- for (var entry in initialBucketStates.entries) {
318
- buckets.add (BucketRequest (entry.key, entry.value));
319
- }
323
+ Future <bool > streamingSyncIteration (
324
+ {AbortController ? abortController}) async {
325
+ adapter.startSession ();
326
+
327
+ var (bucketRequests, bucketMap) = await _collectLocalBucketState ();
320
328
321
329
Checkpoint ? targetCheckpoint;
322
330
Checkpoint ? validatedCheckpoint;
323
331
Checkpoint ? appliedCheckpoint;
324
- var bucketSet = Set <String >.from (initialBucketStates.keys);
325
332
326
333
var requestStream = streamingSyncRequest (
327
- StreamingSyncRequest (buckets , syncParameters, clientId! ));
334
+ StreamingSyncRequest (bucketRequests , syncParameters, clientId! ));
328
335
329
336
var merged = addBroadcast (requestStream, _localPingController.stream);
330
337
@@ -343,13 +350,16 @@ class StreamingSyncImplementation implements StreamingSync {
343
350
switch (line) {
344
351
case Checkpoint ():
345
352
targetCheckpoint = line;
346
- final Set <String > bucketsToDelete = {...bucketSet };
347
- final Set <String > newBuckets = {};
353
+ final Set <String > bucketsToDelete = {...bucketMap.keys };
354
+ final Map <String , BucketDescription > newBuckets = {};
348
355
for (final checksum in line.checksums) {
349
- newBuckets.add (checksum.bucket);
356
+ newBuckets[checksum.bucket] = (
357
+ name: checksum.bucket,
358
+ priority: checksum.priority,
359
+ );
350
360
bucketsToDelete.remove (checksum.bucket);
351
361
}
352
- bucketSet = newBuckets;
362
+ bucketMap = newBuckets;
353
363
await adapter.removeBuckets ([...bucketsToDelete]);
354
364
_updateStatus (downloading: true );
355
365
case StreamingSyncCheckpointComplete ():
@@ -371,6 +381,27 @@ class StreamingSyncImplementation implements StreamingSync {
371
381
lastSyncedAt: DateTime .now ());
372
382
}
373
383
384
+ validatedCheckpoint = targetCheckpoint;
385
+ case StreamingSyncCheckpointPartiallyComplete (: final bucketPriority):
386
+ final result = await adapter.syncLocalDatabase (targetCheckpoint! ,
387
+ forPriority: bucketPriority);
388
+ if (! result.checkpointValid) {
389
+ // This means checksums failed. Start again with a new checkpoint.
390
+ // TODO: better back-off
391
+ // await new Promise((resolve) => setTimeout(resolve, 50));
392
+ return false ;
393
+ } else if (! result.ready) {
394
+ // Checksums valid, but need more data for a consistent checkpoint.
395
+ // Continue waiting.
396
+ } else {
397
+ appliedCheckpoint = targetCheckpoint;
398
+
399
+ _updateStatus (
400
+ downloading: false ,
401
+ downloadError: _noError,
402
+ lastSyncedAt: DateTime .now ());
403
+ }
404
+
374
405
validatedCheckpoint = targetCheckpoint;
375
406
case StreamingSyncCheckpointDiff ():
376
407
// TODO: It may be faster to just keep track of the diff, instead of the entire checkpoint
@@ -397,7 +428,8 @@ class StreamingSyncImplementation implements StreamingSync {
397
428
writeCheckpoint: diff.writeCheckpoint);
398
429
targetCheckpoint = newCheckpoint;
399
430
400
- bucketSet = Set .from (newBuckets.keys);
431
+ bucketMap = newBuckets.map ((name, checksum) =>
432
+ MapEntry (name, (name: name, priority: checksum.priority)));
401
433
await adapter.removeBuckets (diff.removedBuckets);
402
434
adapter.setTargetCheckpoint (targetCheckpoint);
403
435
case SyncBucketData ():
@@ -424,6 +456,9 @@ class StreamingSyncImplementation implements StreamingSync {
424
456
});
425
457
}
426
458
}
459
+ case UnknownSyncLine (: final rawData):
460
+ isolateLogger.fine ('Ignoring unknown sync line: $rawData ' );
461
+ break ;
427
462
case null : // Local ping
428
463
if (targetCheckpoint == appliedCheckpoint) {
429
464
_updateStatus (
0 commit comments