@@ -31,29 +31,24 @@ public static async IAsyncEnumerable<TCommit> GetMissingCommits<TCommit, TChange
3131 if ( includeChangeEntities ) commits = commits . Include ( c => c . ChangeEntities ) ;
3232 foreach ( var ( clientId , localTimestamp ) in localState . ClientHeads )
3333 {
34- //client is new to the other history
35- if ( ! remoteState . ClientHeads . TryGetValue ( clientId , out var otherTimestamp ) )
34+ long ? remoteTimestamp = remoteState . ClientHeads . TryGetValue ( clientId , out var otherTimestamp )
35+ ? otherTimestamp
36+ : null ;
37+ var clientCommits = commits . Where ( c => c . ClientId == clientId ) ;
38+ if ( remoteTimestamp is null )
3639 {
37- //todo slow, it would be better if we could query on client id and get latest changes per client
38- await foreach ( var commit in commits
39- . DefaultOrder ( )
40- . Where ( c => c . ClientId == clientId )
41- . AsAsyncEnumerable ( ) )
42- {
40+ await foreach ( var commit in clientCommits . DefaultOrder ( ) . AsAsyncEnumerable ( ) )
4341 yield return commit ;
44- }
4542 }
46- //client has newer history than the other history
47- else if ( localTimestamp > otherTimestamp )
43+ else if ( localTimestamp > remoteTimestamp )
4844 {
49- var otherDt = DateTimeOffset . FromUnixTimeMilliseconds ( otherTimestamp ) ;
50- //todo even slower because we need to filter out changes that are already in the other history
51- await foreach ( var commit in commits
45+ var otherDt = DateTimeOffset . FromUnixTimeMilliseconds ( remoteTimestamp . Value ) ;
46+ await foreach ( var commit in clientCommits
47+ . Where ( c => c . HybridDateTime . DateTime > otherDt )
5248 . DefaultOrder ( )
53- . Where ( c => c . ClientId == clientId && c . HybridDateTime . DateTime > otherDt )
5449 . AsAsyncEnumerable ( ) )
5550 {
56- if ( commit . DateTime . ToUnixTimeMilliseconds ( ) > otherTimestamp )
51+ if ( commit . DateTime . ToUnixTimeMilliseconds ( ) > remoteTimestamp )
5752 yield return commit ;
5853 }
5954 }
@@ -75,6 +70,47 @@ public static async Task<SortedSet<T>> ToSortedSetAsync<T>(this IQueryable<T> qu
7570 return set ;
7671 }
7772
73+ public static IEnumerable < TCommit > GetMissingCommits < TCommit , TChange > (
74+ this IEnumerable < TCommit > commits ,
75+ SyncState localState ,
76+ SyncState remoteState ) where TCommit : CommitBase < TChange >
77+ {
78+ foreach ( var ( clientId , localTimestamp ) in localState . ClientHeads )
79+ {
80+ long ? remoteTimestamp = remoteState . ClientHeads . TryGetValue ( clientId , out var otherTimestamp )
81+ ? otherTimestamp
82+ : null ;
83+ foreach ( var commit in GetMissingCommitsForClient (
84+ commits . Where ( c => c . ClientId == clientId ) , localTimestamp , remoteTimestamp ) )
85+ {
86+ yield return commit ;
87+ }
88+ }
89+ }
90+
91+ private static IEnumerable < TCommit > GetMissingCommitsForClient < TCommit > (
92+ IEnumerable < TCommit > clientCommits ,
93+ long localTimestamp ,
94+ long ? remoteTimestamp ) where TCommit : CommitBase
95+ {
96+ if ( remoteTimestamp is null )
97+ {
98+ foreach ( var commit in clientCommits . DefaultOrder ( ) )
99+ yield return commit ;
100+ }
101+ else if ( localTimestamp > remoteTimestamp )
102+ {
103+ var otherDt = DateTimeOffset . FromUnixTimeMilliseconds ( remoteTimestamp . Value ) ;
104+ foreach ( var commit in clientCommits
105+ . Where ( c => c . HybridDateTime . DateTime > otherDt )
106+ . DefaultOrder ( ) )
107+ {
108+ if ( commit . DateTime . ToUnixTimeMilliseconds ( ) > remoteTimestamp )
109+ yield return commit ;
110+ }
111+ }
112+ }
113+
78114 public static IQueryable < T > DefaultOrder < T > ( this IQueryable < T > queryable ) where T : CommitBase
79115 {
80116 return queryable
0 commit comments