@@ -6,13 +6,15 @@ import { Endpoint } from '../network/NetworkAgent';
66import { PeerGroupAgent } from '../peer/PeerGroupAgent' ;
77import { PeeringAgentBase } from '../peer/PeeringAgentBase' ;
88import { HeaderBasedState } from './history/HeaderBasedState' ;
9- import { AgentStateUpdateEvent , GossipEventTypes } from './StateGossipAgent' ;
9+ import { AgentStateUpdateEvent , GossipEventTypes , StateGossipAgent } from './StateGossipAgent' ;
1010import { StateSyncAgent } from './StateSyncAgent' ;
1111
1212import { HistorySynchronizer } from './history/HistorySynchronizer' ;
1313import { HistoryProvider , MessageType , SyncMsg } from './history/HistoryProvider' ;
1414import { OpHeader , OpHeaderLiteral } from 'data/history/OpHeader' ;
1515import { Resources } from 'spaces/Resources' ;
16+ import { EventRelay } from 'util/events' ;
17+ import { SyncObserverEventTypes , SyncState , SyncStateUpdateEvent } from './SyncObserverAgent' ;
1618
1719/*
1820 * Important notice: The constructor of the HeaderBasedSyncAgent can receive either an instance or just the
@@ -36,7 +38,7 @@ class HeaderBasedSyncAgent extends PeeringAgentBase implements StateSyncAgent {
3638
3739 static MaxRequestsPerRemote = 2 ;
3840
39- mutableObj ? : MutableObject ;
41+ mutableObj : MutableObject ;
4042 mutableObjHash : Hash ;
4143 acceptedMutationOpClasses : string [ ] ;
4244 stateOpFilter ?: StateFilter ;
@@ -55,20 +57,19 @@ class HeaderBasedSyncAgent extends PeeringAgentBase implements StateSyncAgent {
5557 synchronizer : HistorySynchronizer ;
5658 provider : HistoryProvider ;
5759
60+ syncEventSource ?: EventRelay < HashedObject > ;
61+
5862 terminated = false ;
5963
6064 controlLog : Logger ;
6165 messageLog : Logger ;
6266
63- constructor ( peerGroupAgent : PeerGroupAgent , mutableObjOrHash : MutableObject | Hash , resources : Resources , acceptedMutationOpClasses : string [ ] , stateOpFilter ?: StateFilter ) {
67+ constructor ( peerGroupAgent : PeerGroupAgent , mutableObj : MutableObject , resources : Resources , acceptedMutationOpClasses : string [ ] , stateOpFilter ?: StateFilter ) {
6468 super ( peerGroupAgent ) ;
6569
66- if ( mutableObjOrHash instanceof MutableObject ) {
67- this . mutableObj = mutableObjOrHash ;
68- this . mutableObjHash = mutableObjOrHash . hash ( ) ;
69- } else {
70- this . mutableObjHash = mutableObjOrHash ;
71- }
70+ this . mutableObj = mutableObj ;
71+ this . mutableObjHash = mutableObj . hash ( ) ;
72+
7273 this . acceptedMutationOpClasses = acceptedMutationOpClasses ;
7374 this . stateOpFilter = stateOpFilter ;
7475
@@ -86,16 +87,14 @@ class HeaderBasedSyncAgent extends PeeringAgentBase implements StateSyncAgent {
8687 this . messageLog = HeaderBasedSyncAgent . messageLog ;
8788 }
8889
89-
90-
91-
9290 getAgentId ( ) : string {
9391 return HeaderBasedSyncAgent . syncAgentIdFor ( this . mutableObjHash , this . peerGroupAgent . peerGroupId ) ;
9492 }
9593
9694 ready ( pod : AgentPod ) : void {
9795
9896 this . pod = pod ;
97+
9998 this . updateStateFromStore ( ) . then ( async ( ) => {
10099 if ( this . stateOpHeadersByOpHash !== undefined ) {
101100 for ( const opHistory of this . stateOpHeadersByOpHash . values ( ) ) {
@@ -112,6 +111,14 @@ class HeaderBasedSyncAgent extends PeeringAgentBase implements StateSyncAgent {
112111
113112 shutdown ( ) : void {
114113
114+ const ev : SyncStateUpdateEvent = {
115+ emitter : this . mutableObj ,
116+ action : SyncObserverEventTypes . SyncStateUpdate ,
117+ data : { inSync : false , synchronizing : false , opsToFetch : 0 , remoteStateHashes : { } }
118+ } ;
119+
120+ this . syncEventSource ?. emit ( ev ) ;
121+
115122 this . terminated = true ;
116123 this . synchronizer . shutdown ( ) ;
117124
@@ -206,6 +213,16 @@ class HeaderBasedSyncAgent extends PeeringAgentBase implements StateSyncAgent {
206213 await this . synchronizer . onNewLocalOp ( op ) ;
207214 await this . updateStateFromStore ( ) ;
208215 }
216+
217+ if ( this . syncEventSource !== undefined ) {
218+ const ev : SyncStateUpdateEvent = {
219+ emitter : this . mutableObj ,
220+ action : SyncObserverEventTypes . SyncStateUpdate ,
221+ data : this . getSyncState ( )
222+ } ;
223+
224+ this . syncEventSource . emit ( ev ) ;
225+ }
209226 } ;
210227
211228 literalIsValidOp ( literal ?: Literal , log = false ) : boolean {
@@ -324,6 +341,46 @@ class HeaderBasedSyncAgent extends PeeringAgentBase implements StateSyncAgent {
324341 return this . synchronizer . expectingMoreOps ( receivedOpHashes ) ;
325342 }
326343
344+ getSyncEventSource ( ) : EventRelay < HashedObject > {
345+
346+ if ( this . syncEventSource === undefined ) {
347+ this . syncEventSource = this . createSyncEventSource ( ) ;
348+ }
349+
350+ return this . syncEventSource ;
351+ }
352+
353+ createSyncEventSource ( ) : EventRelay < HashedObject > {
354+ return new EventRelay ( this . mutableObj as HashedObject , new Map ( ) ) ;
355+ }
356+
357+ getSyncState ( ) : SyncState {
358+
359+ const gossipAgent = this . pod ?. getAgent ( StateGossipAgent . agentIdForGossipId ( this . getAgentId ( ) ) ) as StateGossipAgent ;
360+
361+ const remoteStateHashes = gossipAgent . getAllRemoteStateForAgent ( this . getAgentId ( ) ) ;
362+ const localStateHash = gossipAgent . getLocalStateForAgent ( this . getAgentId ( ) ) ;
363+
364+ let inSync = true ;
365+ for ( const remoteHash of Object . values ( remoteStateHashes ) ) {
366+ if ( remoteHash !== localStateHash ) {
367+ inSync = false ;
368+ break ;
369+ }
370+ }
371+
372+ const opsToFetch = this . synchronizer . discoveredHistory . contents . size ;
373+
374+ return { remoteStateHashes : remoteStateHashes , localStateHash : localStateHash , inSync : inSync , opsToFetch : opsToFetch , synchronizing : true }
375+ }
376+
377+ getMutableObject ( ) : MutableObject {
378+ return this . mutableObj ;
379+ }
380+
381+ getPeerGroupId ( ) : string {
382+ return this . peerGroupAgent . peerGroupId ;
383+ }
327384}
328385
329386export { SyncMsg as HistoryMsg , HeaderBasedSyncAgent , StateFilter }
0 commit comments