Skip to content

Commit e75b30b

Browse files
authored
Merge pull request #505 from utopia-php/feat-cache-updates
Feat cache updates
2 parents 8a7b212 + e783760 commit e75b30b

File tree

2 files changed

+48
-96
lines changed

2 files changed

+48
-96
lines changed

src/Database/Database.php

Lines changed: 40 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,17 +1462,8 @@ public function createAttribute(string $collection, string $id, string $type, in
14621462
throw new DatabaseException("Attribute of type: $type requires the following filters: " . implode(",", $requiredFilters));
14631463
}
14641464

1465-
if (
1466-
$this->adapter->getLimitForAttributes() > 0 &&
1467-
$this->adapter->getCountOfAttributes($collection) >= $this->adapter->getLimitForAttributes()
1468-
) {
1469-
throw new LimitException('Column limit reached. Cannot create new attribute.');
1470-
}
1471-
1472-
if ($format) {
1473-
if (!Structure::hasFormat($format, $type)) {
1474-
throw new DatabaseException('Format ("' . $format . '") not available for this attribute type ("' . $type . '")');
1475-
}
1465+
if ($format && !Structure::hasFormat($format, $type)) {
1466+
throw new DatabaseException('Format ("' . $format . '") not available for this attribute type ("' . $type . '")');
14761467
}
14771468

14781469
$attribute = new Document([
@@ -1489,22 +1480,20 @@ public function createAttribute(string $collection, string $id, string $type, in
14891480
'filters' => $filters,
14901481
]);
14911482

1492-
$collection->setAttribute('attributes', $attribute, Document::SET_TYPE_APPEND);
1483+
$this->checkAttribute($collection, $attribute);
14931484

1494-
if (
1495-
$this->adapter->getDocumentSizeLimit() > 0 &&
1496-
$this->adapter->getAttributeWidth($collection) >= $this->adapter->getDocumentSizeLimit()
1497-
) {
1498-
throw new LimitException('Row width limit reached. Cannot create new attribute.');
1499-
}
1485+
$collection->setAttribute(
1486+
'attributes',
1487+
$attribute,
1488+
Document::SET_TYPE_APPEND
1489+
);
15001490

15011491
switch ($type) {
15021492
case self::VAR_STRING:
15031493
if ($size > $this->adapter->getLimitForString()) {
15041494
throw new DatabaseException('Max size allowed for string is: ' . number_format($this->adapter->getLimitForString()));
15051495
}
15061496
break;
1507-
15081497
case self::VAR_INTEGER:
15091498
$limit = ($signed) ? $this->adapter->getLimitForInt() / 2 : $this->adapter->getLimitForInt();
15101499
if ($size > $limit) {
@@ -2259,8 +2248,24 @@ public function createRelationship(
22592248
}
22602249

22612250
$this->silent(function () use ($collection, $relatedCollection, $type, $twoWay, $id, $twoWayKey) {
2262-
$this->updateDocument(self::METADATA, $collection->getId(), $collection);
2263-
$this->updateDocument(self::METADATA, $relatedCollection->getId(), $relatedCollection);
2251+
try {
2252+
$this->withTransaction(function () use ($collection, $relatedCollection) {
2253+
$this->updateDocument(self::METADATA, $collection->getId(), $collection);
2254+
$this->updateDocument(self::METADATA, $relatedCollection->getId(), $relatedCollection);
2255+
});
2256+
} catch (\Throwable $e) {
2257+
$this->adapter->deleteRelationship(
2258+
$collection->getId(),
2259+
$relatedCollection->getId(),
2260+
$type,
2261+
$twoWay,
2262+
$id,
2263+
$twoWayKey,
2264+
Database::RELATION_SIDE_PARENT
2265+
);
2266+
2267+
throw new DatabaseException('Failed to create relationship: ' . $e->getMessage());
2268+
}
22642269

22652270
$indexKey = '_index_' . $id;
22662271
$twoWayIndexKey = '_index_' . $twoWayKey;
@@ -2328,13 +2333,13 @@ public function updateRelationship(
23282333
!\is_null($newKey)
23292334
&& \in_array($newKey, \array_map(fn ($attribute) => $attribute['key'], $attributes))
23302335
) {
2331-
throw new DuplicateException('Attribute already exists');
2336+
throw new DuplicateException('Relationship already exists');
23322337
}
23332338

23342339
$attributeIndex = array_search($id, array_map(fn ($attribute) => $attribute['$id'], $attributes));
23352340

23362341
if ($attributeIndex === false) {
2337-
throw new NotFoundException('Attribute not found');
2342+
throw new NotFoundException('Relationship not found');
23382343
}
23392344

23402345
$attribute = $attributes[$attributeIndex];
@@ -2521,7 +2526,7 @@ public function deleteRelationship(string $collection, string $id): bool
25212526
}
25222527

25232528
if (\is_null($relationship)) {
2524-
throw new NotFoundException('Attribute not found');
2529+
throw new NotFoundException('Relationship not found');
25252530
}
25262531

25272532
$collection->setAttribute('attributes', \array_values($attributes));
@@ -2545,8 +2550,14 @@ public function deleteRelationship(string $collection, string $id): bool
25452550
$relatedCollection->setAttribute('attributes', \array_values($relatedAttributes));
25462551

25472552
$this->silent(function () use ($collection, $relatedCollection, $type, $twoWay, $id, $twoWayKey, $side) {
2548-
$this->updateDocument(self::METADATA, $collection->getId(), $collection);
2549-
$this->updateDocument(self::METADATA, $relatedCollection->getId(), $relatedCollection);
2553+
try {
2554+
$this->withTransaction(function () use ($collection, $relatedCollection) {
2555+
$this->updateDocument(self::METADATA, $collection->getId(), $collection);
2556+
$this->updateDocument(self::METADATA, $relatedCollection->getId(), $relatedCollection);
2557+
});
2558+
} catch (\Throwable $e) {
2559+
throw new DatabaseException('Failed to delete relationship: ' . $e->getMessage());
2560+
}
25502561

25512562
$indexKey = '_index_' . $id;
25522563
$twoWayIndexKey = '_index_' . $twoWayKey;
@@ -2992,35 +3003,9 @@ public function getDocument(string $collection, string $id, array $queries = [],
29923003
$attribute['type'] === Database::VAR_RELATIONSHIP
29933004
);
29943005

2995-
$hasTwoWayRelationship = false;
2996-
foreach ($relationships as $relationship) {
2997-
if ($relationship['options']['twoWay']) {
2998-
$hasTwoWayRelationship = true;
2999-
break;
3000-
}
3001-
}
3002-
3003-
/**
3004-
* Bug with function purity in PHPStan means it thinks $this->map is always empty
3005-
* @phpstan-ignore-next-line
3006-
*/
3007-
foreach ($this->map as $key => $value) {
3008-
[$k, $v] = \explode('=>', $key);
3009-
$ck = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':map:' . $k;
3010-
$cache = $this->cache->load($ck, self::TTL, $ck);
3011-
if (empty($cache)) {
3012-
$cache = [];
3013-
}
3014-
if (!\in_array($v, $cache)) {
3015-
$cache[] = $v;
3016-
$this->cache->save($ck, $cache, $ck);
3017-
}
3018-
}
3019-
30203006
// Don't save to cache if it's part of a relationship
3021-
if (!$hasTwoWayRelationship && empty($relationships)) {
3007+
if (empty($relationships)) {
30223008
$this->cache->save($documentCacheKey, $document->getArrayCopy(), $documentCacheHash);
3023-
// Add document reference to the collection key
30243009
$this->cache->save($collectionCacheKey, 'empty', $documentCacheKey);
30253010
}
30263011

@@ -3948,7 +3933,6 @@ public function updateDocument(string $collection, string $id, Document $documen
39483933

39493934
$document = $this->decode($collection, $document);
39503935

3951-
$this->purgeRelatedDocuments($collection, $id);
39523936
$this->purgeCachedDocument($collection->getId(), $id);
39533937
$this->trigger(self::EVENT_DOCUMENT_UPDATE, $document);
39543938

@@ -4103,7 +4087,6 @@ public function updateDocuments(string $collection, Document $updates, array $qu
41034087
}
41044088

41054089
foreach ($documents as $document) {
4106-
$this->purgeRelatedDocuments($collection, $document->getId());
41074090
$this->purgeCachedDocument($collection->getId(), $document->getId());
41084091
}
41094092

@@ -4752,7 +4735,6 @@ public function deleteDocument(string $collection, string $id): bool
47524735
return $this->adapter->deleteDocument($collection->getId(), $id);
47534736
});
47544737

4755-
$this->purgeRelatedDocuments($collection, $id);
47564738
$this->purgeCachedDocument($collection->getId(), $id);
47574739

47584740
$this->trigger(self::EVENT_DOCUMENT_DELETE, $document);
@@ -5246,7 +5228,6 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba
52465228
throw new ConflictException('Document was updated after the request timestamp');
52475229
}
52485230

5249-
$this->purgeRelatedDocuments($collection, $document->getId());
52505231
$this->purgeCachedDocument($collection->getId(), $document->getId());
52515232
}
52525233

@@ -5292,6 +5273,8 @@ public function purgeCachedCollection(string $collectionId): bool
52925273
$this->cache->purge($documentKey);
52935274
}
52945275

5276+
$this->cache->purge($collectionKey);
5277+
52955278
return true;
52965279
}
52975280

@@ -5993,39 +5976,6 @@ public static function convertQueries(Document $collection, array $queries): arr
59935976
return $queries;
59945977
}
59955978

5996-
/**
5997-
* @param Document $collection
5998-
* @param string $id
5999-
* @return void
6000-
* @throws DatabaseException
6001-
*/
6002-
private function purgeRelatedDocuments(Document $collection, string $id): void
6003-
{
6004-
if ($collection->getId() === self::METADATA) {
6005-
return;
6006-
}
6007-
6008-
$relationships = \array_filter(
6009-
$collection->getAttribute('attributes', []),
6010-
fn ($attribute) =>
6011-
$attribute['type'] === Database::VAR_RELATIONSHIP
6012-
);
6013-
6014-
if (empty($relationships)) {
6015-
return;
6016-
}
6017-
6018-
$key = $this->cacheName . '-cache-' . $this->getNamespace() . ':map:' . $collection->getId() . ':' . $id;
6019-
$cache = $this->cache->load($key, self::TTL, $key);
6020-
if (!empty($cache)) {
6021-
foreach ($cache as $v) {
6022-
list($collectionId, $documentId) = explode(':', $v);
6023-
$this->purgeCachedDocument($collectionId, $documentId);
6024-
}
6025-
$this->cache->purge($key);
6026-
}
6027-
}
6028-
60295979
/**
60305980
* @return array<array<string, mixed>>
60315981
*/

tests/e2e/Adapter/Base.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7897,7 +7897,7 @@ public function testIdenticalTwoWayKeyRelationship(): void
78977897
);
78987898
$this->fail('Failed to throw Exception');
78997899
} catch (Exception $e) {
7900-
$this->assertEquals('Attribute already exists', $e->getMessage());
7900+
$this->assertEquals('Relationship already exists', $e->getMessage());
79017901
}
79027902

79037903
try {
@@ -12955,10 +12955,12 @@ public function testDeleteMissingRelationship(): void
1295512955
return;
1295612956
}
1295712957

12958-
$this->expectException(Exception::class);
12959-
$this->expectExceptionMessage('Attribute not found');
12960-
12961-
static::getDatabase()->deleteRelationship('test', 'test2');
12958+
try {
12959+
static::getDatabase()->deleteRelationship('test', 'test2');
12960+
$this->fail('Failed to throw exception');
12961+
} catch (\Throwable $e) {
12962+
$this->assertEquals('Relationship not found', $e->getMessage());
12963+
}
1296212964
}
1296312965

1296412966
public function testCreateInvalidIntValueRelationship(): void
@@ -13321,7 +13323,7 @@ public function testUpdateRelationshipToExistingKey(): void
1332113323
static::getDatabase()->updateRelationship('ovens', 'cakes', newKey: 'owner');
1332213324
$this->fail('Failed to throw exception');
1332313325
} catch (DuplicateException $e) {
13324-
$this->assertEquals('Attribute already exists', $e->getMessage());
13326+
$this->assertEquals('Relationship already exists', $e->getMessage());
1332513327
}
1332613328

1332713329
try {

0 commit comments

Comments
 (0)