Skip to content

Commit 04b5ee9

Browse files
committed
perf: skip context data added in api-platform#5758
1 parent ef0ee64 commit 04b5ee9

File tree

4 files changed

+96
-9
lines changed

4 files changed

+96
-9
lines changed

src/GraphQl/Serializer/SerializerContextBuilder.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface;
2121
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
2222
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
23+
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
2324

2425
/**
2526
* Builds the context used by the Symfony Serializer.
@@ -53,6 +54,15 @@ public function create(?string $resourceClass, Operation $operation, array $reso
5354
$context['attributes'] = $this->fieldsToAttributes($resourceClass, $operation, $resolverContext, $context);
5455
}
5556

57+
// to keep the cache computation smaller, we have "operation_name" and "iri" anyways
58+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'root_operation';
59+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'operation';
60+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'object';
61+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'data';
62+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'property_metadata';
63+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'circular_reference_limit_counters';
64+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'debug_trace_id';
65+
5666
return $context;
5767
}
5868

src/GraphQl/Tests/Serializer/SerializerContextBuilderTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ public static function createNormalizationContextProvider(): iterable
141141
'id' => 3,
142142
'field' => 'foo',
143143
],
144+
'exclude_from_cache_key' => [
145+
'root_operation',
146+
'operation',
147+
'object',
148+
'data',
149+
'property_metadata',
150+
'circular_reference_limit_counters',
151+
'debug_trace_id',
152+
],
144153
],
145154
];
146155
yield 'nominal with advanced name converter' => [
@@ -161,6 +170,15 @@ public static function createNormalizationContextProvider(): iterable
161170
'id' => 3,
162171
'denormalizedField' => 'foo',
163172
],
173+
'exclude_from_cache_key' => [
174+
'root_operation',
175+
'operation',
176+
'object',
177+
'data',
178+
'property_metadata',
179+
'circular_reference_limit_counters',
180+
'debug_trace_id',
181+
],
164182
],
165183
$advancedNameConverterFactory,
166184
];
@@ -181,6 +199,15 @@ public static function createNormalizationContextProvider(): iterable
181199
'attributes' => [
182200
'nodeField' => 'baz',
183201
],
202+
'exclude_from_cache_key' => [
203+
'root_operation',
204+
'operation',
205+
'object',
206+
'data',
207+
'property_metadata',
208+
'circular_reference_limit_counters',
209+
'debug_trace_id',
210+
],
184211
],
185212
];
186213
yield 'no resource class' => [
@@ -197,6 +224,15 @@ public static function createNormalizationContextProvider(): iterable
197224
'attributes' => [
198225
'related' => ['id' => 9],
199226
],
227+
'exclude_from_cache_key' => [
228+
'root_operation',
229+
'operation',
230+
'object',
231+
'data',
232+
'property_metadata',
233+
'circular_reference_limit_counters',
234+
'debug_trace_id',
235+
],
200236
],
201237
];
202238
yield 'mutation' => [
@@ -217,6 +253,15 @@ public static function createNormalizationContextProvider(): iterable
217253
'id' => 7,
218254
'related' => ['field' => 'bar'],
219255
],
256+
'exclude_from_cache_key' => [
257+
'root_operation',
258+
'operation',
259+
'object',
260+
'data',
261+
'property_metadata',
262+
'circular_reference_limit_counters',
263+
'debug_trace_id',
264+
],
220265
],
221266
];
222267
yield 'subscription (using fields in context)' => [
@@ -238,6 +283,15 @@ public static function createNormalizationContextProvider(): iterable
238283
'id' => 7,
239284
'related' => ['field' => 'bar'],
240285
],
286+
'exclude_from_cache_key' => [
287+
'root_operation',
288+
'operation',
289+
'object',
290+
'data',
291+
'property_metadata',
292+
'circular_reference_limit_counters',
293+
'debug_trace_id',
294+
],
241295
],
242296
];
243297
}
@@ -268,6 +322,15 @@ public static function createDenormalizationContextProvider(): array
268322
'graphql_operation_name' => $operationName,
269323
'input' => ['class' => 'inputClass'],
270324
'output' => ['class' => 'outputClass'],
325+
'exclude_from_cache_key' => [
326+
'root_operation',
327+
'operation',
328+
'object',
329+
'data',
330+
'property_metadata',
331+
'circular_reference_limit_counters',
332+
'debug_trace_id',
333+
],
271334
],
272335
],
273336
'no resource class' => [
@@ -277,6 +340,15 @@ public static function createDenormalizationContextProvider(): array
277340
'resource_class' => $resourceClass,
278341
'operation_name' => $operationName,
279342
'graphql_operation_name' => $operationName,
343+
'exclude_from_cache_key' => [
344+
'root_operation',
345+
'operation',
346+
'object',
347+
'data',
348+
'property_metadata',
349+
'circular_reference_limit_counters',
350+
'debug_trace_id',
351+
],
280352
],
281353
],
282354
];

src/Serializer/SerializerContextBuilder.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ public function createFromRequest(Request $request, bool $normalization, ?array
113113
// to keep the cache computation smaller, we have "operation_name" and "iri" anyways
114114
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'root_operation';
115115
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'operation';
116+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'object';
117+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'data';
118+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'property_metadata';
119+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'circular_reference_limit_counters';
120+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'debug_trace_id';
116121

117122
// JSON API see JsonApiProvider
118123
if ($included = $request->attributes->get('_api_included')) {

src/Serializer/Tests/SerializerContextBuilderTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,42 +67,42 @@ public function testCreateFromRequest(): void
6767
{
6868
$request = Request::create('/foos/1');
6969
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
70-
$expected = ['foo' => 'bar', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
70+
$expected = ['foo' => 'bar', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
7171
$this->assertEquals($expected, $this->builder->createFromRequest($request, true));
7272

7373
$request = Request::create('/foos');
7474
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get_collection', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
75-
$expected = ['foo' => 'bar', 'operation_name' => 'get_collection', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection'), 'exclude_from_cache_key' => ['root_operation', 'operation']];
75+
$expected = ['foo' => 'bar', 'operation_name' => 'get_collection', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection'), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
7676
$this->assertEquals($expected, $this->builder->createFromRequest($request, true));
7777

7878
$request = Request::create('/foos/1');
7979
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
80-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
80+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
8181
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
8282

8383
$request = Request::create('/foos', 'POST');
8484
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
85-
$expected = ['bar' => 'baz', 'operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post'), 'exclude_from_cache_key' => ['root_operation', 'operation']];
85+
$expected = ['bar' => 'baz', 'operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post'), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
8686
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
8787

8888
$request = Request::create('/foos', 'PUT');
8989
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
90-
$expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => (new Put(name: 'put'))->withOperation($this->operation), 'exclude_from_cache_key' => ['root_operation', 'operation']];
90+
$expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => (new Put(name: 'put'))->withOperation($this->operation), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
9191
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
9292

9393
$request = Request::create('/bars/1/foos');
9494
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
95-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
95+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
9696
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
9797

9898
$request = Request::create('/foowithpatch/1', 'PATCH');
9999
$request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']);
100-
$expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
100+
$expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
101101
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
102102

103103
$request = Request::create('/bars/1/foos');
104104
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', 'id' => '1']);
105-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true, 'exclude_from_cache_key' => ['root_operation', 'operation']];
105+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
106106
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
107107
}
108108

@@ -115,7 +115,7 @@ public function testThrowExceptionOnInvalidRequest(): void
115115

116116
public function testReuseExistingAttributes(): void
117117
{
118-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
118+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
119119
$this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'operation_name' => 'get']));
120120
}
121121

0 commit comments

Comments
 (0)