updated configs

This commit is contained in:
ArnabChatterjee20k
2026-04-15 16:11:05 +05:30
parent 2ce39768c3
commit 968b1c0861
4 changed files with 74 additions and 34 deletions
+5 -5
View File
@@ -2764,7 +2764,7 @@ return [
'attributes' => [
[
'$id' => ID::custom('userInternalId'),
'type' => Database::VAR_ID,
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
@@ -2775,7 +2775,7 @@ return [
],
[
'$id' => ID::custom('userId'),
'type' => Database::VAR_ID,
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
@@ -2844,15 +2844,15 @@ return [
// permissions must be sorted before md5 conversion to have deterministic hashes
'indexes' => [
[
'$id' => ID::custom('_key_userId'),
'type' => Database::INDEX_KEY,
'$id' => ID::custom('_unique_userId'),
'type' => Database::INDEX_UNIQUE,
'attributes' => ['userId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC]
],
[
'$id' => ID::custom('_key_userInternal'),
'type' => Database::INDEX_KEY,
'type' => Database::INDEX_UNIQUE,
'attributes' => ['userInternalId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC]
+6 -14
View File
@@ -1146,23 +1146,15 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
if (array_key_exists('metadata', $message['data'])) {
$presenceData['metadata'] = $message['data']['metadata'];
}
// for an user if presence is present and expiry is null and service is realtime is the indicator that connection cleanup for the user failed
// in later case of multi-presence per user these must be cleaned up first
// currently in case of single presence per user we can directly upsert
$presenceDocument = new Document($presenceData);
setPermission($presenceDocument, $message['data']['permissions'] ?? null, $authorization);
$presence = $database->withTransaction(function () use ($database, $userId, $presenceDocument, $message) {
$existingPresence = $database->findOne('presenceLogs', [
Query::equal('userId', [$userId]),
]);
if ($existingPresence->isEmpty()) {
$presenceId = $message['data']['presenceId'] ?? 'unique()';
$presenceDocument->setAttribute('$id', $presenceId === 'unique()' ? ID::unique() : $presenceId);
return $database->createDocument('presenceLogs', $presenceDocument);
}
return $database->updateDocument('presenceLogs', $existingPresence->getId(), $presenceDocument);
});
$presenceId = $message['data']['presenceId'] ?? 'unique()';
if ($presenceId !== 'unique()') {
$presenceDocument->setAttribute('$id', $presenceId);
}
$presence = $database->upsertDocument('presenceLogs', $presenceDocument);
$presence->removeAttribute('hostname');
@@ -3,7 +3,6 @@
namespace Appwrite\Platform\Modules\Presences\HTTP;
use Appwrite\Extend\Exception;
use Appwrite\ID;
use Appwrite\Platform\Modules\Presences\HTTP\Action as PresenceAction;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\Method;
@@ -13,7 +12,6 @@ use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Permissions;
@@ -118,20 +116,11 @@ class Upsert extends PresenceAction
$presenceDocument = new Document($presenceData);
$this->setPermission($presenceDocument, $permissions, $user, $authorization);
// inside transaction as realtime also do get -> update/create
$presence = $dbForProject->withTransaction(function () use ($dbForProject, $resolvedUserId, $presenceId, $presenceDocument) {
$existingPresence = $dbForProject->findOne('presenceLogs', [
Query::equal('userId', [$resolvedUserId]),
]);
if ($presenceId !== 'unique()') {
$presenceDocument->setAttribute('$id', $presenceId);
}
if ($existingPresence->isEmpty()) {
$presenceId = $presenceId === 'unique()' ? ID::unique() : $presenceId;
$presenceDocument->setAttribute('$id', $presenceId);
return $dbForProject->createDocument('presenceLogs', $presenceDocument);
}
return $dbForProject->updateDocument('presenceLogs', $existingPresence->getId(), $presenceDocument);
});
$presence = $dbForProject->upsertDocument('presenceLogs', $presenceDocument);
$response->dynamic($presence, Response::MODEL_PRESENCE);
}
@@ -312,4 +312,63 @@ trait PresenceBase
$this->assertEquals(400, $response['headers']['status-code']);
}
public function testUpsertSameUserMaintainsSinglePresence(): void
{
if ($this->getSide() === 'client') {
$this->expectNotToPerformAssertions();
return;
}
$projectId = $this->getProject()['$id'];
$userId = $this->getUser()['$id'];
$headers = \array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders(false));
$firstUpsert = $this->client->call(
Client::METHOD_PUT,
'/presences/' . ID::unique(),
$headers,
[
'userId' => $userId,
'status' => 'online',
'metadata' => ['source' => 'first-upsert'],
]
);
$this->assertEquals(200, $firstUpsert['headers']['status-code']);
$secondUpsert = $this->client->call(
Client::METHOD_PUT,
'/presences/' . ID::unique(),
$headers,
[
'userId' => $userId,
'status' => 'away',
'metadata' => ['source' => 'second-upsert'],
]
);
$this->assertEquals(200, $secondUpsert['headers']['status-code']);
$this->assertEquals('away', $secondUpsert['body']['status']);
$this->assertEquals(['source' => 'second-upsert'], $secondUpsert['body']['metadata']);
$list = $this->client->call(
Client::METHOD_GET,
'/presences',
$headers,
[
'queries' => [
Query::equal('userId', [$userId])->toString(),
],
]
);
$this->assertEquals(200, $list['headers']['status-code']);
$this->assertEquals(1, $list['body']['total']);
$this->assertCount(1, $list['body']['presences']);
$this->assertEquals($userId, $list['body']['presences'][0]['userId']);
$this->assertEquals('away', $list['body']['presences'][0]['status']);
}
}