felanios / murlock

MurLock: A distributed locking solution for NestJS, providing a decorator for critical sections with Redis-based synchronization. Ideal for microservices and scalable applications.
https://www.npmjs.com/package/murlock
MIT License
62 stars 1 forks source link

Lock Acquired multiple time on the same Nest.js Instance #33

Closed Chiyo-no-sake closed 6 months ago

Chiyo-no-sake commented 6 months ago

This is pretty much self explainatory, but for instance, take the following logs:

[Nest] 220767  - 02/19/2024, 10:27:44 AM     LOG [OrdersController] Received request to create a new order from a111c873-dba6-4af3-aa06-8e37d12b7c1b
[Nest] 220767  - 02/19/2024, 10:27:44 AM   DEBUG [MurLockService] MurLock Client ID is dc467585-ecf1-4654-bc51-5af88fcf68db
[Nest] 220767  - 02/19/2024, 10:27:44 AM   DEBUG [MurLockService] undefined
[Nest] 220767  - 02/19/2024, 10:27:44 AM     LOG [MurLockService] Successfully obtained lock for key OrdersService:createOrder:https://localhost/s1-s1/profile/dlterp/stores#S1%20Store:a111c873-dba6-4af3-aa06-8e37d12b7c1b
[Nest] 220767  - 02/19/2024, 10:27:44 AM     LOG [MurLockService] undefined
[Nest] 220767  - 02/19/2024, 10:27:44 AM     LOG [OrdersController] Received request to create a new order from a111c873-dba6-4af3-aa06-8e37d12b7c1b
[Nest] 220767  - 02/19/2024, 10:27:44 AM   DEBUG [MurLockService] MurLock Client ID is dc467585-ecf1-4654-bc51-5af88fcf68db
[Nest] 220767  - 02/19/2024, 10:27:44 AM   DEBUG [MurLockService] undefined
[Nest] 220767  - 02/19/2024, 10:27:44 AM     LOG [MurLockService] Successfully obtained lock for key OrdersService:createOrder:https://localhost/s1-s1/profile/dlterp/stores#S1%20Store:a111c873-dba6-4af3-aa06-8e37d12b7c1b
[Nest] 220767  - 02/19/2024, 10:27:44 AM     LOG [MurLockService] undefined

Above you can see two parallel requests being handled by Nest, as you see Murlock assigns both requests the same clientID and allows for both to acquire the lock, despite having the same key. This results in multiple concurrency problems, and leads to the following murlock error when the latter request finishes:

Failed to release lock for key OrdersService:createOrder:https://localhost/s1-s1/profile/dlterp/stores#S1%20Store:a111c873-dba6-4af3-aa06-8e37d12b7c1b: Failed to release lock for key OrdersService:createOrder:https://localhost/s1-s1/profile/dlterp/stores#S1%20Store:a111c873-dba6-4af3-aa06-8e37d12b7c1b

Here's my config:

MurLockModule.forRootAsync({
    imports: [ConfigModule],
    inject: [ConfigService],
    useFactory: (configService: ConfigService) => ({
      redisOptions: {
        url: `redis://${configService.getOrThrow('REDIS_HOST')}:${configService.getOrThrow('REDIS_PORT')}`,
      },
      wait: 1000,
      maxAttempts: 3,
      logLevel: "debug"
    }),
  });

I can just suppose that the problem is the clientID being the same for the whole instance, instead of changing for each handled request (?)

Is there any workaround to this? Is this a Bug or am I using this lib incorrectly?

felanios commented 6 months ago

Hi @Chiyo-no-sake, I was guessing that this problem might occur. Previously, in order to avoid this problem, I used the nestjs-cls package and managed the clientId on a request basis, but that package constantly caused dependency problems. I guess, if a different context is opened for each request in async-local-storage and managed there, such a problem will not be encountered, I will make an improvement for this.

felanios commented 6 months ago

Hi @Chiyo-no-sake, I released the new version to solve this issue. https://www.npmjs.com/package/murlock/v/3.2.0 you can check this, fyi