You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/session/apis/open_group_api/sogsv3/sogsV3MutationCache.ts

136 lines
4.5 KiB
TypeScript

/**
* This is strictly use to resolve conflicts between local state and the opengroup poll updates
* Currently only supports message reactions 26/08/2022
*/
import { filter, findIndex, remove } from 'lodash';
import { handleOpenGroupMessageReactions } from '../../../../util/reactions';
import { OpenGroupMessageV4 } from '../opengroupV2/OpenGroupServerPoller';
export enum ChangeType {
REACTIONS = 0,
}
type ReactionAction = 'ADD' | 'REMOVE';
type ReactionChange = {
messageId: number; // will be serverId of the reacted message
emoji: string;
action: ReactionAction;
};
export type SogsV3Mutation = {
seqno: number | null; // null until mutating API request returns
server: string; // serverUrl
room: string; // roomId
changeType: ChangeType;
metadata: ReactionChange; // For now we only support message reactions
};
// we don't want to export this, we want to export functions that manipulate it
const sogsMutationCache: Array<SogsV3Mutation> = [];
function verifyEntry(entry: SogsV3Mutation): boolean {
return Boolean(
!entry.server ||
!entry.room ||
entry.seqno !== null ||
entry.metadata.messageId ||
entry.metadata.emoji ||
entry.metadata.action === 'ADD' ||
entry.metadata.action === 'REMOVE'
);
}
export function addToMutationCache(entry: SogsV3Mutation) {
if (!verifyEntry(entry)) {
window.log.error('SOGS Mutation Cache: Entry verification on add failed!', entry);
} else {
sogsMutationCache.push(entry);
window.log.info('SOGS Mutation Cache: Entry added!', entry);
}
}
export function updateMutationCache(entry: SogsV3Mutation, seqno: number) {
if (!verifyEntry(entry)) {
window.log.error('SOGS Mutation Cache: Entry verification on update failed!');
} else {
const entryIndex = findIndex(sogsMutationCache, entry);
if (entryIndex >= 0) {
const updatedEntry = entry;
updatedEntry.seqno = seqno;
sogsMutationCache[entryIndex] = updatedEntry;
window.log.info('SOGS Mutation Cache: Entry updated!', updatedEntry);
} else {
window.log.error('SOGS Mutation Cache: Updated failed! Cannot find entry', entry);
}
}
}
export async function processMessagesUsingCache(
server: string,
room: string,
message: OpenGroupMessageV4
) {
const updatedReactions = message.reactions;
const matches: Array<SogsV3Mutation> = filter(sogsMutationCache, { server, room });
if (matches?.length) {
for (const match of matches) {
if (message.seqno && match.seqno && match.seqno <= message.seqno) {
const removedEntry = remove(sogsMutationCache, match);
window.log.info('SOGS Mutation Cache: Entry ignored and removed!', removedEntry);
} else if (!message.seqno || (message.seqno && match.seqno && match.seqno > message.seqno)) {
for (const reaction of Object.keys(message.reactions)) {
const _matches = filter(sogsMutationCache, {
server,
room,
changeType: ChangeType.REACTIONS,
metadata: {
messageId: message.id,
emoji: reaction,
},
});
if (_matches?.length) {
for (const match of _matches) {
switch (match.metadata.action) {
case 'ADD':
updatedReactions[reaction].you = true;
updatedReactions[reaction].count += 1;
window.log.info(
'SOGS Mutation Cache: Added our reaction based on the cache',
updatedReactions[reaction]
);
break;
case 'REMOVE':
updatedReactions[reaction].you = false;
updatedReactions[reaction].count -= 1;
window.log.info(
'SOGS Mutation Cache: Removed our reaction based on the cache',
updatedReactions[reaction]
);
break;
default:
window.log.warn(
'SOGS Mutation Cache: Unsupported metadata action in OpenGroupMessageV4',
match
);
break;
}
}
const removedMatches = remove(sogsMutationCache, ...matches);
window.log.info(
'SOGS Mutation Cache: Removed processed entries from cache!',
removedMatches
);
}
}
}
}
}
message.reactions = updatedReactions;
await handleOpenGroupMessageReactions(message.reactions, message.id);
}