mankowitz's avatar

RateLimiter causing MySQL deadlock on cache access

(This is crossposted to SO: https://stackoverflow.com/questions/78541364/)

I'm using Laravel 10 with MySql 8.0.35 and have a fairly basic api limiter which governs the use of a webhook. Most of the time it works. Sometimes, it generates a database deadlock. This is the exception I get:

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (Connection: mysql, SQL: insert ignore into `cache` (`key`, `value`, `expiration`) values (staging_cache534e467cdecd3603ca82c5d4b56095801efbe432:timer, i:1716832967;, 1716832967))

The ratelimiter is defined in the Kernel (app/Http/Kernel.php)

  protected $middlewareGroups = [
    'api' => [
      'throttle:60,1',
      ...,
    ],

This seems to be related to line 132 in .../laravel/framework/src/Illuminate/Cache/RateLimiter.php

public function increment($key, $decaySeconds = 60, $amount = 1)    
{    
    $key = $this->cleanRateLimiterKey($key);    
    $this->cache->add(      
       $key.':timer', $this->availableAt($decaySeconds), $decaySeconds    // <--- This line
    );

In case it's valuable, this is most of the webhook. It does not use the cache directly:

  public static function handleWebHook(Request $request): JsonResponse|HttpResponse
  {
    $secretToken = config("zoom.oauth.token");
    if (request()->header('authorization') == $secretToken) {
      $response = $request->getContent(); 
      ....
    }

    $event = $request->input("event");

    switch ($event) {
      case "meeting.ended":
        event(new ProviderAvailabilityChanged(....));
        break;

      case "meeting.started":
        event(new ProviderAvailabilityChanged(....));
        break;

      case "endpoint.url_validation":
        $plainToken = request()->input("payload.plainToken");
        $encryptedToken = hash_hmac("sha256", $plainToken, $secretToken);
        return response()->json(compact('plainToken', 'encryptedToken'));
    }

    return response('Received', 200);
  }
0 likes
2 replies
chewlim's avatar

Did you manage to find the solution? I'm getting the same error after upgrading to Laravel 10.

Please or to participate in this conversation.