66
77use DateTimeImmutable ;
88use Doctrine \DBAL \Connection ;
9+ use Doctrine \DBAL \DriverManager ;
10+ use Doctrine \DBAL \Platforms \PostgreSQLPlatform ;
11+ use Doctrine \DBAL \Platforms \SQLitePlatform ;
912use Doctrine \DBAL \Schema \Schema ;
1013use Patchlevel \EventSourcing \Aggregate \AggregateHeader ;
1114use Patchlevel \EventSourcing \Message \Message ;
1215use Patchlevel \EventSourcing \Schema \DoctrineSchemaDirector ;
1316use Patchlevel \EventSourcing \Serializer \DefaultEventSerializer ;
1417use Patchlevel \EventSourcing \Store \DoctrineDbalStore ;
18+ use Patchlevel \EventSourcing \Store \Header \PlayheadHeader ;
19+ use Patchlevel \EventSourcing \Store \Header \RecordedOnHeader ;
20+ use Patchlevel \EventSourcing \Store \Header \StreamNameHeader ;
21+ use Patchlevel \EventSourcing \Store \LockCouldNotBeAcquired ;
1522use Patchlevel \EventSourcing \Store \Store ;
1623use Patchlevel \EventSourcing \Store \UniqueConstraintViolation ;
1724use Patchlevel \EventSourcing \Tests \DbalManager ;
2027use PHPUnit \Framework \TestCase ;
2128
2229use function json_decode ;
30+ use function sprintf ;
2331
2432#[CoversNothing]
2533final class DoctrineDbalStoreTest extends TestCase
@@ -34,6 +42,7 @@ public function setUp(): void
3442 $ this ->store = new DoctrineDbalStore (
3543 $ this ->connection ,
3644 DefaultEventSerializer::createFromPaths ([__DIR__ . '/Events ' ]),
45+ config: ['lock_timeout ' => 1 ],
3746 );
3847
3948 $ schemaDirector = new DoctrineSchemaDirector (
@@ -190,6 +199,45 @@ public function testSave10000Messages(): void
190199 self ::assertEquals (10000 , $ result );
191200 }
192201
202+ public function testSaveLockTimeout (): void
203+ {
204+ if ($ this ->connection ->getDatabasePlatform () instanceof SQLitePlatform) {
205+ $ this ->markTestSkipped ('SQLite does not support locks ' );
206+ }
207+
208+ if ($ this ->connection ->getDatabasePlatform () instanceof PostgreSQLPlatform) {
209+ $ this ->markTestSkipped ('PostgreSQL does lock indefinitely ' );
210+ }
211+
212+ $ profileId = ProfileId::generate ();
213+
214+ $ messages = [
215+ Message::create (new ProfileCreated ($ profileId , 'test ' ))
216+ ->withHeader (new StreamNameHeader (sprintf ('profile-%s ' , $ profileId ->toString ())))
217+ ->withHeader (new PlayheadHeader (1 ))
218+ ->withHeader (new RecordedOnHeader (new DateTimeImmutable ('2020-01-01 00:00:00 ' ))),
219+ ];
220+
221+ $ connection = DriverManager::getConnection ($ this ->connection ->getParams ());
222+
223+ $ lock = $ connection ->fetchOne (
224+ sprintf (
225+ 'SELECT GET_LOCK("%s", %d) ' ,
226+ 133742 ,
227+ 1 ,
228+ ),
229+ );
230+ self ::assertSame (1 , $ lock );
231+
232+ $ this ->expectException (LockCouldNotBeAcquired::class);
233+ $ this ->expectExceptionMessage ('The lock with id [133742] could not be acquired with a timeout of 1 ' );
234+ try {
235+ $ this ->store ->save (...$ messages );
236+ } finally {
237+ $ connection ->close ();
238+ }
239+ }
240+
193241 public function testLoad (): void
194242 {
195243 $ profileId = ProfileId::generate ();
0 commit comments