Skip to content

Commit a05eaf2

Browse files
committed
Add finally blocks for attribute and index operations
- createAttribute: Clear collection cache if trigger fails after adapter creates attribute - deleteAttribute: Clear collection cache if trigger fails after adapter deletes attribute - createIndex: Clear collection cache if trigger fails after adapter creates index - deleteIndex: Clear collection cache if trigger fails after adapter deletes index These operations all follow the pattern: adapter change -> updateDocument -> trigger. If trigger fails, the collection cache could be stale even though updateDocument clears the metadata document cache.
1 parent e48fece commit a05eaf2

File tree

1 file changed

+74
-31
lines changed

1 file changed

+74
-31
lines changed

src/Database/Database.php

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,26 +1594,40 @@ public function createAttribute(string $collection, string $id, string $type, in
15941594
Document::SET_TYPE_APPEND
15951595
);
15961596

1597+
$created = false;
15971598
try {
15981599
$created = $this->adapter->createAttribute($collection->getId(), $id, $type, $size, $signed, $array);
15991600

16001601
if (!$created) {
16011602
throw new DatabaseException('Failed to create attribute');
16021603
}
1604+
1605+
if ($collection->getId() !== self::METADATA) {
1606+
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
1607+
}
1608+
1609+
$this->trigger(self::EVENT_ATTRIBUTE_CREATE, $attribute);
1610+
1611+
return true;
16031612
} catch (DuplicateException $e) {
16041613
// HACK: Metadata should still be updated, can be removed when null tenant collections are supported.
16051614
if (!$this->adapter->getSharedTables() || !$this->isMigrating()) {
16061615
throw $e;
16071616
}
1608-
}
16091617

1610-
if ($collection->getId() !== self::METADATA) {
1611-
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
1612-
}
1618+
if ($collection->getId() !== self::METADATA) {
1619+
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
1620+
}
16131621

1614-
$this->trigger(self::EVENT_ATTRIBUTE_CREATE, $attribute);
1622+
$this->trigger(self::EVENT_ATTRIBUTE_CREATE, $attribute);
16151623

1616-
return true;
1624+
return true;
1625+
} finally {
1626+
// Ensure collection cache is cleared even if trigger fails after adapter changes
1627+
if ($created) {
1628+
$this->purgeCachedCollection($collection->getId());
1629+
}
1630+
}
16171631
}
16181632

16191633
/**
@@ -2320,24 +2334,32 @@ public function deleteAttribute(string $collection, string $id): bool
23202334
}
23212335
}
23222336

2337+
$deleted = false;
23232338
try {
2324-
if (!$this->adapter->deleteAttribute($collection->getId(), $id)) {
2339+
$deleted = $this->adapter->deleteAttribute($collection->getId(), $id);
2340+
if (!$deleted) {
23252341
throw new DatabaseException('Failed to delete attribute');
23262342
}
2327-
} catch (NotFoundException) {
2328-
// Ignore
2329-
}
23302343

2331-
$collection->setAttribute('attributes', \array_values($attributes));
2332-
$collection->setAttribute('indexes', \array_values($indexes));
2344+
$collection->setAttribute('attributes', \array_values($attributes));
2345+
$collection->setAttribute('indexes', \array_values($indexes));
23332346

2334-
if ($collection->getId() !== self::METADATA) {
2335-
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
2336-
}
2347+
if ($collection->getId() !== self::METADATA) {
2348+
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
2349+
}
23372350

2338-
$this->trigger(self::EVENT_ATTRIBUTE_DELETE, $attribute);
2351+
$this->trigger(self::EVENT_ATTRIBUTE_DELETE, $attribute);
23392352

2340-
return true;
2353+
return true;
2354+
} catch (NotFoundException) {
2355+
// Ignore - attribute doesn't exist
2356+
return true;
2357+
} finally {
2358+
// Ensure collection cache is cleared even if trigger fails after adapter changes
2359+
if ($deleted) {
2360+
$this->purgeCachedCollection($collection->getId());
2361+
}
2362+
}
23412363
}
23422364

23432365
/**
@@ -3120,27 +3142,40 @@ public function createIndex(string $collection, string $id, string $type, array
31203142
}
31213143
}
31223144

3145+
$created = false;
31233146
try {
31243147
$created = $this->adapter->createIndex($collection->getId(), $id, $type, $attributes, $lengths, $orders, $indexAttributesWithTypes);
31253148

31263149
if (!$created) {
31273150
throw new DatabaseException('Failed to create index');
31283151
}
3152+
3153+
if ($collection->getId() !== self::METADATA) {
3154+
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
3155+
}
3156+
3157+
$this->trigger(self::EVENT_INDEX_CREATE, $index);
3158+
3159+
return true;
31293160
} catch (DuplicateException $e) {
31303161
// HACK: Metadata should still be updated, can be removed when null tenant collections are supported.
3131-
31323162
if (!$this->adapter->getSharedTables() || !$this->isMigrating()) {
31333163
throw $e;
31343164
}
3135-
}
31363165

3137-
if ($collection->getId() !== self::METADATA) {
3138-
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
3139-
}
3166+
if ($collection->getId() !== self::METADATA) {
3167+
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
3168+
}
31403169

3141-
$this->trigger(self::EVENT_INDEX_CREATE, $index);
3170+
$this->trigger(self::EVENT_INDEX_CREATE, $index);
31423171

3143-
return true;
3172+
return true;
3173+
} finally {
3174+
// Ensure collection cache is cleared even if trigger fails after adapter changes
3175+
if ($created) {
3176+
$this->purgeCachedCollection($collection->getId());
3177+
}
3178+
}
31443179
}
31453180

31463181
/**
@@ -3169,17 +3204,25 @@ public function deleteIndex(string $collection, string $id): bool
31693204
}
31703205
}
31713206

3172-
$deleted = $this->adapter->deleteIndex($collection->getId(), $id);
3207+
$deleted = false;
3208+
try {
3209+
$deleted = $this->adapter->deleteIndex($collection->getId(), $id);
31733210

3174-
$collection->setAttribute('indexes', \array_values($indexes));
3211+
$collection->setAttribute('indexes', \array_values($indexes));
31753212

3176-
if ($collection->getId() !== self::METADATA) {
3177-
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
3178-
}
3213+
if ($collection->getId() !== self::METADATA) {
3214+
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
3215+
}
31793216

3180-
$this->trigger(self::EVENT_INDEX_DELETE, $indexDeleted);
3217+
$this->trigger(self::EVENT_INDEX_DELETE, $indexDeleted);
31813218

3182-
return $deleted;
3219+
return $deleted;
3220+
} finally {
3221+
// Ensure collection cache is cleared even if trigger fails after adapter changes
3222+
if ($deleted) {
3223+
$this->purgeCachedCollection($collection->getId());
3224+
}
3225+
}
31833226
}
31843227

31853228
/**

0 commit comments

Comments
 (0)