feat: Mutex redesign - isolate event processing for better ordering and throughput (#2137)
* fix: improve message resend logic by adding checks for message IDs * Revert "fix: improve message resend logic by adding checks for message IDs" This reverts commit c03f9d8e6fc6cbfbb9d1f8f67c169700e704213d. * fix: introduce separate mutexes for message, receipt, app state patch, and notification processing * fix: remove unused processing mutex for notifications
This commit is contained in:
+17
-4
@@ -72,8 +72,18 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
let privacySettings: { [_: string]: string } | undefined
|
let privacySettings: { [_: string]: string } | undefined
|
||||||
|
|
||||||
let syncState: SyncState = SyncState.Connecting
|
let syncState: SyncState = SyncState.Connecting
|
||||||
/** this mutex ensures that the notifications (receipts, messages etc.) are processed in order */
|
|
||||||
const processingMutex = makeMutex()
|
/** this mutex ensures that messages are processed in order */
|
||||||
|
const messageMutex = makeMutex()
|
||||||
|
|
||||||
|
/** this mutex ensures that receipts are processed in order */
|
||||||
|
const receiptMutex = makeMutex()
|
||||||
|
|
||||||
|
/** this mutex ensures that app state patches are processed in order */
|
||||||
|
const appStatePatchMutex = makeMutex()
|
||||||
|
|
||||||
|
/** this mutex ensures that notifications are processed in order */
|
||||||
|
const notificationMutex = makeMutex()
|
||||||
|
|
||||||
// Timeout for AwaitingInitialSync state
|
// Timeout for AwaitingInitialSync state
|
||||||
let awaitingSyncTimeout: NodeJS.Timeout | undefined
|
let awaitingSyncTimeout: NodeJS.Timeout | undefined
|
||||||
@@ -748,7 +758,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
let initial: LTHashState
|
let initial: LTHashState
|
||||||
let encodeResult: { patch: proto.ISyncdPatch; state: LTHashState }
|
let encodeResult: { patch: proto.ISyncdPatch; state: LTHashState }
|
||||||
|
|
||||||
await processingMutex.mutex(async () => {
|
await appStatePatchMutex.mutex(async () => {
|
||||||
await authState.keys.transaction(async () => {
|
await authState.keys.transaction(async () => {
|
||||||
logger.debug({ patch: patchCreate }, 'applying app patch')
|
logger.debug({ patch: patchCreate }, 'applying app patch')
|
||||||
|
|
||||||
@@ -1180,7 +1190,10 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
...sock,
|
...sock,
|
||||||
createCallLink,
|
createCallLink,
|
||||||
getBotListV2,
|
getBotListV2,
|
||||||
processingMutex,
|
messageMutex,
|
||||||
|
receiptMutex,
|
||||||
|
appStatePatchMutex,
|
||||||
|
notificationMutex,
|
||||||
fetchPrivacySettings,
|
fetchPrivacySettings,
|
||||||
upsertMessage,
|
upsertMessage,
|
||||||
appPatch,
|
appPatch,
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
ev,
|
ev,
|
||||||
authState,
|
authState,
|
||||||
ws,
|
ws,
|
||||||
processingMutex,
|
messageMutex,
|
||||||
|
notificationMutex,
|
||||||
|
receiptMutex,
|
||||||
signalRepository,
|
signalRepository,
|
||||||
query,
|
query,
|
||||||
upsertMessage,
|
upsertMessage,
|
||||||
@@ -1067,7 +1069,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
processingMutex.mutex(async () => {
|
receiptMutex.mutex(async () => {
|
||||||
const status = getStatusFromReceiptType(attrs.type)
|
const status = getStatusFromReceiptType(attrs.type)
|
||||||
if (
|
if (
|
||||||
typeof status !== 'undefined' &&
|
typeof status !== 'undefined' &&
|
||||||
@@ -1141,7 +1143,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
processingMutex.mutex(async () => {
|
notificationMutex.mutex(async () => {
|
||||||
const msg = await processNotification(node)
|
const msg = await processNotification(node)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me!.id)
|
const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me!.id)
|
||||||
@@ -1218,7 +1220,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await processingMutex.mutex(async () => {
|
await messageMutex.mutex(async () => {
|
||||||
await decrypt()
|
await decrypt()
|
||||||
// message failed to decrypt
|
// message failed to decrypt
|
||||||
if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT && msg.category !== 'peer') {
|
if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT && msg.category !== 'peer') {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
const {
|
const {
|
||||||
ev,
|
ev,
|
||||||
authState,
|
authState,
|
||||||
processingMutex,
|
messageMutex,
|
||||||
signalRepository,
|
signalRepository,
|
||||||
upsertMessage,
|
upsertMessage,
|
||||||
query,
|
query,
|
||||||
@@ -1199,7 +1199,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
})
|
})
|
||||||
if (config.emitOwnEvents) {
|
if (config.emitOwnEvents) {
|
||||||
process.nextTick(async () => {
|
process.nextTick(async () => {
|
||||||
await processingMutex.mutex(() => upsertMessage(fullMsg, 'append'))
|
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user