mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch 'new-pool-adapter' into documents-db-api
This commit is contained in:
@@ -138,3 +138,4 @@ _APP_PROJECT_REGIONS=default
|
||||
_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000
|
||||
_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main
|
||||
_APP_TRUSTED_HEADERS=x-forwarded-for
|
||||
_APP_POOL_ADAPTER=stack
|
||||
|
||||
@@ -25,6 +25,8 @@ use Utopia\Logger\Adapter\LogOwl;
|
||||
use Utopia\Logger\Adapter\Raygun;
|
||||
use Utopia\Logger\Adapter\Sentry;
|
||||
use Utopia\Logger\Logger;
|
||||
use Utopia\Pools\Adapter\Stack as StackPool;
|
||||
use Utopia\Pools\Adapter\Swoole as SwoolePool;
|
||||
use Utopia\Mongo\Client as MongoClient;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\Pools\Pool;
|
||||
@@ -338,7 +340,9 @@ $register->set('pools', function () {
|
||||
default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'),
|
||||
};
|
||||
|
||||
$pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn, $key) {
|
||||
$poolAdapter = System::getEnv('_APP_POOL_ADAPTER', default: 'stack') === 'swoole' ? new SwoolePool() : new StackPool();
|
||||
|
||||
$pool = new Pool($poolAdapter, $name, $poolSize, function () use ($type, $resource, $dsn, $key) {
|
||||
// Get Adapter
|
||||
switch ($type) {
|
||||
case 'database':
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@
|
||||
"utopia-php/migration": "dev-multitype-db as 1.4.5",
|
||||
"utopia-php/orchestration": "0.9.*",
|
||||
"utopia-php/platform": "0.7.*",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
"utopia-php/pools": "1.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/queue": "0.15.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
|
||||
Generated
+40
-28
@@ -1361,15 +1361,19 @@
|
||||
{
|
||||
"name": "open-telemetry/exporter-otlp",
|
||||
"version": "1.3.4",
|
||||
"version": "1.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentelemetry-php/exporter-otlp.git",
|
||||
"reference": "62e680d587beb42e5247aa6ecd89ad1ca406e8ca"
|
||||
"reference": "62e680d587beb42e5247aa6ecd89ad1ca406e8ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/62e680d587beb42e5247aa6ecd89ad1ca406e8ca",
|
||||
"reference": "62e680d587beb42e5247aa6ecd89ad1ca406e8ca",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/62e680d587beb42e5247aa6ecd89ad1ca406e8ca",
|
||||
"reference": "62e680d587beb42e5247aa6ecd89ad1ca406e8ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1421,6 +1425,7 @@
|
||||
"source": "https://github.com/open-telemetry/opentelemetry-php"
|
||||
},
|
||||
"time": "2026-01-15T09:31:34+00:00"
|
||||
"time": "2026-01-15T09:31:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "open-telemetry/gen-otlp-protobuf",
|
||||
@@ -1488,15 +1493,19 @@
|
||||
{
|
||||
"name": "open-telemetry/sdk",
|
||||
"version": "1.11.0",
|
||||
"version": "1.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentelemetry-php/sdk.git",
|
||||
"reference": "d91f21addcdb42da9a451c002777f8318432461a"
|
||||
"reference": "d91f21addcdb42da9a451c002777f8318432461a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/d91f21addcdb42da9a451c002777f8318432461a",
|
||||
"reference": "d91f21addcdb42da9a451c002777f8318432461a",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/d91f21addcdb42da9a451c002777f8318432461a",
|
||||
"reference": "d91f21addcdb42da9a451c002777f8318432461a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1581,6 +1590,7 @@
|
||||
"source": "https://github.com/open-telemetry/opentelemetry-php"
|
||||
},
|
||||
"time": "2026-01-15T11:21:03+00:00"
|
||||
"time": "2026-01-15T11:21:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "open-telemetry/sem-conv",
|
||||
@@ -3721,16 +3731,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cache",
|
||||
"version": "0.13.2",
|
||||
"version": "0.13.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/cache.git",
|
||||
"reference": "5768498c9f451482f0bf3eede4d6452ddcd4a0f6"
|
||||
"reference": "355707ab2c0090435059216165db86976b68a126"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/cache/zipball/5768498c9f451482f0bf3eede4d6452ddcd4a0f6",
|
||||
"reference": "5768498c9f451482f0bf3eede4d6452ddcd4a0f6",
|
||||
"url": "https://api.github.com/repos/utopia-php/cache/zipball/355707ab2c0090435059216165db86976b68a126",
|
||||
"reference": "355707ab2c0090435059216165db86976b68a126",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3738,7 +3748,7 @@
|
||||
"ext-memcached": "*",
|
||||
"ext-redis": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
"utopia-php/pools": "1.*",
|
||||
"utopia-php/telemetry": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -3767,9 +3777,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/cache/issues",
|
||||
"source": "https://github.com/utopia-php/cache/tree/0.13.2"
|
||||
"source": "https://github.com/utopia-php/cache/tree/0.13.3"
|
||||
},
|
||||
"time": "2025-12-17T08:55:43+00:00"
|
||||
"time": "2026-01-16T07:54:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cli",
|
||||
@@ -3963,16 +3973,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "4.5.2",
|
||||
"version": "4.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23"
|
||||
"reference": "b5c16caf4f6b12fa2c04d5a48f6e5785c99da8df"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23",
|
||||
"reference": "8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/b5c16caf4f6b12fa2c04d5a48f6e5785c99da8df",
|
||||
"reference": "b5c16caf4f6b12fa2c04d5a48f6e5785c99da8df",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3983,7 +3993,7 @@
|
||||
"utopia-php/cache": "0.13.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/mongo": "0.11.*",
|
||||
"utopia-php/pools": "0.8.*"
|
||||
"utopia-php/pools": "1.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "1.23.*",
|
||||
@@ -4015,9 +4025,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/4.5.2"
|
||||
"source": "https://github.com/utopia-php/database/tree/4.6.0"
|
||||
},
|
||||
"time": "2026-01-15T04:23:30+00:00"
|
||||
"time": "2026-01-16T12:35:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
@@ -4815,16 +4825,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/pools",
|
||||
"version": "0.8.3",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/pools.git",
|
||||
"reference": "ad7d6ba946376e81c603204285ce9a674b6502b8"
|
||||
"reference": "74ba7dc985c2f629df8cf08ed95507955e3bcf86"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/pools/zipball/ad7d6ba946376e81c603204285ce9a674b6502b8",
|
||||
"reference": "ad7d6ba946376e81c603204285ce9a674b6502b8",
|
||||
"url": "https://api.github.com/repos/utopia-php/pools/zipball/74ba7dc985c2f629df8cf08ed95507955e3bcf86",
|
||||
"reference": "74ba7dc985c2f629df8cf08ed95507955e3bcf86",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4834,7 +4844,8 @@
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
"phpstan/phpstan": "1.*",
|
||||
"phpunit/phpunit": "11.*"
|
||||
"phpunit/phpunit": "11.*",
|
||||
"swoole/ide-helper": "5.1.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -4861,9 +4872,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/pools/issues",
|
||||
"source": "https://github.com/utopia-php/pools/tree/0.8.3"
|
||||
"source": "https://github.com/utopia-php/pools/tree/1.0.0"
|
||||
},
|
||||
"time": "2025-12-17T09:35:18+00:00"
|
||||
"time": "2026-01-15T12:34:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/preloader",
|
||||
@@ -4920,16 +4931,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/queue",
|
||||
"version": "0.15.0",
|
||||
"version": "0.15.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/queue.git",
|
||||
"reference": "6abb268ba7ec00dea4e5201b007776ea1bce9242"
|
||||
"reference": "e551606385990ec7901d222017c4cfc2749a518c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/6abb268ba7ec00dea4e5201b007776ea1bce9242",
|
||||
"reference": "6abb268ba7ec00dea4e5201b007776ea1bce9242",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/e551606385990ec7901d222017c4cfc2749a518c",
|
||||
"reference": "e551606385990ec7901d222017c4cfc2749a518c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4938,7 +4949,7 @@
|
||||
"utopia-php/console": "0.0.*",
|
||||
"utopia-php/fetch": "0.5.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
"utopia-php/pools": "1.*",
|
||||
"utopia-php/telemetry": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -4980,9 +4991,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/queue/issues",
|
||||
"source": "https://github.com/utopia-php/queue/tree/0.15.0"
|
||||
"source": "https://github.com/utopia-php/queue/tree/0.15.1"
|
||||
},
|
||||
"time": "2026-01-06T12:41:51+00:00"
|
||||
"time": "2026-01-16T07:54:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/registry",
|
||||
@@ -9111,4 +9122,5 @@
|
||||
"php": "8.3"
|
||||
},
|
||||
"plugin-api-version": "2.9.0"
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_LOGGING_CONFIG_REALTIME
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_POOL_ADAPTER=swoole
|
||||
|
||||
appwrite-worker-audits:
|
||||
entrypoint: worker-audits
|
||||
|
||||
@@ -1979,7 +1979,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
|
||||
$this->assertEquals(1, count($sessions));
|
||||
$this->assertEquals($sessionId2, $sessions[0]['$id']);
|
||||
});
|
||||
}, 120_000, 300);
|
||||
|
||||
/**
|
||||
* Reset Limit
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Realtime;
|
||||
|
||||
use CURLFile;
|
||||
use Exception;
|
||||
use Swoole\Coroutine;
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
@@ -3123,6 +3124,155 @@ class RealtimeCustomClientTest extends Scope
|
||||
|
||||
$client->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate concurrent realtime traffic using Swoole coroutines.
|
||||
* Opens multiple websocket clients concurrently, then performs create/update/delete ops.
|
||||
*/
|
||||
public function testConcurrentRealtimeTrafficCoroutines()
|
||||
{
|
||||
if (!class_exists(\Swoole\Coroutine::class)) {
|
||||
$this->markTestSkipped('Swoole Coroutine not available in this environment.');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$session = $user['session'] ?? '';
|
||||
$projectId = $this->getProject()['$id'];
|
||||
|
||||
Coroutine\run(function () use ($session, $projectId) {
|
||||
$headers = [
|
||||
'origin' => 'http://localhost',
|
||||
'cookie' => 'a_session_' . $projectId . '=' . $session
|
||||
];
|
||||
|
||||
$clientCount = 5;
|
||||
$clients = [];
|
||||
for ($i = 0; $i < $clientCount; $i++) {
|
||||
$clients[] = $this->getWebsocket(['documents', 'collections'], $headers);
|
||||
}
|
||||
|
||||
foreach ($clients as $client) {
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertEquals('connected', $response['type']);
|
||||
}
|
||||
|
||||
// Setup DB/collection/attribute
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Concurrent DB',
|
||||
]);
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Concurrent Collection',
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
'documentSecurity' => true,
|
||||
]);
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
$this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 64,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
Coroutine::sleep(1);
|
||||
|
||||
$creates = [
|
||||
['name' => 'Doc A'],
|
||||
['name' => 'Doc B'],
|
||||
['name' => 'Doc C'],
|
||||
['name' => 'Doc D'],
|
||||
['name' => 'Doc E'],
|
||||
['name' => 'Doc F'],
|
||||
];
|
||||
|
||||
$expectedEvents = count($creates);
|
||||
|
||||
// Per-client receipts
|
||||
$receivedEvents = array_fill(0, $clientCount, []);
|
||||
|
||||
// Launch receiver coroutines (one per client)
|
||||
foreach ($clients as $idx => $client) {
|
||||
Coroutine::create(function () use ($client, &$receivedEvents, $expectedEvents, $idx) {
|
||||
$local = [];
|
||||
for ($i = 0; $i < $expectedEvents; $i++) {
|
||||
$event = json_decode($client->receive(), true);
|
||||
$local[] = $event;
|
||||
}
|
||||
$receivedEvents[$idx] = $local;
|
||||
});
|
||||
}
|
||||
|
||||
// Create docs
|
||||
foreach ($creates as $payload) {
|
||||
$this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => $payload,
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
// Wait for receivers to collect; timeout ~10s
|
||||
$deadline = microtime(true) + 10;
|
||||
while (microtime(true) < $deadline) {
|
||||
$done = true;
|
||||
foreach ($receivedEvents as $events) {
|
||||
if (count($events) < $expectedEvents) {
|
||||
$done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($done) {
|
||||
break;
|
||||
}
|
||||
Coroutine::sleep(0.1);
|
||||
}
|
||||
|
||||
$expectedNames = array_column($creates, 'name');
|
||||
|
||||
for ($c = 0; $c < $clientCount; $c++) {
|
||||
$events = $receivedEvents[$c];
|
||||
$this->assertCount($expectedEvents, $events, 'Unexpected event count on client '.$c);
|
||||
$seen = [];
|
||||
foreach ($events as $event) {
|
||||
$this->assertEquals('event', $event['type']);
|
||||
$this->assertArrayHasKey('payload', $event['data']);
|
||||
$seen[] = $event['data']['payload']['name'] ?? '';
|
||||
}
|
||||
foreach ($expectedNames as $name) {
|
||||
$this->assertContains($name, $seen);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($clients as $client) {
|
||||
$client->close();
|
||||
}
|
||||
});
|
||||
}
|
||||
public function testChannelTablesDB()
|
||||
{
|
||||
$user = $this->getUser();
|
||||
|
||||
Reference in New Issue
Block a user