mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 17:08:45 +00:00
Merge pull request #11007 from appwrite/new-pool-adapter
This commit is contained in:
commit
9d953f898d
9 changed files with 216 additions and 38 deletions
1
.env
1
.env
|
|
@ -130,3 +130,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
|
||||
|
|
@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \
|
|||
--no-plugins --no-scripts --prefer-dist \
|
||||
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`
|
||||
|
||||
FROM appwrite/base:0.10.6 AS base
|
||||
FROM appwrite/base:0.11.5 AS base
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,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\Pools\Group;
|
||||
use Utopia\Pools\Pool;
|
||||
use Utopia\Queue;
|
||||
|
|
@ -285,7 +287,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) {
|
||||
$poolAdapter = System::getEnv('_APP_POOL_ADAPTER', default: 'stack') === 'swoole' ? new SwoolePool() : new StackPool();
|
||||
|
||||
$pool = new Pool($poolAdapter, $name, $poolSize, function () use ($type, $resource, $dsn) {
|
||||
// Get Adapter
|
||||
switch ($type) {
|
||||
case 'database':
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
"ext-yaml": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-swoole": "*",
|
||||
"ext-swoole": "6.*",
|
||||
"ext-pdo": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-zlib": "*",
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
"utopia-php/migration": "1.*",
|
||||
"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.*",
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
"ext-fileinfo": "*",
|
||||
"appwrite/sdk-generator": "*",
|
||||
"phpunit/phpunit": "9.*",
|
||||
"swoole/ide-helper": "5.1.2",
|
||||
"swoole/ide-helper": "6.*",
|
||||
"phpstan/phpstan": "1.8.*",
|
||||
"textalk/websocket": "1.5.*",
|
||||
"laravel/pint": "1.*",
|
||||
|
|
|
|||
63
composer.lock
generated
63
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "33da844fdf5648d1d1a027dfb6ae42bc",
|
||||
"content-hash": "2aca1c8eeaa9fa338e389e3527cb6bd6",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -3719,16 +3719,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": {
|
||||
|
|
@ -3736,7 +3736,7 @@
|
|||
"ext-memcached": "*",
|
||||
"ext-redis": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
"utopia-php/pools": "1.*",
|
||||
"utopia-php/telemetry": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
@ -3765,9 +3765,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",
|
||||
|
|
@ -3981,7 +3981,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.*",
|
||||
|
|
@ -4796,16 +4796,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/pools",
|
||||
"version": "0.8.3",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/pools.git",
|
||||
"reference": "ad7d6ba946376e81c603204285ce9a674b6502b8"
|
||||
"reference": "b7d8dd00306cdd8bf3ff6f1dc90caeaf27dabeb1"
|
||||
},
|
||||
"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/b7d8dd00306cdd8bf3ff6f1dc90caeaf27dabeb1",
|
||||
"reference": "b7d8dd00306cdd8bf3ff6f1dc90caeaf27dabeb1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4815,7 +4815,8 @@
|
|||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
"phpstan/phpstan": "1.*",
|
||||
"phpunit/phpunit": "11.*"
|
||||
"phpunit/phpunit": "11.*",
|
||||
"swoole/ide-helper": "6.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -4842,9 +4843,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.2"
|
||||
},
|
||||
"time": "2025-12-17T09:35:18+00:00"
|
||||
"time": "2026-01-28T13:12:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/preloader",
|
||||
|
|
@ -4901,16 +4902,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": {
|
||||
|
|
@ -4919,7 +4920,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": {
|
||||
|
|
@ -4961,9 +4962,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",
|
||||
|
|
@ -8007,16 +8008,16 @@
|
|||
},
|
||||
{
|
||||
"name": "swoole/ide-helper",
|
||||
"version": "5.1.2",
|
||||
"version": "6.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/swoole/ide-helper.git",
|
||||
"reference": "33ec7af9111b76d06a70dd31191cc74793551112"
|
||||
"reference": "6f12243dce071714c5febe059578d909698f9a52"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/swoole/ide-helper/zipball/33ec7af9111b76d06a70dd31191cc74793551112",
|
||||
"reference": "33ec7af9111b76d06a70dd31191cc74793551112",
|
||||
"url": "https://api.github.com/repos/swoole/ide-helper/zipball/6f12243dce071714c5febe059578d909698f9a52",
|
||||
"reference": "6f12243dce071714c5febe059578d909698f9a52",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
|
|
@ -8033,9 +8034,9 @@
|
|||
"description": "IDE help files for Swoole.",
|
||||
"support": {
|
||||
"issues": "https://github.com/swoole/ide-helper/issues",
|
||||
"source": "https://github.com/swoole/ide-helper/tree/5.1.2"
|
||||
"source": "https://github.com/swoole/ide-helper/tree/6.0.2"
|
||||
},
|
||||
"time": "2024-02-01T22:28:11+00:00"
|
||||
"time": "2025-03-23T07:31:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
|
|
@ -9063,7 +9064,7 @@
|
|||
"ext-yaml": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-swoole": "*",
|
||||
"ext-swoole": "6.*",
|
||||
"ext-pdo": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-zlib": "*",
|
||||
|
|
@ -9075,5 +9076,5 @@
|
|||
"platform-overrides": {
|
||||
"php": "8.3"
|
||||
},
|
||||
"plugin-api-version": "2.9.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ services:
|
|||
- _APP_ENV
|
||||
- _APP_EDITION
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_LOCALE
|
||||
- _APP_COMPRESSION_ENABLED
|
||||
- _APP_COMPRESSION_MIN_SIZE_BYTES
|
||||
|
|
@ -301,6 +302,7 @@ services:
|
|||
- _APP_LOGGING_CONFIG
|
||||
- _APP_LOGGING_CONFIG_REALTIME
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_POOL_ADAPTER=swoole
|
||||
|
||||
appwrite-worker-audits:
|
||||
entrypoint: worker-audits
|
||||
|
|
@ -318,6 +320,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -349,6 +352,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_DB_HOST
|
||||
|
|
@ -386,6 +390,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -443,6 +448,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -477,6 +483,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
|
|
@ -550,6 +557,7 @@ services:
|
|||
# Basic
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
# Database
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
|
|
@ -607,6 +615,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
|
|
@ -649,6 +658,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
|
|
@ -692,6 +702,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
|
|
@ -726,6 +737,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -783,6 +795,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
|
|
@ -822,6 +835,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
|
|
@ -866,6 +880,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
|
|
@ -904,6 +919,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
|
|
@ -935,6 +951,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
|
|
@ -966,6 +983,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
|
|
@ -997,6 +1015,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -1025,6 +1044,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -1052,6 +1072,7 @@ services:
|
|||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
|
|||
|
|
@ -1870,7 +1870,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;
|
||||
|
|
@ -3122,4 +3123,153 @@ 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2409,7 +2409,8 @@ class SitesCustomServerTest extends Scope
|
|||
$this->assertEquals(301, $response['headers']['status-code']);
|
||||
$this->assertArrayHasKey('set-cookie', $response['headers']);
|
||||
$this->assertStringContainsString('a_jwt_console=', $response['headers']['set-cookie']);
|
||||
$this->assertStringContainsString('httponly', $response['headers']['set-cookie']);
|
||||
// due to swoole update; no more httponly
|
||||
$this->assertStringContainsString('HttpOnly', $response['headers']['set-cookie']);
|
||||
$this->assertStringContainsString('domain=' . $domain, $response['headers']['set-cookie']);
|
||||
$this->assertStringContainsString('path=/', $response['headers']['set-cookie']);
|
||||
$this->assertNotEmpty($response['cookies']['a_jwt_console']);
|
||||
|
|
|
|||
Loading…
Reference in a new issue