@@ -715,6 +715,7 @@ export class LevelLocalRepo implements LocalRepo {
715715 } catch ( error ) {
716716 if ( error instanceof Error && error . message === 'EXISTS' )
717717 // TODO: make sure reset does not happen, if models are the same.
718+ // TODO: Check for `req.time` in `_syncRead`.
718719 return await this . _syncRead ( id ) ;
719720 throw error ;
720721 }
@@ -732,6 +733,16 @@ export class LevelLocalRepo implements LocalRepo {
732733
733734 private async _syncMerge ( req : LocalRepoSyncRequest ) : Promise < LocalRepoSyncResponse > {
734735 const { id, patches} = req ;
736+ let lastKnownTime : number = 0 ;
737+ const reqTime = req . time ;
738+ if ( typeof reqTime === 'number' ) {
739+ lastKnownTime = reqTime ;
740+ const firstPatch = patches ?. [ 0 ] ;
741+ if ( firstPatch ?. getId ( ) ?. sid === SESSION . GLOBAL ) lastKnownTime = firstPatch . getId ( ) ! . time + firstPatch . span ( ) - 1 ;
742+ } else if ( patches ?. length ) {
743+ const firstPatchTime = patches ?. [ 0 ] ?. getId ( ) ?. time ;
744+ if ( typeof firstPatchTime === 'number' ) lastKnownTime = firstPatchTime - 1 ;
745+ }
735746 const keyBase = await this . blockKeyBase ( id ) ;
736747 if ( ! patches || ! patches . length ) throw new Error ( 'EMPTY_BATCH' ) ;
737748 const writtenPatches : Uint8Array [ ] = [ ] ;
@@ -740,10 +751,12 @@ export class LevelLocalRepo implements LocalRepo {
740751 // TODO: Return correct response.
741752 // TODO: Check that remote state is in sync, too.
742753 let needsReset = false ;
754+ let cursorBehind = false ;
743755 const didPush = await this . lockBlock ( keyBase , async ( ) => {
744756 const [ tip , meta ] = await Promise . all ( [ this . readFrontierTip ( keyBase ) , this . readMeta ( keyBase ) ] ) ;
745- if ( meta . seq > - 1 && ( typeof req . cursor !== 'number' || req . cursor < meta . seq ) ) needsReset = true ;
757+ if ( meta . seq > - 1 && ( typeof req . cursor !== 'number' || req . cursor < meta . seq ) ) cursorBehind = true ;
746758 let nextTick = meta . time + 1 ;
759+ if ( lastKnownTime < meta . time ) needsReset = true ;
747760 cursor = meta . seq ;
748761 if ( tip ) {
749762 const tipTime = tip . getId ( ) ?. time ?? 0 ;
@@ -775,18 +788,18 @@ export class LevelLocalRepo implements LocalRepo {
775788 const op : BinStrLevelOperation = { type : 'put' , key : patchKey , value : uint8 } ;
776789 ops . push ( op ) ;
777790 }
791+ if ( writtenPatches . length ) {
792+ this . pubsub . pub ( { type : 'rebase' , id, patches : writtenPatches , session : req . session } ) ;
793+ }
778794 if ( ops . length ) {
779795 await this . kv . batch ( ops ) ;
780796 return true ;
781797 }
782798 return false ;
783799 } ) ;
784- if ( writtenPatches . length ) {
785- this . pubsub . pub ( { type : 'rebase' , id, patches : writtenPatches , session : req . session } ) ;
786- }
787800 if ( ! didPush && ! needsReset ) {
788801 const merge = await this . readFrontier0 ( keyBase ) ;
789- return { cursor, merge} ;
802+ return { cursor, merge, cursorBehind } ;
790803 }
791804 const remote = this . markDirtyAndSync ( keyBase , id )
792805 . then ( ( ) => { } )
@@ -796,9 +809,9 @@ export class LevelLocalRepo implements LocalRepo {
796809 } ) ;
797810 if ( needsReset ) {
798811 const { cursor, model} = await this . _syncRead0 ( keyBase ) ;
799- return { cursor, model, remote} ;
812+ return { cursor, model, remote, cursorBehind } ;
800813 }
801- return { cursor, remote} ;
814+ return { cursor, remote, cursorBehind } ;
802815 }
803816
804817 protected async readLocal0 ( keyBase : string ) : Promise < [ model : Model , cursor : LevelLocalRepoCursor ] > {
0 commit comments