Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Lock] Not working anymore with RedisStore and predis/predis since evalSha implementation #59087

Closed
@Yondz

Description

@Yondz

Symfony version(s) affected

7.2.0

Description

Hi,

When updating our 7.1.x application to 7.2.0 we've experienced a regression on the Lock component in a specific configuration using predis/predis.

It seems that the newly introduced evalSha approach (#58533) is not working when using Lock component with both predis and Cache component.

Predis\Client has an option to throw or not exceptions when receiving errors from Redis (see \Predis\Client::onErrorResponse) but this seems to be forced to false by Symfony\Component\Cache\Adapter\RedisAdapter

Due to this behavior, the logic introduced to Symfony\Component\Lock\Store\RedisStore in #58533 for Predis can't work properly because no ServerException are thrown. Instead, $this->redis->evalSha() calls return a Predis\Response\Error containing the expected error message (self::NO_SCRIPT_ERROR_MESSAGE) when the script hasn't been loaded yet :

        try {
            return $this->redis->evalSha($scriptSha, 1, $resource, ...$args);
        } catch (ServerException $e) {
            // Fallthrough only if we need to load the script
            if (self::NO_SCRIPT_ERROR_MESSAGE !== $e->getMessage()) {
                throw new LockStorageException($e->getMessage(), $e->getCode(), $e);
            }
        }

        try {
            $this->redis->script('LOAD', $script);
        } catch (ServerException $e) {
            throw new LockStorageException($e->getMessage(), $e->getCode(), $e);
        }

        try {
            return $this->redis->evalSha($scriptSha, 1, $resource, ...$args);
        } catch (ServerException $e) {
            throw new LockStorageException($e->getMessage(), $e->getCode(), $e);
        }

How to reproduce

  1. Clone https://github.com/Yondz/symfony_bug_lock_7.2 and install dependencies
  2. Make sure you don't have php8.x-redis extension enabled to ensure predis usage
  3. Start the redis container : docker compose up -d
  4. Launch this command (wrapped by symfony cli) : symfony console app:lock:issue

You should get an exception :
image

Possible Solution

I guess RedisStore could be fixed to test if $this->redis->getOptions()->exceptions is true (then try/catch is applicable) or false (then result response should be manipulated)

A simple workaround would be to manually throw ServerException if the evalSha returns an Error, but this will have to be handled in the 3 try/catches

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions