1 import type { UseCaseInterface } from '../Domain/UseCase/UseCaseInterface'
2 import { Result } from '@proton/docs-shared'
3 import type { DocumentUpdate } from '@proton/docs-proto'
4 import type { DecryptedMessage } from '@proton/docs-shared'
5 import { mergeUpdates } from 'yjs'
6 import type { LoggerInterface } from '@proton/utils/logs'
8 export type UpdatePair = {
9 encrypted: DocumentUpdate
10 decrypted: DecryptedMessage
13 export type SquashResult = {
14 unmodifiedUpdates: UpdatePair[]
15 updatesAsSquashed: Uint8Array | undefined
18 export class SquashAlgorithm implements UseCaseInterface<SquashResult> {
19 constructor(private logger: LoggerInterface) {}
21 async execute(updates: UpdatePair[], config: { limit: number; factor: number }): Promise<Result<SquashResult>> {
23 `[Squash] Executing squash algorithm with ${updates.length} updates and config ${JSON.stringify(config)}`,
26 const desiredNumberOfUpdates = Math.floor(config.limit * config.factor)
28 const numUpdatesToSquash = updates.length - desiredNumberOfUpdates
30 if (numUpdatesToSquash <= 0) {
31 this.logger.info(`[Squash] No updates to squash, returning original updates`)
34 updatesAsSquashed: undefined,
35 unmodifiedUpdates: updates,
39 this.logger.info(`[Squash] Squashing ${numUpdatesToSquash} updates`)
41 const updatesToSquash = updates.slice(-numUpdatesToSquash)
42 const unmodifiedUpdates = updates.slice(0, updates.length - numUpdatesToSquash)
44 const updatesAsSquashed = mergeUpdates(updatesToSquash.map((update) => update.decrypted.content))
46 this.logger.info(`[Squash] Squashed ${updatesToSquash.length} updates`)