feat: db perf improvements

This commit is contained in:
loks0n
2025-03-04 14:48:28 +00:00
parent 52ba87e77e
commit 78bbac2ef6
3 changed files with 77 additions and 11 deletions
+25 -2
View File
@@ -3468,11 +3468,34 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
static $relatedCollectionsCache = [];
$relationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
// First collect all required related collection IDs
$relatedCollectionIds = [];
foreach ($relationships as $relationship) {
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
$cacheKey = 'database_' . $database->getInternalId() . '_' . $relatedCollectionId;
if (!isset($relatedCollectionsCache[$cacheKey])) {
$relatedCollectionIds[$cacheKey] = $relatedCollectionId;
}
}
// Fetch all required collections in a single batch if needed
if (!empty($relatedCollectionIds)) {
foreach ($relatedCollectionIds as $cacheKey => $relatedCollectionId) {
$relatedCollectionsCache[$cacheKey] = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)
);
}
}
// Now process each relationship with cached collection data
foreach ($relationships as $relationship) {
$related = $document->getAttribute($relationship->getAttribute('key'));
@@ -3491,8 +3514,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
}
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
// todo: Use local cache for this getDocument
$relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId));
$cacheKey = 'database_' . $database->getInternalId() . '_' . $relatedCollectionId;
$relatedCollection = $relatedCollectionsCache[$cacheKey];
foreach ($relations as $index => $doc) {
if ($doc instanceof Document) {
+24 -3
View File
@@ -1915,7 +1915,17 @@ App::post('/v1/functions/:functionId/executions')
throw new Exception($validator->getDescription(), 400);
}
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
// Cache keys for frequently accessed documents
static $functionCache = [];
static $deploymentCache = [];
static $buildCache = [];
// Get function document with caching
$cacheKey = $functionId;
if (!isset($functionCache[$cacheKey])) {
$functionCache[$cacheKey] = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
}
$function = $functionCache[$cacheKey];
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -1934,7 +1944,13 @@ App::post('/v1/functions/:functionId/executions')
throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported');
}
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', '')));
// Get deployment document with caching
$deploymentId = $function->getAttribute('deployment', '');
$deploymentCacheKey = $deploymentId;
if (!isset($deploymentCache[$deploymentCacheKey])) {
$deploymentCache[$deploymentCacheKey] = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $deploymentId));
}
$deployment = $deploymentCache[$deploymentCacheKey];
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function');
@@ -1945,7 +1961,12 @@ App::post('/v1/functions/:functionId/executions')
}
/** Check if build has completed */
$build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')));
$buildId = $deployment->getAttribute('buildId', '');
$buildCacheKey = $buildId;
if (!isset($buildCache[$buildCacheKey])) {
$buildCache[$buildCacheKey] = Authorization::skip(fn () => $dbForProject->getDocument('builds', $buildId));
}
$build = $buildCache[$buildCacheKey];
if ($build->isEmpty()) {
throw new Exception(Exception::BUILD_NOT_FOUND);
}
+28 -6
View File
@@ -809,16 +809,38 @@ App::get('/v1/users/:userId/memberships')
throw new Exception(Exception::USER_NOT_FOUND);
}
$memberships = array_map(function ($membership) use ($dbForProject, $user) {
$team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId'));
$memberships = $user->getAttribute('memberships', []);
// Get all team IDs to fetch in a single query
$teamIds = array_map(function ($membership) {
return $membership->getAttribute('teamId');
}, $memberships);
// Fetch all teams in a single query if there are any memberships
$teams = [];
if (!empty($teamIds)) {
$teamsDocuments = $dbForProject->find('teams', [
Query::equal('$id', $teamIds),
]);
// Index teams by ID for quick lookup
foreach ($teamsDocuments as $team) {
$teams[$team->getId()] = $team;
}
}
// Now map memberships with team data
$memberships = array_map(function ($membership) use ($teams, $user) {
$teamId = $membership->getAttribute('teamId');
$team = $teams[$teamId] ?? null;
$membership
->setAttribute('teamName', $team->getAttribute('name'))
->setAttribute('teamName', $team ? $team->getAttribute('name') : '')
->setAttribute('userName', $user->getAttribute('name'))
->setAttribute('userEmail', $user->getAttribute('email'));
return $membership;
}, $user->getAttribute('memberships', []));
}, $memberships);
$response->dynamic(new Document([
'memberships' => $memberships,