Description
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
(
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).