Skip to content

Commit 0424157

Browse files
authored
fix(channel-web) prevent mapping error (#1814)
1 parent 4c037ef commit 0424157

File tree

1 file changed

+26
-1
lines changed
  • modules/channel-web/src/backend

1 file changed

+26
-1
lines changed

modules/channel-web/src/backend/db.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default class WebchatDb {
4343
// Prevents issues when switching between different Messaging servers
4444
// TODO: Remove this check once the 'web_user_map' table is removed
4545
if (!(await this.checkUserExist(botId, userMapping.userId))) {
46+
this.bp.logger.info(`No user found for visitor ${visitorId} in the current mapping, reseting mapping`)
4647
await this.deleteMappingFromVisitor(botId, visitorId)
4748
await createUserAndMapping()
4849
}
@@ -105,11 +106,31 @@ export default class WebchatDb {
105106
}
106107
}
107108

109+
async waitForLock(lockName: string, durationMs: number, run: number = 0): Promise<sdk.RedisLock> {
110+
const lock = this.bp.distributed.acquireLock(lockName, durationMs)
111+
112+
if (!lock) {
113+
if (run > durationMs / 100) {
114+
throw new Error(`Timeout acquiring lock '${lockName}'`)
115+
}
116+
117+
await new Promise(resolve => setTimeout(resolve, 100))
118+
return this.waitForLock(lockName, durationMs, run + 1)
119+
}
120+
121+
return lock
122+
}
123+
108124
async createUserMapping(botId: string, visitorId: string, userId: string): Promise<UserMapping> {
109125
let mapping: UserMapping | undefined = { botId, visitorId, userId }
110-
126+
let lock: sdk.RedisLock
111127
try {
112128
try {
129+
// Lock prevent issues when multiple endpoints are trying
130+
// to map the user at the same time
131+
const lockName = `create_user_mapping_${botId}_${visitorId}`
132+
lock = await this.waitForLock(lockName, ms('5s'))
133+
113134
await this.knex('web_user_map').insert(mapping)
114135
this.cacheByVisitor.set(`${botId}_${visitorId}`, mapping)
115136
} catch (err) {
@@ -124,6 +145,10 @@ export default class WebchatDb {
124145
.forBot(botId)
125146
.attachError(err)
126147
.error(`An error occurred while creating a user mapping for user ${userId} and visitor ${visitorId}.`)
148+
} finally {
149+
if (lock) {
150+
lock.unlock()
151+
}
127152
}
128153

129154
return mapping

0 commit comments

Comments
 (0)