Skip to content

Commit 4f2f9fe

Browse files
committed
fix: resolve merge conflict keeping both lock and route restore
Merge conflict in Resolvers.php between the coroutine lock (fix/graphql-coroutine-safe-response) and the otel route restore (fix-gql-route-reset from 1.9.x). Both changes are needed: the lock serialises concurrent resolvers while the route restore prevents otel span clobbering.
2 parents d869c39 + 8fcba8b commit 4f2f9fe

26 files changed

Lines changed: 595 additions & 62 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ jobs:
512512
# Services that rely on sequential test method execution (shared static state)
513513
FUNCTIONAL_FLAG="--functional"
514514
case "${{ matrix.service }}" in
515-
Databases|TablesDB|Functions|Realtime) FUNCTIONAL_FLAG="" ;;
515+
Databases|TablesDB|Functions|Realtime|GraphQL) FUNCTIONAL_FLAG="" ;;
516516
esac
517517
518518
docker compose exec -T \

app/config/variables.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -872,18 +872,18 @@
872872
],
873873
[
874874
'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT',
875-
'description' => 'Deprecated since 1.7.0. The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.',
875+
'description' => 'Deprecated since 1.7.0. The maximum number of seconds allowed as a timeout value when building a new function. The default value is 2700 seconds.',
876876
'introduction' => '0.13.0',
877-
'default' => '900',
877+
'default' => '2700',
878878
'required' => false,
879879
'question' => '',
880880
'filter' => ''
881881
],
882882
[
883883
'name' => '_APP_COMPUTE_BUILD_TIMEOUT',
884-
'description' => 'The maximum number of seconds allowed as a timeout value when building a new function or site. The default value is 900 seconds.',
884+
'description' => 'The maximum number of seconds allowed as a timeout value when building a new function or site. The default value is 2700 seconds.',
885885
'introduction' => '1.7.0',
886-
'default' => '900',
886+
'default' => '2700',
887887
'required' => false,
888888
'question' => '',
889889
'filter' => ''

app/controllers/api/graphql.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ function execute(
231231
$validations = GraphQL::getStandardValidationRules();
232232

233233
if (System::getEnv('_APP_GRAPHQL_INTROSPECTION', 'enabled') === 'disabled') {
234-
$validations[] = new DisableIntrospection();
234+
$validations[] = new DisableIntrospection(DisableIntrospection::ENABLED);
235235
}
236236

237237
if (System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') {

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
"chillerlan/php-qrcode": "4.3.*",
9393
"adhocore/jwt": "1.1.*",
9494
"spomky-labs/otphp": "11.*",
95-
"webonyx/graphql-php": "14.11.*",
95+
"webonyx/graphql-php": "15.31.*",
9696
"league/csv": "9.14.*",
9797
"enshrined/svg-sanitize": "0.22.*"
9898
},

composer.lock

Lines changed: 34 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Appwrite/Bus/Listeners/Log.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use Appwrite\Event\Publisher\Execution as ExecutionPublisher;
88
use Utopia\Bus\Listener;
99
use Utopia\Database\Document;
10+
use Utopia\Span\Span;
11+
use Utopia\System\System;
1012

1113
class Log extends Listener
1214
{
@@ -30,9 +32,27 @@ public function __construct()
3032

3133
public function handle(ExecutionCompleted $event, ExecutionPublisher $publisherForExecutions): void
3234
{
35+
$project = new Document($event->project);
36+
$execution = new Document($event->execution);
37+
if ($execution->getAttribute('resourceType', '') === 'functions') {
38+
$traceProjectId = System::getEnv('_APP_TRACE_PROJECT_ID', '');
39+
$traceFunctionId = System::getEnv('_APP_TRACE_FUNCTION_ID', '');
40+
$resourceId = $execution->getAttribute('resourceId', '');
41+
if ($traceProjectId !== '' && $traceFunctionId !== '' && $project->getId() === $traceProjectId && $resourceId === $traceFunctionId) {
42+
Span::init('execution.trace.v1_executions_enqueue');
43+
Span::add('datetime', gmdate('c'));
44+
Span::add('projectId', $project->getId());
45+
Span::add('functionId', $resourceId);
46+
Span::add('executionId', $execution->getId());
47+
Span::add('deploymentId', $execution->getAttribute('deploymentId', ''));
48+
Span::add('status', $execution->getAttribute('status', ''));
49+
Span::current()?->finish();
50+
}
51+
}
52+
3353
$publisherForExecutions->enqueue(new ExecutionMessage(
34-
project: new Document($event->project),
35-
execution: new Document($event->execution),
54+
project: $project,
55+
execution: $execution,
3656
));
3757
}
3858
}

src/Appwrite/GraphQL/Promises/Adapter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ abstract public function createRejected(mixed $reason): GQLPromise;
8181
/**
8282
* Create a new promise that resolves when all passed in promises resolve.
8383
*
84-
* @param array $promisesOrValues
84+
* @param iterable $promisesOrValues
8585
* @return GQLPromise
8686
*/
87-
abstract public function all(array $promisesOrValues): GQLPromise;
87+
abstract public function all(iterable $promisesOrValues): GQLPromise;
8888
}

src/Appwrite/GraphQL/Promises/Adapter/Swoole.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ public function createRejected($reason): GQLPromise
3535
return new GQLPromise($promise, $this);
3636
}
3737

38-
public function all(array $promisesOrValues): GQLPromise
38+
public function all(iterable $promisesOrValues): GQLPromise
3939
{
40+
if ($promisesOrValues instanceof \Traversable) {
41+
$promisesOrValues = \iterator_to_array($promisesOrValues);
42+
}
43+
4044
return new GQLPromise(SwoolePromise::all($promisesOrValues), $this);
4145
}
4246
}

src/Appwrite/GraphQL/Resolvers.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ private static function resolve(
420420
$lock = self::getLock($utopia);
421421

422422
self::acquireLock($lock);
423+
424+
$original = $utopia->getRoute();
423425
try {
424426
$request = clone $request;
425427

@@ -461,6 +463,10 @@ private static function resolve(
461463
$reject($e);
462464
return;
463465
} finally {
466+
if ($original !== null) {
467+
$utopia->setRoute($original);
468+
}
469+
464470
self::releaseLock($lock);
465471
}
466472

src/Appwrite/GraphQL/Types/Assoc.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
namespace Appwrite\GraphQL\Types;
44

55
use GraphQL\Language\AST\Node;
6+
use GraphQL\Language\AST\StringValueNode;
67

78
// https://github.com/webonyx/graphql-php/issues/129#issuecomment-309366803
89
class Assoc extends Json
910
{
10-
public $name = 'Assoc';
11-
public $description = 'The `Assoc` scalar type represents associative array values.';
11+
public string $name = 'Assoc';
12+
public ?string $description = 'The `Assoc` scalar type represents associative array values.';
1213

1314
public function serialize($value)
1415
{
@@ -30,6 +31,10 @@ public function parseValue($value)
3031

3132
public function parseLiteral(Node $valueNode, ?array $variables = null)
3233
{
33-
return \json_decode($valueNode->value, true);
34+
if ($valueNode instanceof StringValueNode) {
35+
return \json_decode($valueNode->value, true);
36+
}
37+
38+
return parent::parseLiteral($valueNode, $variables);
3439
}
3540
}

0 commit comments

Comments
 (0)