Skip to content

Database lock fails in transaction on PostgreSQL on second attempt #61125

Open
@Steveb-p

Description

@Steveb-p

Symfony version(s) affected

7.3

Description

Current implementation of Symfony Lock for PdoStore / DoctrineDbalStore will fail on PostgreSQL if:

  • Database connection has an open transaction
  • An attempt is made to acquire a lock on a key for a 2nd time

The error message will be:

current transaction is aborted, commands ignored until end of transaction block

and will appear on any SQL statement sent to the database after Store fails to INSERT (

$sql = "INSERT INTO $this->table ($this->idCol, $this->tokenCol, $this->expirationCol) VALUES (:id, :token, {$this->getCurrentTimestampStatement()} + $this->initialTtl)";
here).

Normally it would rarely happen and be limited to developer usage of the lock, but now since Symfony Messenger has deduplication feature - which combines Symfony Lock - there is a high likelihood that dispatching messages within a transaction can lead to an unrecoverable error (when deduplication mechanism should trigger a skip).

How to reproduce

Following test case can be used to trigger the error.

    /**
     * @requires extension pdo_pgsql
     *
     * @group integration
     */
    public function testTransactionWithPostgreSQL(): void
    {
        if (!$host = getenv('POSTGRES_HOST')) {
            $this->markTestSkipped('Missing POSTGRES_HOST env variable');
        }

        $key = new Key(__METHOD__);

        $dsn = 'pgsql:host='.$host.';user=postgres;password=password';
        $pdo = new \PDO($dsn);
        $pdo->beginTransaction();

        try {
            $store = new PdoStore($pdo);

            $store->save($key);
            $this->assertTrue($store->exists($key));

            $store->save($key);
        } finally {
            $pdo = new \PDO($dsn);
            $pdo->exec('DROP TABLE IF EXISTS lock_keys');
        }
    }

Possible Solution

I'd be happy to provide a PR with a fix, but would need directions on how to approach this.

Additional Context

I was able to trigger the issue both in tests (since I am using DAMA Doctrine bundle for tests I have database transaction open almost immediately), and in a real application - when dispatching a message that needed deduplication (i.e. should be skipped).

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

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy