@@ -43,6 +43,7 @@ export default class WebchatDb {
43
43
// Prevents issues when switching between different Messaging servers
44
44
// TODO: Remove this check once the 'web_user_map' table is removed
45
45
if ( ! ( await this . checkUserExist ( botId , userMapping . userId ) ) ) {
46
+ this . bp . logger . info ( `No user found for visitor ${ visitorId } in the current mapping, reseting mapping` )
46
47
await this . deleteMappingFromVisitor ( botId , visitorId )
47
48
await createUserAndMapping ( )
48
49
}
@@ -105,11 +106,31 @@ export default class WebchatDb {
105
106
}
106
107
}
107
108
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
+
108
124
async createUserMapping ( botId : string , visitorId : string , userId : string ) : Promise < UserMapping > {
109
125
let mapping : UserMapping | undefined = { botId, visitorId, userId }
110
-
126
+ let lock : sdk . RedisLock
111
127
try {
112
128
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
+
113
134
await this . knex ( 'web_user_map' ) . insert ( mapping )
114
135
this . cacheByVisitor . set ( `${ botId } _${ visitorId } ` , mapping )
115
136
} catch ( err ) {
@@ -124,6 +145,10 @@ export default class WebchatDb {
124
145
. forBot ( botId )
125
146
. attachError ( err )
126
147
. error ( `An error occurred while creating a user mapping for user ${ userId } and visitor ${ visitorId } .` )
148
+ } finally {
149
+ if ( lock ) {
150
+ lock . unlock ( )
151
+ }
127
152
}
128
153
129
154
return mapping
0 commit comments