perf(reconnect): eliminate race condition between connection:open and offline message delivery
perf(reconnect): eliminate race condition between connection:open and offline message delivery
This commit is contained in:
+23
-14
@@ -1499,27 +1499,36 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
})
|
||||
// login complete
|
||||
ws.on('CB:success', async (node: BinaryNode) => {
|
||||
try {
|
||||
await uploadPreKeysToServerIfRequired()
|
||||
await sendPassiveIq('active')
|
||||
|
||||
// After successful login, validate our key-bundle against server
|
||||
try {
|
||||
await digestKeyBundle()
|
||||
} catch (e) {
|
||||
logger.warn({ e }, 'failed to run digest after login')
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn({ err }, 'failed to send initial passive iq')
|
||||
}
|
||||
|
||||
logger.info('opened connection to WA')
|
||||
clearTimeout(qrTimer) // will never happen in all likelyhood -- but just in case WA sends success on first try
|
||||
|
||||
ev.emit('creds.update', { me: { ...authState.creds.me!, lid: node.attrs.lid } })
|
||||
|
||||
// Emit connection:open immediately so the application layer begins processing
|
||||
// incoming messages without waiting for any WA round-trips.
|
||||
ev.emit('connection.update', { connection: 'open' })
|
||||
|
||||
// ─── Background: sendPassiveIq + pre-key validation + key-bundle digest ──
|
||||
// sendPassiveIq('active') tells the WA edge server to start routing live
|
||||
// messages to this connection. All three operations involve WA round-trips
|
||||
// (100–500 ms each) but none need to complete before the app can handle
|
||||
// messages. Run them in parallel, fire-and-forget, non-blocking.
|
||||
Promise.allSettled([sendPassiveIq('active'), uploadPreKeysToServerIfRequired(), digestKeyBundle()])
|
||||
.then(results => {
|
||||
const [passiveResult] = results
|
||||
if (passiveResult.status === 'rejected') {
|
||||
logger.warn({ err: passiveResult.reason }, 'failed to send initial passive iq')
|
||||
}
|
||||
for (const result of results.slice(1)) {
|
||||
if (result.status === 'rejected') {
|
||||
logger.warn({ err: result.reason }, 'background key operation failed after login (non-critical)')
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error({ err }, 'unexpected error in background post-login handler')
|
||||
})
|
||||
|
||||
// Record successful connection metrics
|
||||
recordConnectionAttempt('success')
|
||||
incrementActiveConnections()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import Long from 'long'
|
||||
import type { Readable } from 'stream'
|
||||
import type { URL } from 'url'
|
||||
import { proto } from '../../WAProto/index.js'
|
||||
@@ -30,7 +29,7 @@ export type WAMessageKey = proto.IMessageKey & {
|
||||
export type PlaceholderMessageData = {
|
||||
key: WAMessageKey
|
||||
pushName?: string | null
|
||||
messageTimestamp?: number | Long | null
|
||||
messageTimestamp?: WAMessage['messageTimestamp']
|
||||
participant?: string | null
|
||||
participantAlt?: string | null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user