mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Added mutex + fixed rare duplicate chats bug + fixed connect bug
The mutex will prevent duplicate functions from being called and throwing funky errors.
This commit is contained in:
@@ -112,6 +112,14 @@ WAConnectionTest('Messages', conn => {
|
||||
}
|
||||
})
|
||||
})
|
||||
it('should not duplicate messages', async () => {
|
||||
const results = await Promise.all ([
|
||||
conn.loadMessages (testJid, 50),
|
||||
conn.loadMessages (testJid, 50)
|
||||
])
|
||||
assert.deepEqual (results[0].messages, results[1].messages)
|
||||
assert.ok (results[0].messages.length <= 50)
|
||||
})
|
||||
it('should deliver a message', async () => {
|
||||
const waitForUpdate =
|
||||
promiseTimeout(15000, resolve => {
|
||||
|
||||
111
src/Tests/Tests.Mutex.ts
Normal file
111
src/Tests/Tests.Mutex.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { strict as assert } from 'assert'
|
||||
import { Mutex } from '../WAConnection/Mutex'
|
||||
|
||||
const DEFAULT_WAIT = 1000
|
||||
|
||||
class MyClass {
|
||||
didDoWork = false
|
||||
values: { [k: string]: number } = {}
|
||||
counter = 0
|
||||
|
||||
@Mutex ()
|
||||
async myFunction () {
|
||||
if (this.didDoWork) return
|
||||
|
||||
await new Promise (resolve => setTimeout(resolve, DEFAULT_WAIT))
|
||||
if (this.didDoWork) {
|
||||
throw new Error ('work already done')
|
||||
}
|
||||
this.didDoWork = true
|
||||
}
|
||||
@Mutex (key => key)
|
||||
async myKeyedFunction (key: string) {
|
||||
if (!this.values[key]) {
|
||||
await new Promise (resolve => setTimeout(resolve, DEFAULT_WAIT))
|
||||
if (this.values[key]) throw new Error ('value already set for ' + key)
|
||||
this.values[key] = Math.floor(Math.random ()*100)
|
||||
}
|
||||
return this.values[key]
|
||||
}
|
||||
@Mutex (key => key)
|
||||
async myQueingFunction (key: string) {
|
||||
await new Promise (resolve => setTimeout(resolve, DEFAULT_WAIT))
|
||||
}
|
||||
@Mutex ()
|
||||
async myErrorFunction () {
|
||||
await new Promise (resolve => setTimeout(resolve, 100))
|
||||
this.counter += 1
|
||||
if (this.counter % 2 === 0) {
|
||||
throw new Error ('failed')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe ('garbage', () => {
|
||||
it ('should only execute once', async () => {
|
||||
const stuff = new MyClass ()
|
||||
const start = new Date ()
|
||||
await Promise.all ([...Array(1000)].map(() => stuff.myFunction ()))
|
||||
const diff = new Date ().getTime()-start.getTime()
|
||||
assert.ok (diff < DEFAULT_WAIT*1.25)
|
||||
})
|
||||
it ('should only execute once based on the key', async () => {
|
||||
const stuff = new MyClass ()
|
||||
const start = new Date ()
|
||||
/*
|
||||
In this test, the mutex will lock the function based on the key.
|
||||
|
||||
So, if the function with argument `key1` is underway
|
||||
and another function with key `key1` is called,
|
||||
the call is blocked till the first function completes.
|
||||
However, if argument `key2` is passed, the function is allowed to pass.
|
||||
*/
|
||||
const keys = ['key1', 'key2', 'key3']
|
||||
const duplicates = 1000
|
||||
const results = await Promise.all (
|
||||
keys.flatMap (key => (
|
||||
[...Array(duplicates)].map(() => stuff.myKeyedFunction (key))
|
||||
))
|
||||
)
|
||||
assert.deepEqual (
|
||||
results.slice(0, duplicates).filter (r => r !== results[0]),
|
||||
[]
|
||||
)
|
||||
|
||||
const diff = new Date ().getTime()-start.getTime()
|
||||
assert.ok (diff < DEFAULT_WAIT*1.25)
|
||||
})
|
||||
it ('should execute operations in a queue', async () => {
|
||||
const stuff = new MyClass ()
|
||||
const start = new Date ()
|
||||
|
||||
const keys = ['key1', 'key2', 'key3']
|
||||
|
||||
await Promise.all (
|
||||
keys.flatMap (key => (
|
||||
[...Array(2)].map(() => stuff.myQueingFunction (key))
|
||||
))
|
||||
)
|
||||
|
||||
const diff = new Date ().getTime()-start.getTime()
|
||||
assert.ok (diff < DEFAULT_WAIT*2.2 && diff > DEFAULT_WAIT*1.5)
|
||||
})
|
||||
it ('should throw an error on selected items', async () => {
|
||||
const stuff = new MyClass ()
|
||||
const start = new Date ()
|
||||
|
||||
const WAIT = 100
|
||||
const FUNCS = 40
|
||||
const results = await Promise.all (
|
||||
[...Array(FUNCS)].map(() => stuff.myErrorFunction ().catch(err => err.message))
|
||||
)
|
||||
|
||||
const diff = new Date ().getTime()-start.getTime()
|
||||
assert.ok (diff < WAIT*FUNCS*1.1)
|
||||
|
||||
assert.equal (
|
||||
results.filter (r => r === 'failed').length,
|
||||
FUNCS/2 // half should fail
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user