tutanota/src/api/main/EventController.ts

66 lines
2.3 KiB
TypeScript
Raw Normal View History

import { downcast, identity, noOp } from "@tutao/tutanota-utils"
2022-12-27 15:37:40 +01:00
import type { LoginController } from "./LoginController"
import stream from "mithril/stream"
import Stream from "mithril/stream"
2022-12-27 15:37:40 +01:00
import { assertMainOrNode } from "../common/Env"
import { EntityUpdate, WebsocketCounterData } from "../entities/sys/TypeRefs"
import { EntityUpdateData } from "../common/utils/EntityUpdateUtils.js"
2017-08-15 13:54:22 +02:00
assertMainOrNode()
2023-01-02 17:39:05 +01:00
export type ExposedEventController = Pick<EventController, "onEntityUpdateReceived" | "onCountersUpdateReceived">
2022-12-28 15:28:28 +01:00
const TAG = "[EventController]"
export type EntityEventsListener = (updates: ReadonlyArray<EntityUpdateData>, eventOwnerGroupId: Id) => Promise<any>
2019-01-21 10:48:07 +01:00
export class EventController {
private countersStream: Stream<WebsocketCounterData> = stream()
private entityListeners: Set<EntityEventsListener> = new Set()
2017-08-15 13:54:22 +02:00
2022-12-27 15:37:40 +01:00
constructor(private readonly logins: LoginController) {}
2017-08-15 13:54:22 +02:00
addEntityListener(listener: EntityEventsListener) {
if (this.entityListeners.has(listener)) {
console.warn(TAG, "Adding the same listener twice!")
} else {
this.entityListeners.add(listener)
}
}
2019-01-21 10:48:07 +01:00
removeEntityListener(listener: EntityEventsListener) {
const wasRemoved = this.entityListeners.delete(listener)
2023-02-22 17:31:36 +01:00
if (!wasRemoved) {
console.warn(TAG, "Could not remove listener, possible leak?", listener)
2023-02-22 17:31:36 +01:00
}
}
2017-08-15 13:54:22 +02:00
getCountersStream(): Stream<WebsocketCounterData> {
// Create copy so it's never ended
return this.countersStream.map(identity)
}
2017-08-15 13:54:22 +02:00
2022-12-28 15:28:28 +01:00
async onEntityUpdateReceived(entityUpdates: ReadonlyArray<EntityUpdate>, eventOwnerGroupId: Id): Promise<void> {
let loginsUpdates = Promise.resolve()
2018-10-19 18:13:58 +02:00
if (this.logins.isUserLoggedIn()) {
// the UserController must be notified first as other event receivers depend on it to be up-to-date
loginsUpdates = this.logins.getUserController().entityEventsReceived(entityUpdates as ReadonlyArray<EntityUpdateData>, eventOwnerGroupId)
}
2019-01-21 10:48:07 +01:00
return loginsUpdates
.then(async () => {
// sequentially to prevent parallel loading of instances
for (const listener of this.entityListeners) {
let entityUpdatesData: Array<EntityUpdateData> = downcast(entityUpdates)
await listener(entityUpdatesData, eventOwnerGroupId)
}
})
.then(noOp)
}
2021-12-23 14:03:23 +01:00
2023-01-02 17:39:05 +01:00
async onCountersUpdateReceived(update: WebsocketCounterData): Promise<void> {
this.countersStream(update)
}
2022-12-27 15:37:40 +01:00
}