@@ -302,29 +302,36 @@ class StreamingSyncImplementation implements StreamingSync {
302302 _statusStreamController.add (newStatus);
303303 }
304304
305- Future <bool > streamingSyncIteration (
306- {AbortController ? abortController}) async {
307- adapter.startSession ();
305+ Future <(List <BucketRequest >, Map <String , BucketDescription >)>
306+ _collectLocalBucketState () async {
308307 final bucketEntries = await adapter.getBucketStates ();
309308
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+ };
311319
312- for (final entry in bucketEntries) {
313- initialBucketStates[entry.bucket] = entry.opId;
314- }
320+ return (initialRequests, localDescriptions);
321+ }
315322
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 ();
320328
321329 Checkpoint ? targetCheckpoint;
322330 Checkpoint ? validatedCheckpoint;
323331 Checkpoint ? appliedCheckpoint;
324- var bucketSet = Set <String >.from (initialBucketStates.keys);
325332
326333 var requestStream = streamingSyncRequest (
327- StreamingSyncRequest (buckets , syncParameters, clientId! ));
334+ StreamingSyncRequest (bucketRequests , syncParameters, clientId! ));
328335
329336 var merged = addBroadcast (requestStream, _localPingController.stream);
330337
@@ -343,13 +350,16 @@ class StreamingSyncImplementation implements StreamingSync {
343350 switch (line) {
344351 case Checkpoint ():
345352 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 = {};
348355 for (final checksum in line.checksums) {
349- newBuckets.add (checksum.bucket);
356+ newBuckets[checksum.bucket] = (
357+ name: checksum.bucket,
358+ priority: checksum.priority,
359+ );
350360 bucketsToDelete.remove (checksum.bucket);
351361 }
352- bucketSet = newBuckets;
362+ bucketMap = newBuckets;
353363 await adapter.removeBuckets ([...bucketsToDelete]);
354364 _updateStatus (downloading: true );
355365 case StreamingSyncCheckpointComplete ():
@@ -371,6 +381,27 @@ class StreamingSyncImplementation implements StreamingSync {
371381 lastSyncedAt: DateTime .now ());
372382 }
373383
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+
374405 validatedCheckpoint = targetCheckpoint;
375406 case StreamingSyncCheckpointDiff ():
376407 // 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 {
397428 writeCheckpoint: diff.writeCheckpoint);
398429 targetCheckpoint = newCheckpoint;
399430
400- bucketSet = Set .from (newBuckets.keys);
431+ bucketMap = newBuckets.map ((name, checksum) =>
432+ MapEntry (name, (name: name, priority: checksum.priority)));
401433 await adapter.removeBuckets (diff.removedBuckets);
402434 adapter.setTargetCheckpoint (targetCheckpoint);
403435 case SyncBucketData ():
@@ -424,6 +456,9 @@ class StreamingSyncImplementation implements StreamingSync {
424456 });
425457 }
426458 }
459+ case UnknownSyncLine (: final rawData):
460+ isolateLogger.fine ('Ignoring unknown sync line: $rawData ' );
461+ break ;
427462 case null : // Local ping
428463 if (targetCheckpoint == appliedCheckpoint) {
429464 _updateStatus (
0 commit comments