2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// @flow
  
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  type  { LoginFacade }  from  "./facades/LoginFacade"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  type  { MailFacade }  from  "./facades/MailFacade"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  type  { WorkerImpl }  from  "./WorkerImpl"  
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { decryptAndMapToInstance }  from  "./crypto/CryptoFacade"  
						 
					
						
							
								
									
										
										
										
											2019-03-14 11:55:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { assertWorkerOrNode ,  getWebsocketOrigin ,  isAdminClient ,  isTest ,  Mode }  from  "../Env"  
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  { _TypeModel  as  MailTypeModel }  from  "../entities/tutanota/Mail"  
						 
					
						
							
								
									
										
										
										
											2018-07-31 17:07:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { load ,  loadAll ,  loadRange }  from  "./EntityWorker"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  { firstBiggerThanSecond ,  GENERATED _MAX _ID ,  GENERATED _MIN _ID ,  getLetId }  from  "../common/EntityFunctions"  
						 
					
						
							
								
									
										
										
										
											2019-09-17 12:17:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { ConnectionError ,  handleRestError ,  NotAuthorizedError ,  NotFoundError ,  ServiceUnavailableError }  from  "../common/error/RestError"  
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  { EntityEventBatchTypeRef }  from  "../entities/sys/EntityEventBatch"  
						 
					
						
							
								
									
										
										
										
											2019-02-12 16:26:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { downcast ,  identity ,  neverNull ,  randomIntFromInterval }  from  "../common/utils/Utils"  
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  { OutOfSyncError }  from  "../common/error/OutOfSyncError"  
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { contains }  from  "../common/utils/ArrayUtils"  
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  type  { Indexer }  from  "./search/Indexer"  
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  type  { CloseEventBusOptionEnum }  from  "../common/TutanotaConstants"  
						 
					
						
							
								
									
										
										
										
											2018-12-11 09:41:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { CloseEventBusOption ,  GroupType }  from  "../common/TutanotaConstants"  
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { _TypeModel  as  WebsocketEntityDataTypeModel }  from  "../entities/sys/WebsocketEntityData"  
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { CancelledError }  from  "../common/error/CancelledError"  
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								assertWorkerOrNode ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-05 17:26:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  EventBusState  =  Object . freeze ( {  
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									Automatic :  "automatic" ,  // automatic reconnection is enabled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Suspended :  "suspended" ,  // automatic reconnection is suspended but can be enabled again
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Terminated :  "terminated"  // automatic reconnection is disabled and websocket is closed but can be opened again by calling connect explicit
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-05 17:26:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} )  
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  EventBusStateEnum  =  $Values < typeof  EventBusState > ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  RETRY _AFTER _SERVICE _UNAVAILABLE _ERROR _MS  =  30000  
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								export  class  EventBusClient  {  
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_MAX _EVENT _IDS _QUEUE _LENGTH :  number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_indexer :  Indexer ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-26 16:14:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_cache :  EntityRestInterface ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_worker :  WorkerImpl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_mail :  MailFacade ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_login :  LoginFacade ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_state :  EventBusStateEnum ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									_socket :  ? WebSocket ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_immediateReconnect :  boolean ;  // if true tries to reconnect immediately after the websocket is closed
 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_lastEntityEventIds :  { [ key :  Id ] :  Id [ ] } ;  // maps group id to last event ids (max. 1000). we do not have to update these event ids if the groups of the user change because we always take the current users groups from the LoginFacade.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									_queueWebsocketEvents :  boolean 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_websocketWrapperQueue :  WebsocketEntityData [ ] ;  // in this array all arriving WebsocketWrappers are stored as long as we are loading or processing EntityEventBatches
 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_reconnectTimer :  ? TimeoutID ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_connectTimer :  ? TimeoutID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/ * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Represents  a  currently  retried  executing  due  to  a  ServiceUnavailableError 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_serviceUnavailableRetry :  ? Promise < void > ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-26 16:14:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									constructor ( worker :  WorkerImpl ,  indexer :  Indexer ,  cache :  EntityRestInterface ,  mail :  MailFacade ,  login :  LoginFacade )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _worker  =  worker 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _indexer  =  indexer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _cache  =  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _mail  =  mail 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _login  =  login 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										this . _socket  =  null 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _state  =  EventBusState . Automatic 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _reconnectTimer  =  null 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _connectTimer  =  null 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _reset ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// we store the last 1000 event ids per group, so we know if an event was already processed.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// it is not sufficient to check the last event id because a smaller event id may arrive later
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// than a bigger one if the requests are processed in parallel on the server
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _MAX _EVENT _IDS _QUEUE _LENGTH  =  1000 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_reset ( ) :  void  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _immediateReconnect  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _lastEntityEventIds  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _queueWebsocketEvents  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _websocketWrapperQueue  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _serviceUnavailableRetry  =  null 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/ * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Opens  a  WebSocket  connection  to  receive  server  events . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  @ param  reconnect  Set  to  true  if  the  connection  has  been  opened  before . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  @ returns  The  event  bus  client  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									connect ( reconnect :  boolean )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( env . mode  ===  Mode . Test )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-19 18:13:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										console . log ( "ws connect reconnect=" ,  reconnect ,  "state:" ,  this . _state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-14 13:15:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _websocketWrapperQueue  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// make sure a retry will be cancelled by setting _serviceUnavailableRetry to null
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _serviceUnavailableRetry  =  null 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 13:56:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _worker . updateWebSocketState ( "connecting" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _state  =  EventBusState . Automatic 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _connectTimer  =  null 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-31 17:07:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										const  authHeaders  =  this . _login . createAuthHeaders ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Native query building is not supported in old browser, mithril is not available in the worker
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  authQuery  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"modelVersions="  +  WebsocketEntityDataTypeModel . version  +  "."  +  MailTypeModel . version 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											+  "&clientVersion="  +  env . versionNumber 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											+  "&userId="  +  this . _login . getLoggedInUser ( ) . _id 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-25 11:07:32 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											+  "&"  +  ( "accessToken="  +  authHeaders . accessToken ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										let  url  =  getWebsocketOrigin ( )  +  "/event?"  +  authQuery ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 13:56:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _unsubscribeFromOldWebsocket ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										this . _socket  =  new  WebSocket ( url ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _socket . onopen  =  ( )  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											console . log ( "ws open: " ,  new  Date ( ) ,  "state:" ,  this . _state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _initEntityEvents ( reconnect ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 09:27:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _worker . updateWebSocketState ( "connected" ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _socket . onclose  =  ( event :  CloseEvent )  =>  this . _close ( event ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _socket . onerror  =  ( error :  any )  =>  this . _error ( error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _socket . onmessage  =  ( message :  MessageEvent )  =>  this . _message ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_initEntityEvents ( reconnect :  boolean )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this . _queueWebsocketEvents  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										let  p  =  ( ( reconnect  &&  Object . keys ( this . _lastEntityEventIds ) . length  >  0 )  ?  this . _loadMissedEntityEvents ( )  :  this . _setLatestEntityEventIds ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _queueWebsocketEvents  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . catch ( ConnectionError ,  e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											console . log ( "not connected in connect(), close websocket" ,  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . close ( CloseEventBusOption . Reconnect ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . catch ( CancelledError ,  e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// the processing was aborted due to a reconnect. do not reset any attributes because they might already be in use since reconnection
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											console . log ( "cancelled retry process entity events after reconnect" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . catch ( ServiceUnavailableError ,  e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// a ServiceUnavailableError is a temporary error and we have to retry to avoid data inconsistencies
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _lastEntityEventIds  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											console . log ( "retry init entity events in 30s" ,  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											let  promise  =  Promise . delay ( RETRY _AFTER _SERVICE _UNAVAILABLE _ERROR _MS ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// if we have a websocket reconnect we have to stop retrying
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( this . _serviceUnavailableRetry  ===  promise )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													console . log ( "retry initializing entity events" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  this . _initEntityEvents ( reconnect ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													console . log ( "cancel initializing entity events" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _serviceUnavailableRetry  =  promise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  promise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . catch ( e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _queueWebsocketEvents  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _worker . sendError ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/ * * 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-28 11:32:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  Sends  a  close  event  to  the  server  and  finally  closes  the  connection . 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  The  state  of  this  event  bus  client  is  reset  and  the  client  is  terminated  ( does  not  automatically  reconnect )  except  reconnect  ==  true 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									 * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									close ( closeOption :  CloseEventBusOptionEnum )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										console . log ( "ws close: " ,  new  Date ( ) ,  "closeOption: " ,  closeOption ,  "state:" ,  this . _state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										switch  ( closeOption )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  CloseEventBusOption . Terminate : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this . _terminate ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  CloseEventBusOption . Pause : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this . _state  =  EventBusState . Suspended 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this . _worker . updateWebSocketState ( "connecting" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  CloseEventBusOption . Reconnect : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this . _worker . updateWebSocketState ( "connecting" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  ( this . _socket  &&  this . _socket . close )  {  // close is undefined in node tests
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _socket . close ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 13:56:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_unsubscribeFromOldWebsocket ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this . _socket )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Remove listeners. We don't want old socket to mess our state
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _socket . onopen  =  this . _socket . onclose  =  this . _socket . onerror  =  this . _socket . onmessage  =  identity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_terminate ( ) :  void  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _state  =  EventBusState . Terminated 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _reset ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this . _worker . updateWebSocketState ( "terminated" ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									_error ( error :  any )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										console . log ( "ws error: " ,  error ,  "state:" ,  this . _state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_message ( message :  MessageEvent ) :  Promise < void >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-14 11:55:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										//console.log("ws message: ", message.data);
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										const  [ type ,  value ]  =  downcast ( message . data ) . split ( ";" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( type  ===  "entityUpdate" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  decryptAndMapToInstance ( WebsocketEntityDataTypeModel ,  JSON . parse ( value ) ,  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												. then ( data  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													// When an event batch is received only process it if there is no other event batch currently processed. Otherwise put it into the cache. After processing an event batch we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													// start processing the next one from the cache. This makes sure that all events are processed in the order they are received and we do not get an inconsistent state
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  ( this . _queueWebsocketEvents )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														this . _websocketWrapperQueue . push ( data ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														this . _queueWebsocketEvents  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														return  this . _processEntityEvents ( data . eventBatch ,  data . eventBatchOwner ,  data . eventBatchId ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															if  ( this . _websocketWrapperQueue . length  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																return  this . _processQueuedEvents ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															} 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														} ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															this . _queueWebsocketEvents  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														} ) . catch ( ConnectionError ,  e  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
															this . _queueWebsocketEvents  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
															console . log ( "not connected in _message(), close websocket" ,  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															this . close ( CloseEventBusOption . Reconnect ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														} ) . catch ( CancelledError ,  e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															// the processing was aborted due to a reconnect. do not reset any attributes because they might already be in use since reconnection
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															console . log ( "cancelled retry process entity events after _message call" ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														} ) . catch ( e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															this . _queueWebsocketEvents  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
															this . _worker . sendError ( e ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														} ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-21 10:48:07 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( type  ===  "unreadCounterUpdate" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _worker . updateCounter ( JSON . parse ( value ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 15:42:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  Promise . resolve ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_close ( event :  CloseEvent )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										console . log ( "ws _close: " ,  event ,  new  Date ( ) ,  "state:" ,  this . _state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-21 10:35:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Avoid running into penalties when trying to authenticate with an invalid session
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// NotAuthenticatedException 401, AccessDeactivatedException 470, AccessBlocked 472
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// do not catch session expired here because websocket will be reused when we authenticate again
 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 14:25:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( event . code  ===  4401  ||  event . code  ===  4470  ||  event . code  ===  4472 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 16:48:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _terminate ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _worker . sendError ( handleRestError ( event . code  -  4000 ,  "web socket error" ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-07 14:12:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( event . code  ===  4440 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// session is expired. do not try to reconnect until the user creates a new session
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _state  =  EventBusState . Suspended 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _worker . updateWebSocketState ( "connecting" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( this . _state  ===  EventBusState . Automatic  &&  this . _login . isLoggedIn ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _worker . updateWebSocketState ( "connecting" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-14 11:55:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( this . _immediateReconnect )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												this . _immediateReconnect  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												this . tryReconnect ( false ,  false ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this . tryReconnect ( false ,  false ,  1000  *  randomIntFromInterval ( 30 ,  120 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tryReconnect ( closeIfOpen :  boolean ,  enableAutomaticState :  boolean ,  delay :  ? number  =  null )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this . _reconnectTimer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// prevent reconnect race-condition
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											clearTimeout ( this . _reconnectTimer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _reconnectTimer  =  null 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! delay )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _reconnect ( closeIfOpen ,  enableAutomaticState ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _reconnectTimer  =  setTimeout ( ( )  =>  this . _reconnect ( false ,  false ) ,  delay ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/ * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Tries  to  reconnect  the  websocket  if  it  is  not  connected . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * / 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_reconnect ( closeIfOpen :  boolean ,  enableAutomaticState :  boolean )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										console . log ( "ws _reconnect socket state (CONNECTING=0, OPEN=1, CLOSING=2, CLOSED=3): " 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-14 11:55:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											+  ( ( this . _socket )  ?  this . _socket . readyState  :  "null" ) ,  "state:" ,  this . _state , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"closeIfOpen" ,  closeIfOpen ,  "enableAutomaticState" ,  enableAutomaticState ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( this . _state  !==  EventBusState . Terminated  &&  enableAutomaticState )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _state  =  EventBusState . Automatic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 14:25:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( closeIfOpen  &&  this . _socket  &&  this . _socket . readyState  ===  WebSocket . OPEN )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											this . _immediateReconnect  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											neverNull ( this . _socket ) . close ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( this . _socket  ==  null  ||  this . _socket . readyState  ===  WebSocket . CLOSED 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-03 14:10:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												||  this . _socket . readyState  ===  WebSocket . CLOSING ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											&&  this . _state  !==  EventBusState . Terminated 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 17:37:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											&&  this . _login . isLoggedIn ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-13 14:53:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// Don't try to connect right away because connection may not be actually there
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// see #1165
 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-08 17:07:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( this . _connectTimer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												clearTimeout ( this . _connectTimer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _connectTimer  =  setTimeout ( ( )  =>  this . connect ( true ) ,  100 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/ * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  stores  the  latest  event  batch  ids  for  each  of  the  users  groups  or  min  id  if  there  is  no  event  batch  yet . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  this  is  needed  to  know  from  where  to  start  loading  missed  events  after  a  reconnect 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_setLatestEntityEventIds ( ) :  Promise < void >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// set all last event ids in one step to avoid that we have just set them for a few groups when a ServiceUnavailableError occurs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										let  lastIds :  { [ key :  Id ] :  Id [ ] }  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-11 09:41:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  Promise . each ( this . _eventGroups ( ) ,  groupId  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  loadRange ( EntityEventBatchTypeRef ,  groupId ,  GENERATED _MAX _ID ,  1 ,  true ) . then ( batches  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												lastIds [ groupId ]  =  [ 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 17:37:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													( batches . length  ===  1 )  ?  getLetId ( batches [ 0 ] ) [ 1 ]  :  GENERATED _MIN _ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												] 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this . _lastEntityEventIds  =  lastIds 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  this . _processQueuedEvents ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_loadMissedEntityEvents ( ) :  Promise < void >  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( this . _login . isLoggedIn ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  this . _checkIfEntityEventsAreExpired ( ) . then ( expired  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( expired )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-23 13:30:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													return  this . _worker . sendError ( new  OutOfSyncError ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-11 09:41:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													return  Promise . each ( this . _eventGroups ( ) ,  groupId  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 17:37:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														return  loadAll ( EntityEventBatchTypeRef ,  groupId ,  this . _getLastEventBatchIdOrMinIdForGroup ( groupId ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															. each ( eventBatch  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																return  this . _processEntityEvents ( eventBatch . events ,  groupId ,  getLetId ( eventBatch ) [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															} ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-17 12:17:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
															. catch ( NotAuthorizedError ,  ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																console . log ( "could not download entity updates => lost permission" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															} ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													} ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														return  this . _processQueuedEvents ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  Promise . resolve ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_processQueuedEvents ( ) :  Promise < void >  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 14:25:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( this . _websocketWrapperQueue . length  ===  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  Promise . resolve ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											let  wrapper  =  this . _websocketWrapperQueue . shift ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// check if we have already processed this queued event when loading the EntityEventBatch
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											let  groupId  =  neverNull ( wrapper . eventBatchOwner ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											let  eventId  =  neverNull ( wrapper . eventBatchId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											let  p  =  Promise . resolve ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! this . _isAlreadyProcessed ( groupId ,  eventId ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												p  =  this . _processEntityEvents ( wrapper . eventBatch ,  groupId ,  eventId ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  p . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  this . _processQueuedEvents ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_processEntityEvents ( events :  EntityUpdate [ ] ,  groupId :  Id ,  batchId :  Id ) :  Promise < void >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 15:06:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  this . _executeIfNotTerminated ( ( )  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-26 16:14:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  this . _cache . entityEventsReceived ( events ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											           . then ( filteredEvents  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           return  this . _executeIfNotTerminated ( ( )  =>  this . _login . entityEventsReceived ( filteredEvents ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												                      . then ( ( )  =>  this . _executeIfNotTerminated ( ( )  =>  this . _mail . entityEventsReceived ( filteredEvents ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-20 18:31:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												                      . then ( ( )  =>  this . _executeIfNotTerminated ( ( )  =>  this . _worker . entityEventsReceived ( filteredEvents ,  groupId ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-26 16:14:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												                      . return ( filteredEvents ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											           } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											           . then ( filteredEvents  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           if  ( ! this . _lastEntityEventIds [ groupId ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           this . _lastEntityEventIds [ groupId ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           this . _lastEntityEventIds [ groupId ] . push ( batchId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           // make sure the batch ids are in ascending order, so we use the highest id when downloading all missed events after a reconnect
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           this . _lastEntityEventIds [ groupId ] . sort ( ( e1 ,  e2 )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           if  ( e1  ===  e2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														           return  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														           return  firstBiggerThanSecond ( e1 ,  e2 )  ?  1  :  - 1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           if  ( this . _lastEntityEventIds [ groupId ] . length  >  this . _MAX _EVENT _IDS _QUEUE _LENGTH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           this . _lastEntityEventIds [ groupId ] . shift ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           } 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 15:06:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-26 16:14:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												           // Call the indexer in this last step because now the processed event is stored and the indexer has a separate event queue that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           // shall not receive the event twice.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           if  ( ! isTest ( )  &&  ! isAdminClient ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           this . _executeIfNotTerminated ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														           this . _indexer . addBatchesToQueue ( [ { groupId ,  batchId ,  events :  filteredEvents } ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														           console . log ( "_indexer.startProcessing from EventBusClient" ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-26 16:14:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														           this . _indexer . startProcessing ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													           } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												           } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											           } ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 15:49:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ) . catch ( ServiceUnavailableError ,  e  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// a ServiceUnavailableError is a temporary error and we have to retry to avoid data inconsistencies
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											console . log ( "retry processing event in 30s" ,  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											let  promise  =  Promise . delay ( RETRY _AFTER _SERVICE _UNAVAILABLE _ERROR _MS ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// if we have a websocket reconnect we have to stop retrying
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( this . _serviceUnavailableRetry  ===  promise )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  this . _processEntityEvents ( events ,  groupId ,  batchId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													throw  new  CancelledError ( "stop retry processing after service unavailable due to reconnect" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _serviceUnavailableRetry  =  promise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  promise 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 15:06:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/ * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Tries  to  load  the  last  EntityEventBatch  if  we  had  loaded  it  before .  If  the  batch  can  be  loaded  all  later  event  batches  are  available .  If  it  can  not  be  loaded  we  assume  that  at  least  some  later  events  are  also  expired . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  @ return  True  if  the  events  have  expired ,  false  otherwise . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_checkIfEntityEventsAreExpired ( ) :  Promise < boolean >  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-11 09:41:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  Promise . each ( this . _eventGroups ( ) ,  groupId  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											let  lastEventBatchId  =  this . _getLastEventBatchIdOrMinIdForGroup ( groupId ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 14:25:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( lastEventBatchId  !==  GENERATED _MIN _ID )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-17 12:17:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return  load ( EntityEventBatchTypeRef ,  [ groupId ,  lastEventBatchId ] ) . catch ( NotAuthorizedError ,  ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													console . log ( "could not download entity updates => lost permission" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . then ( ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . catch ( NotFoundError ,  ( )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_getLastEventBatchIdOrMinIdForGroup ( groupId :  Id ) :  Id  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 11:07:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// TODO handle lost updates (old event surpassed by newer one, we store the new id and retrieve instances from the newer one on next login
 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 17:37:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  ( this . _lastEntityEventIds [ groupId ]  &&  this . _lastEntityEventIds [ groupId ] . length  >  0 )  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this . _lastEntityEventIds [ groupId ] [ this . _lastEntityEventIds [ groupId ] . length  -  1 ]  :  GENERATED _MIN _ID 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_isAlreadyProcessed ( groupId :  Id ,  eventId :  Id ) :  boolean  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this . _lastEntityEventIds [ groupId ]  &&  this . _lastEntityEventIds [ groupId ] . length  >  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 17:37:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  firstBiggerThanSecond ( this . _lastEntityEventIds [ groupId ] [ 0 ] ,  eventId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												||  contains ( this . _lastEntityEventIds [ groupId ] ,  eventId ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-19 14:54:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_executeIfNotTerminated ( call :  Function ) :  Promise < void >  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 13:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( this . _state  !==  EventBusState . Terminated )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  call ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  Promise . resolve ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-11 09:41:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_eventGroups ( ) :  Id [ ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  this . _login . getLoggedInUser ( ) . memberships 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										           . filter ( membership  =>  membership . groupType  !==  GroupType . MailingList ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										           . map ( membership  =>  membership . group ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-04 17:04:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										           . concat ( this . _login . getLoggedInUser ( ) . userGroup . group ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-11 09:41:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 13:54:22 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}