@apollo/gateway 2.0.0-preview.0 → 2.0.0-preview.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__generated__/graphqlTypes.d.ts +1 -0
- package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
- package/dist/config.d.ts +8 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts.map +1 -1
- package/dist/supergraphManagers/LegacyFetcher/index.d.ts +1 -1
- package/dist/supergraphManagers/LegacyFetcher/index.d.ts.map +1 -1
- package/dist/supergraphManagers/LocalCompose/index.d.ts +1 -1
- package/dist/supergraphManagers/LocalCompose/index.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/index.d.ts +4 -2
- package/dist/supergraphManagers/UplinkFetcher/index.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/index.js +20 -4
- package/dist/supergraphManagers/UplinkFetcher/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts +3 -2
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js +9 -3
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js.map +1 -1
- package/package.json +7 -7
- package/src/__generated__/graphqlTypes.ts +1 -1
- package/src/__tests__/buildQueryPlan.test.ts +51 -4
- package/src/__tests__/execution-utils.ts +3 -2
- package/src/__tests__/gateway/executor.test.ts +1 -1
- package/src/__tests__/gateway/lifecycle-hooks.test.ts +5 -5
- package/src/__tests__/gateway/reporting.test.ts +5 -0
- package/src/__tests__/gateway/supergraphSdl.test.ts +1 -1
- package/src/__tests__/integration/complex-key.test.ts +1 -6
- package/src/__tests__/integration/configuration.test.ts +1 -12
- package/src/__tests__/integration/logger.test.ts +1 -1
- package/src/__tests__/integration/networkRequests.test.ts +1 -1
- package/src/config.ts +13 -10
- package/src/core/__tests__/core.test.ts +8 -8
- package/src/index.ts +13 -7
- package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +1 -1
- package/src/supergraphManagers/IntrospectAndCompose/index.ts +1 -1
- package/src/supergraphManagers/LegacyFetcher/index.ts +1 -1
- package/src/supergraphManagers/LocalCompose/index.ts +1 -1
- package/src/supergraphManagers/UplinkFetcher/__tests__/loadSupergraphSdlFromStorage.test.ts +41 -0
- package/src/supergraphManagers/UplinkFetcher/index.ts +38 -19
- package/src/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts +9 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
astSerializer,
|
|
3
|
+
queryPlanSerializer,
|
|
4
|
+
} from 'apollo-federation-integration-testsuite';
|
|
2
5
|
import { getFederatedTestingSchema } from './execution-utils';
|
|
3
6
|
import { QueryPlan, QueryPlanner } from '@apollo/query-planner';
|
|
4
7
|
import { Schema, parseOperation } from '@apollo/federation-internals';
|
|
@@ -6,14 +9,13 @@ import { Schema, parseOperation } from '@apollo/federation-internals';
|
|
|
6
9
|
expect.addSnapshotSerializer(astSerializer);
|
|
7
10
|
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
8
11
|
|
|
9
|
-
|
|
10
12
|
describe('buildQueryPlan', () => {
|
|
11
13
|
let schema: Schema;
|
|
12
14
|
let queryPlanner: QueryPlanner;
|
|
13
15
|
|
|
14
16
|
const buildPlan = (operation: string): QueryPlan => {
|
|
15
17
|
return queryPlanner.buildQueryPlan(parseOperation(schema, operation));
|
|
16
|
-
}
|
|
18
|
+
};
|
|
17
19
|
|
|
18
20
|
beforeEach(() => {
|
|
19
21
|
expect(
|
|
@@ -515,7 +517,7 @@ describe('buildQueryPlan', () => {
|
|
|
515
517
|
|
|
516
518
|
describe(`when requesting a composite field with subfields from another service`, () => {
|
|
517
519
|
it(`should add key fields to the parent selection set and use a dependent fetch`, () => {
|
|
518
|
-
|
|
520
|
+
const operationString = `#graphql
|
|
519
521
|
query {
|
|
520
522
|
topReviews {
|
|
521
523
|
body
|
|
@@ -1171,4 +1173,49 @@ describe('buildQueryPlan', () => {
|
|
|
1171
1173
|
`);
|
|
1172
1174
|
});
|
|
1173
1175
|
});
|
|
1176
|
+
|
|
1177
|
+
describe('overridden fields and type', () => {
|
|
1178
|
+
it(`query plan of overridden field`, () => {
|
|
1179
|
+
const operationString = `#graphql
|
|
1180
|
+
query {
|
|
1181
|
+
library (id: "3") {
|
|
1182
|
+
name
|
|
1183
|
+
description
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
`;
|
|
1187
|
+
|
|
1188
|
+
const queryPlan = buildPlan(operationString);
|
|
1189
|
+
expect(queryPlan).toMatchInlineSnapshot(`
|
|
1190
|
+
QueryPlan {
|
|
1191
|
+
Sequence {
|
|
1192
|
+
Fetch(service: "books") {
|
|
1193
|
+
{
|
|
1194
|
+
library(id: 3) {
|
|
1195
|
+
__typename
|
|
1196
|
+
id
|
|
1197
|
+
name
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
Flatten(path: "library") {
|
|
1202
|
+
Fetch(service: "accounts") {
|
|
1203
|
+
{
|
|
1204
|
+
... on Library {
|
|
1205
|
+
__typename
|
|
1206
|
+
id
|
|
1207
|
+
}
|
|
1208
|
+
} =>
|
|
1209
|
+
{
|
|
1210
|
+
... on Library {
|
|
1211
|
+
description
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
},
|
|
1215
|
+
},
|
|
1216
|
+
},
|
|
1217
|
+
}
|
|
1218
|
+
`);
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1174
1221
|
});
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
GraphQLSchemaModule,
|
|
4
4
|
GraphQLResolverMap,
|
|
5
5
|
} from '../schema-helper';
|
|
6
|
-
import { GraphQLRequest, GraphQLExecutionResult
|
|
6
|
+
import { GraphQLRequest, GraphQLExecutionResult } from 'apollo-server-types';
|
|
7
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
7
8
|
import { buildSubgraphSchema } from '@apollo/subgraph';
|
|
8
9
|
import {
|
|
9
10
|
executeQueryPlan,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
} from '@apollo/gateway';
|
|
12
13
|
import { QueryPlan, QueryPlanner } from '@apollo/query-planner';
|
|
13
14
|
import { LocalGraphQLDataSource } from '../datasources/LocalGraphQLDataSource';
|
|
14
|
-
import { mergeDeep } from 'apollo
|
|
15
|
+
import { mergeDeep } from '@apollo/client/utilities';
|
|
15
16
|
|
|
16
17
|
import { queryPlanSerializer, astSerializer } from 'apollo-federation-integration-testsuite';
|
|
17
18
|
import gql from 'graphql-tag';
|
|
@@ -2,7 +2,7 @@ import { fetch } from '../../__mocks__/make-fetch-happen-fetcher';
|
|
|
2
2
|
import gql from 'graphql-tag';
|
|
3
3
|
import { ApolloGateway } from '../../';
|
|
4
4
|
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
5
|
-
import { Logger } from 'apollo
|
|
5
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
6
6
|
|
|
7
7
|
let logger: {
|
|
8
8
|
warn: jest.MockedFunction<Logger['warn']>,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
fixtures,
|
|
17
17
|
fixturesWithUpdate,
|
|
18
18
|
} from 'apollo-federation-integration-testsuite';
|
|
19
|
-
import { Logger } from 'apollo
|
|
19
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
20
20
|
import resolvable from '@josephg/resolvable';
|
|
21
21
|
import { createHash } from '../../utilities/createHash';
|
|
22
22
|
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
@@ -137,7 +137,7 @@ describe('lifecycle hooks', () => {
|
|
|
137
137
|
|
|
138
138
|
const [firstCall, secondCall] = mockDidUpdate.mock.calls;
|
|
139
139
|
|
|
140
|
-
// Note that we've composing our usual test fixtures here
|
|
140
|
+
// Note that we've composing our usual test fixtures here
|
|
141
141
|
const expectedFirstId = createHash('sha256').update(getTestingSupergraphSdl()).digest('hex');
|
|
142
142
|
expect(firstCall[0]!.compositionId).toEqual(expectedFirstId);
|
|
143
143
|
// first call should have no second "previous" argument
|
|
@@ -145,9 +145,9 @@ describe('lifecycle hooks', () => {
|
|
|
145
145
|
|
|
146
146
|
// Note that this assertion is a tad fragile in that every time we modify
|
|
147
147
|
// the supergraph (even just formatting differences), this ID will change
|
|
148
|
-
// and this test will have to updated.
|
|
148
|
+
// and this test will have to updated.
|
|
149
149
|
expect(secondCall[0]!.compositionId).toEqual(
|
|
150
|
-
'
|
|
150
|
+
'730a2fe4036db8e2c847096ba2a62f78ff8f3c08c9ee092a5b1b37e1aa00ef5a',
|
|
151
151
|
);
|
|
152
152
|
// second call should have previous info in the second arg
|
|
153
153
|
expect(secondCall[1]!.compositionId).toEqual(expectedFirstId);
|
|
@@ -183,7 +183,7 @@ describe('lifecycle hooks', () => {
|
|
|
183
183
|
);
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
-
it('registers schema change callbacks when
|
|
186
|
+
it('registers schema change callbacks when pollIntervalInMs is set for unmanaged configs', async () => {
|
|
187
187
|
const experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions =
|
|
188
188
|
jest.fn(async (_config) => {
|
|
189
189
|
return { serviceDefinitions, isNewSchema: true };
|
|
@@ -229,6 +229,7 @@ describe('reporting', () => {
|
|
|
229
229
|
"seconds": "1562203363",
|
|
230
230
|
},
|
|
231
231
|
"header": "<HEADER>",
|
|
232
|
+
"operationCount": 1,
|
|
232
233
|
"tracesPerQuery": Object {
|
|
233
234
|
"# -
|
|
234
235
|
{me{name{first last}}topProducts{name}}": Object {
|
|
@@ -301,6 +302,7 @@ describe('reporting', () => {
|
|
|
301
302
|
"nanos": 123000000,
|
|
302
303
|
"seconds": "1562203363",
|
|
303
304
|
},
|
|
305
|
+
"fieldExecutionWeight": 1,
|
|
304
306
|
"root": Object {
|
|
305
307
|
"child": Array [
|
|
306
308
|
Object {
|
|
@@ -366,6 +368,7 @@ describe('reporting', () => {
|
|
|
366
368
|
"nanos": 123000000,
|
|
367
369
|
"seconds": "1562203363",
|
|
368
370
|
},
|
|
371
|
+
"fieldExecutionWeight": 1,
|
|
369
372
|
"root": Object {
|
|
370
373
|
"child": Array [
|
|
371
374
|
Object {
|
|
@@ -467,6 +470,7 @@ describe('reporting', () => {
|
|
|
467
470
|
"nanos": 123000000,
|
|
468
471
|
"seconds": "1562203363",
|
|
469
472
|
},
|
|
473
|
+
"fieldExecutionWeight": 1,
|
|
470
474
|
"root": Object {
|
|
471
475
|
"child": Array [
|
|
472
476
|
Object {
|
|
@@ -556,6 +560,7 @@ describe('reporting', () => {
|
|
|
556
560
|
"nanos": 123000000,
|
|
557
561
|
"seconds": "1562203363",
|
|
558
562
|
},
|
|
563
|
+
"fieldExecutionWeight": 1,
|
|
559
564
|
"root": Object {
|
|
560
565
|
"child": Array [
|
|
561
566
|
Object {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import { fixturesWithUpdate } from 'apollo-federation-integration-testsuite';
|
|
8
8
|
import { createHash } from '../../utilities/createHash';
|
|
9
9
|
import { ApolloServer } from 'apollo-server';
|
|
10
|
-
import { Logger } from 'apollo
|
|
10
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
11
11
|
import { fetch } from '../../__mocks__/make-fetch-happen-fetcher';
|
|
12
12
|
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
13
13
|
import { mockAllServicesHealthCheckSuccess } from '../integration/nockMocks';
|
|
@@ -91,12 +91,7 @@ const userService: ServiceDefinitionModule = {
|
|
|
91
91
|
);
|
|
92
92
|
},
|
|
93
93
|
organization(user) {
|
|
94
|
-
return
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
Organization: {
|
|
98
|
-
__resolveObject(object) {
|
|
99
|
-
return organizations.find(org => org.id === object.id);
|
|
94
|
+
return organizations.find(org => org.id === user.organizationId);
|
|
100
95
|
},
|
|
101
96
|
},
|
|
102
97
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import gql from 'graphql-tag';
|
|
2
2
|
import http from 'http';
|
|
3
3
|
import mockedEnv from 'mocked-env';
|
|
4
|
-
import { Logger } from 'apollo
|
|
4
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
5
5
|
import { ApolloGateway } from '../..';
|
|
6
6
|
import {
|
|
7
7
|
mockSdlQuerySuccess,
|
|
@@ -444,15 +444,4 @@ describe('deprecation warnings', () => {
|
|
|
444
444
|
'The `schemaConfigDeliveryEndpoint` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to the equivalent (array form) `uplinkEndpoints` configuration option.',
|
|
445
445
|
);
|
|
446
446
|
});
|
|
447
|
-
|
|
448
|
-
it('warns with `experimental_pollInterval` option set', async () => {
|
|
449
|
-
new ApolloGateway({
|
|
450
|
-
experimental_pollInterval: 10000,
|
|
451
|
-
logger,
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
455
|
-
'The `experimental_pollInterval` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to the equivalent `pollIntervalInMs` configuration option.',
|
|
456
|
-
);
|
|
457
|
-
});
|
|
458
447
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import gql from 'graphql-tag';
|
|
2
2
|
import { GraphQLObjectType, GraphQLSchema } from 'graphql';
|
|
3
3
|
import mockedEnv from 'mocked-env';
|
|
4
|
-
import { Logger } from 'apollo
|
|
4
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
5
5
|
import { ApolloGateway } from '../..';
|
|
6
6
|
import {
|
|
7
7
|
mockSdlQuerySuccess,
|
package/src/config.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { GraphQLError, GraphQLSchema } from 'graphql';
|
|
2
2
|
import { HeadersInit } from 'node-fetch';
|
|
3
3
|
import { fetch } from 'apollo-server-env';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
Logger,
|
|
7
|
-
} from 'apollo-server-types';
|
|
4
|
+
import { GraphQLRequestContextExecutionDidStart } from 'apollo-server-types';
|
|
5
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
8
6
|
import { GraphQLDataSource } from './datasources/types';
|
|
9
7
|
import { QueryPlan } from '@apollo/query-planner';
|
|
10
8
|
import { OperationContext } from './operationContext';
|
|
@@ -81,6 +79,7 @@ export interface ServiceDefinitionUpdate {
|
|
|
81
79
|
export interface SupergraphSdlUpdate {
|
|
82
80
|
id: string;
|
|
83
81
|
supergraphSdl: string;
|
|
82
|
+
minDelaySeconds?: number;
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
export function isSupergraphSdlUpdate(
|
|
@@ -125,11 +124,6 @@ interface GatewayConfigBase {
|
|
|
125
124
|
// experimental observability callbacks
|
|
126
125
|
experimental_didResolveQueryPlan?: Experimental_DidResolveQueryPlanCallback;
|
|
127
126
|
experimental_didUpdateSupergraph?: Experimental_DidUpdateSupergraphCallback;
|
|
128
|
-
/**
|
|
129
|
-
* @deprecated use `pollIntervalInMs` instead
|
|
130
|
-
*/
|
|
131
|
-
experimental_pollInterval?: number;
|
|
132
|
-
pollIntervalInMs?: number;
|
|
133
127
|
experimental_approximateQueryPlanStoreMiB?: number;
|
|
134
128
|
experimental_autoFragmentization?: boolean;
|
|
135
129
|
fetcher?: typeof fetch;
|
|
@@ -150,6 +144,7 @@ export interface ServiceListGatewayConfig extends GatewayConfigBase {
|
|
|
150
144
|
| ((
|
|
151
145
|
service: ServiceEndpointDefinition,
|
|
152
146
|
) => Promise<HeadersInit> | HeadersInit);
|
|
147
|
+
pollIntervalInMs?: number;
|
|
153
148
|
}
|
|
154
149
|
|
|
155
150
|
export interface ManagedGatewayConfig extends GatewayConfigBase {
|
|
@@ -168,6 +163,11 @@ export interface ManagedGatewayConfig extends GatewayConfigBase {
|
|
|
168
163
|
*/
|
|
169
164
|
uplinkEndpoints?: string[];
|
|
170
165
|
uplinkMaxRetries?: number;
|
|
166
|
+
/**
|
|
167
|
+
* @deprecated use `fallbackPollIntervalInMs` instead
|
|
168
|
+
*/
|
|
169
|
+
pollIntervalInMs?: number;
|
|
170
|
+
fallbackPollIntervalInMs?: number;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
// TODO(trevor:removeServiceList): migrate users to `supergraphSdl` function option
|
|
@@ -176,6 +176,7 @@ interface ManuallyManagedServiceDefsGatewayConfig extends GatewayConfigBase {
|
|
|
176
176
|
* @deprecated: use `supergraphSdl` instead (either as a `SupergraphSdlHook` or `SupergraphManager`)
|
|
177
177
|
*/
|
|
178
178
|
experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions;
|
|
179
|
+
pollIntervalInMs?: number;
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
// TODO(trevor:removeServiceList): migrate users to `supergraphSdl` function option
|
|
@@ -185,6 +186,7 @@ interface ExperimentalManuallyManagedSupergraphSdlGatewayConfig
|
|
|
185
186
|
* @deprecated: use `supergraphSdl` instead (either as a `SupergraphSdlHook` or `SupergraphManager`)
|
|
186
187
|
*/
|
|
187
188
|
experimental_updateSupergraphSdl: Experimental_UpdateSupergraphSdl;
|
|
189
|
+
pollIntervalInMs?: number;
|
|
188
190
|
}
|
|
189
191
|
|
|
190
192
|
export function isManuallyManagedSupergraphSdlGatewayConfig(
|
|
@@ -238,7 +240,7 @@ type ManuallyManagedGatewayConfig =
|
|
|
238
240
|
| ManuallyManagedServiceDefsGatewayConfig
|
|
239
241
|
| ExperimentalManuallyManagedSupergraphSdlGatewayConfig
|
|
240
242
|
| ManuallyManagedSupergraphSdlGatewayConfig
|
|
241
|
-
// TODO(trevor:removeServiceList
|
|
243
|
+
// TODO(trevor:removeServiceList)
|
|
242
244
|
| ServiceListGatewayConfig;
|
|
243
245
|
|
|
244
246
|
// TODO(trevor:removeServiceList)
|
|
@@ -322,6 +324,7 @@ export function isManagedConfig(
|
|
|
322
324
|
return (
|
|
323
325
|
'schemaConfigDeliveryEndpoint' in config ||
|
|
324
326
|
'uplinkEndpoints' in config ||
|
|
327
|
+
'fallbackPollIntervalInMs' in config ||
|
|
325
328
|
(!isLocalConfig(config) &&
|
|
326
329
|
!isStaticSupergraphSdlConfig(config) &&
|
|
327
330
|
!isManuallyManagedConfig(config))
|
|
@@ -31,7 +31,7 @@ describe('core v0.1', () => {
|
|
|
31
31
|
|
|
32
32
|
directive @tag(
|
|
33
33
|
name: String!
|
|
34
|
-
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
|
|
34
|
+
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
|
35
35
|
|
|
36
36
|
enum CacheControlScope {
|
|
37
37
|
PRIVATE
|
|
@@ -87,7 +87,7 @@ describe('core v0.1', () => {
|
|
|
87
87
|
|
|
88
88
|
directive @tag(
|
|
89
89
|
name: String!
|
|
90
|
-
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
|
|
90
|
+
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
|
91
91
|
|
|
92
92
|
enum CacheControlScope {
|
|
93
93
|
PRIVATE
|
|
@@ -124,7 +124,7 @@ describe('core v0.2', () => {
|
|
|
124
124
|
schema
|
|
125
125
|
@core(feature: "https://specs.apollo.dev/core/v0.2")
|
|
126
126
|
@core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
|
|
127
|
-
@core(feature: "https://specs.apollo.dev/tag/v0.
|
|
127
|
+
@core(feature: "https://specs.apollo.dev/tag/v0.2") {
|
|
128
128
|
query: Query
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -151,7 +151,7 @@ describe('core v0.2', () => {
|
|
|
151
151
|
|
|
152
152
|
directive @tag(
|
|
153
153
|
name: String!
|
|
154
|
-
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
|
|
154
|
+
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
|
155
155
|
|
|
156
156
|
enum CacheControlScope {
|
|
157
157
|
PRIVATE
|
|
@@ -193,7 +193,7 @@ describe('core v0.2', () => {
|
|
|
193
193
|
schema
|
|
194
194
|
@core(feature: "https://specs.apollo.dev/core/v0.2")
|
|
195
195
|
@core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
|
|
196
|
-
@core(feature: "https://specs.apollo.dev/tag/v0.
|
|
196
|
+
@core(feature: "https://specs.apollo.dev/tag/v0.2")
|
|
197
197
|
@core(feature: "https://specs.apollo.dev/unsupported-feature/v0.1") {
|
|
198
198
|
query: Query
|
|
199
199
|
}
|
|
@@ -221,7 +221,7 @@ describe('core v0.2', () => {
|
|
|
221
221
|
|
|
222
222
|
directive @tag(
|
|
223
223
|
name: String!
|
|
224
|
-
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
|
|
224
|
+
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
|
225
225
|
|
|
226
226
|
enum CacheControlScope {
|
|
227
227
|
PRIVATE
|
|
@@ -293,7 +293,7 @@ describe('core v0.2', () => {
|
|
|
293
293
|
|
|
294
294
|
directive @tag(
|
|
295
295
|
name: String!
|
|
296
|
-
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
|
|
296
|
+
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
|
297
297
|
|
|
298
298
|
enum CacheControlScope {
|
|
299
299
|
PRIVATE
|
|
@@ -369,7 +369,7 @@ describe('core v0.2', () => {
|
|
|
369
369
|
|
|
370
370
|
directive @tag(
|
|
371
371
|
name: String!
|
|
372
|
-
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
|
|
372
|
+
) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
|
373
373
|
|
|
374
374
|
enum CacheControlScope {
|
|
375
375
|
PRIVATE
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { deprecate } from 'util';
|
|
|
2
2
|
import { GraphQLService, Unsubscriber } from 'apollo-server-core';
|
|
3
3
|
import {
|
|
4
4
|
GraphQLExecutionResult,
|
|
5
|
-
Logger,
|
|
6
5
|
GraphQLRequestContextExecutionDidStart,
|
|
7
6
|
} from 'apollo-server-types';
|
|
7
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
8
8
|
import { InMemoryLRUCache } from 'apollo-server-caching';
|
|
9
9
|
import {
|
|
10
10
|
isObjectType,
|
|
@@ -200,8 +200,12 @@ export class ApolloGateway implements GraphQLService {
|
|
|
200
200
|
this.experimental_didUpdateSupergraph =
|
|
201
201
|
config?.experimental_didUpdateSupergraph;
|
|
202
202
|
|
|
203
|
-
this.
|
|
204
|
-
|
|
203
|
+
if (isManagedConfig(this.config)) {
|
|
204
|
+
this.pollIntervalInMs =
|
|
205
|
+
this.config.fallbackPollIntervalInMs ?? this.config.pollIntervalInMs;
|
|
206
|
+
} else if (isServiceListConfig(this.config)) {
|
|
207
|
+
this.pollIntervalInMs = this.config?.pollIntervalInMs;
|
|
208
|
+
}
|
|
205
209
|
|
|
206
210
|
this.issueConfigurationWarningsIfApplicable();
|
|
207
211
|
|
|
@@ -252,7 +256,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
252
256
|
'Polling Apollo services at a frequency of less than once per 10 ' +
|
|
253
257
|
'seconds (10000) is disallowed. Instead, the minimum allowed ' +
|
|
254
258
|
'pollInterval of 10000 will be used. Please reconfigure your ' +
|
|
255
|
-
'`
|
|
259
|
+
'`fallbackPollIntervalInMs` accordingly. If this is problematic for ' +
|
|
256
260
|
'your team, please contact support.',
|
|
257
261
|
);
|
|
258
262
|
}
|
|
@@ -286,9 +290,11 @@ export class ApolloGateway implements GraphQLService {
|
|
|
286
290
|
);
|
|
287
291
|
}
|
|
288
292
|
|
|
289
|
-
if ('
|
|
293
|
+
if (isManagedConfig(this.config) && 'pollIntervalInMs' in this.config) {
|
|
290
294
|
this.logger.warn(
|
|
291
|
-
'The `
|
|
295
|
+
'The `pollIntervalInMs` option is deprecated and will be removed in a future version of `@apollo/gateway`. ' +
|
|
296
|
+
'Please migrate to the equivalent `fallbackPollIntervalInMs` configuration option. ' +
|
|
297
|
+
'The poll interval is now defined by Uplink, this option will only be used if it is greater than the value defined by Uplink or as a fallback.',
|
|
292
298
|
);
|
|
293
299
|
}
|
|
294
300
|
}
|
|
@@ -406,7 +412,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
406
412
|
subgraphHealthCheck: this.config.serviceHealthCheck,
|
|
407
413
|
fetcher: this.fetcher,
|
|
408
414
|
logger: this.logger,
|
|
409
|
-
|
|
415
|
+
fallbackPollIntervalInMs: this.pollIntervalInMs ?? 10000,
|
|
410
416
|
}),
|
|
411
417
|
);
|
|
412
418
|
}
|
|
@@ -9,7 +9,7 @@ import { IntrospectAndCompose } from '..';
|
|
|
9
9
|
import { mockAllServicesSdlQuerySuccess } from '../../../__tests__/integration/nockMocks';
|
|
10
10
|
import { getTestingSupergraphSdl, wait } from '../../../__tests__/execution-utils';
|
|
11
11
|
import resolvable from '@josephg/resolvable';
|
|
12
|
-
import { Logger } from 'apollo
|
|
12
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
13
13
|
|
|
14
14
|
describe('IntrospectAndCompose', () => {
|
|
15
15
|
beforeEach(nockBeforeEach);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* configuration options of the gateway and will be removed in a future release
|
|
5
5
|
* along with those options.
|
|
6
6
|
*/
|
|
7
|
-
import { Logger } from 'apollo
|
|
7
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
8
8
|
import resolvable from '@josephg/resolvable';
|
|
9
9
|
import {
|
|
10
10
|
SupergraphManager,
|
|
@@ -65,6 +65,7 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
65
65
|
compositionId: "originalId-1234",
|
|
66
66
|
maxRetries: 1,
|
|
67
67
|
roundRobinSeed: 0,
|
|
68
|
+
earliestFetchTime: null,
|
|
68
69
|
});
|
|
69
70
|
|
|
70
71
|
expect(result).toMatchObject({
|
|
@@ -88,6 +89,7 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
88
89
|
compositionId: "originalId-1234",
|
|
89
90
|
maxRetries: 1,
|
|
90
91
|
roundRobinSeed: 0,
|
|
92
|
+
earliestFetchTime: null,
|
|
91
93
|
}),
|
|
92
94
|
).rejects.toThrowError(
|
|
93
95
|
new UplinkFetcherError(
|
|
@@ -388,10 +390,49 @@ describe("loadSupergraphSdlFromUplinks", () => {
|
|
|
388
390
|
compositionId: "id-1234",
|
|
389
391
|
maxRetries: 5,
|
|
390
392
|
roundRobinSeed: 0,
|
|
393
|
+
earliestFetchTime: null,
|
|
391
394
|
});
|
|
392
395
|
|
|
393
396
|
expect(result).toBeNull();
|
|
394
397
|
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
395
398
|
});
|
|
399
|
+
|
|
400
|
+
it("Waits the correct time before retrying", async () => {
|
|
401
|
+
const timeoutSpy = jest.spyOn(global, 'setTimeout');
|
|
402
|
+
|
|
403
|
+
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
|
|
404
|
+
mockSupergraphSdlRequestIfAfter('originalId-1234', mockCloudConfigUrl2).reply(
|
|
405
|
+
200,
|
|
406
|
+
JSON.stringify({
|
|
407
|
+
data: {
|
|
408
|
+
routerConfig: {
|
|
409
|
+
__typename: 'RouterConfigResult',
|
|
410
|
+
id: 'originalId-1234',
|
|
411
|
+
supergraphSdl: getTestingSupergraphSdl()
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
}),
|
|
415
|
+
);
|
|
416
|
+
const fetcher = getDefaultFetcher();
|
|
417
|
+
|
|
418
|
+
await loadSupergraphSdlFromUplinks({
|
|
419
|
+
graphRef,
|
|
420
|
+
apiKey,
|
|
421
|
+
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
422
|
+
errorReportingEndpoint: undefined,
|
|
423
|
+
fetcher: fetcher,
|
|
424
|
+
compositionId: "originalId-1234",
|
|
425
|
+
maxRetries: 1,
|
|
426
|
+
roundRobinSeed: 0,
|
|
427
|
+
earliestFetchTime: new Date(Date.now() + 1000),
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// test if setTimeout was called with a value in range to deal with time jitter
|
|
431
|
+
const setTimeoutCall = timeoutSpy.mock.calls[1][1];
|
|
432
|
+
expect(setTimeoutCall).toBeLessThanOrEqual(1000);
|
|
433
|
+
expect(setTimeoutCall).toBeGreaterThanOrEqual(900);
|
|
434
|
+
|
|
435
|
+
timeoutSpy.mockRestore();
|
|
436
|
+
});
|
|
396
437
|
});
|
|
397
438
|
|