Skip to content

Commit ff9f07d

Browse files
committed
gateway: Update gateway.load() to support AS2 and AS3
Starting with AS 2.25.0, gateway.load receives `graphRef` in addition to `graphId` and `graphVariant`; `graphVariant` is declared as always provided. In AS3, only `graphRef` will be provided; `graphVariant` will not be provided. In order for this code to work with both versions, we declare a version of ApolloConfig that could come from either ourselves, and parse it into an internal representation based on the AS3 version.
1 parent 757e6fb commit ff9f07d

File tree

5 files changed

+56
-40
lines changed

5 files changed

+56
-40
lines changed

gateway-js/src/__tests__/integration/nockMocks.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@ import { getTestingSupergraphSdl } from '../../__tests__/execution-utils';
66
import { print } from 'graphql';
77
import { fixtures } from 'apollo-federation-integration-testsuite';
88

9-
export const graphId = 'federated-service';
10-
export const graphVariant = 'current';
9+
export const graphRef = 'federated-service@current';
1110
export const apiKey = 'service:federated-service:DD71EBbGmsuh-6suUVDwnA';
1211
const apiKeyHash = 'dd55a79d467976346d229a7b12b673ce';
1312

1413
export const mockApolloConfig = {
1514
apollo: {
1615
key: apiKey,
1716
keyHash: apiKeyHash,
18-
graphId,
19-
graphVariant,
17+
graphRef,
2018
},
2119
};
2220

@@ -73,7 +71,7 @@ export function mockSupergraphSdlRequest() {
7371
return gatewayNock(mockCloudConfigUrl).post('/', {
7472
query: SUPERGRAPH_SDL_QUERY,
7573
variables: {
76-
ref: `${graphId}@${graphVariant}`,
74+
ref: graphRef,
7775
apiKey: apiKey,
7876
},
7977
});

gateway-js/src/__tests__/loadSupergraphSdlFromStorage.test.ts

+5-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { loadSupergraphSdlFromStorage } from '../loadSupergraphSdlFromStorage';
22
import { getDefaultFetcher } from '../..';
33
import {
44
mockSupergraphSdlRequestSuccess,
5-
graphId,
6-
graphVariant,
5+
graphRef,
76
apiKey,
87
mockCloudConfigUrl,
98
mockSupergraphSdlRequest,
@@ -14,8 +13,7 @@ describe('loadSupergraphSdlFromStorage', () => {
1413
mockSupergraphSdlRequestSuccess();
1514
const fetcher = getDefaultFetcher();
1615
const result = await loadSupergraphSdlFromStorage({
17-
graphId,
18-
graphVariant,
16+
graphRef,
1917
apiKey,
2018
endpoint: mockCloudConfigUrl,
2119
fetcher,
@@ -308,8 +306,7 @@ describe('loadSupergraphSdlFromStorage', () => {
308306
const fetcher = getDefaultFetcher();
309307
await expect(
310308
loadSupergraphSdlFromStorage({
311-
graphId,
312-
graphVariant,
309+
graphRef,
313310
apiKey,
314311
endpoint: mockCloudConfigUrl,
315312
fetcher,
@@ -331,8 +328,7 @@ describe('loadSupergraphSdlFromStorage', () => {
331328
const fetcher = getDefaultFetcher();
332329
await expect(
333330
loadSupergraphSdlFromStorage({
334-
graphId,
335-
graphVariant,
331+
graphRef,
336332
apiKey,
337333
endpoint: mockCloudConfigUrl,
338334
fetcher,
@@ -346,8 +342,7 @@ describe('loadSupergraphSdlFromStorage', () => {
346342
const fetcher = getDefaultFetcher();
347343
await expect(
348344
loadSupergraphSdlFromStorage({
349-
graphId,
350-
graphVariant,
345+
graphRef,
351346
apiKey,
352347
endpoint: mockCloudConfigUrl,
353348
fetcher,

gateway-js/src/index.ts

+37-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
GraphQLExecutionResult,
99
Logger,
1010
GraphQLRequestContextExecutionDidStart,
11-
ApolloConfig,
1211
} from 'apollo-server-types';
1312
import { InMemoryLRUCache } from 'apollo-server-caching';
1413
import {
@@ -126,7 +125,7 @@ export const SERVICE_DEFINITION_QUERY =
126125

127126
type GatewayState =
128127
| { phase: 'initialized' }
129-
| { phase: 'failed to load'}
128+
| { phase: 'failed to load' }
130129
| { phase: 'loaded' }
131130
| { phase: 'stopping'; stoppingDonePromise: Promise<void> }
132131
| { phase: 'stopped' }
@@ -136,13 +135,28 @@ type GatewayState =
136135
doneWaiting: () => void;
137136
}
138137
| { phase: 'polling'; pollingDonePromise: Promise<void> };
138+
139+
interface ApolloConfigFromAS3 {
140+
key?: string;
141+
keyHash?: string;
142+
graphRef?: string;
143+
}
144+
145+
interface ApolloConfigFromAS2Or3 {
146+
key?: string;
147+
keyHash?: string;
148+
graphRef?: string;
149+
graphId?: string;
150+
graphVariant?: string;
151+
}
152+
139153
export class ApolloGateway implements GraphQLService {
140154
public schema?: GraphQLSchema;
141155
private serviceMap: DataSourceMap = Object.create(null);
142156
private config: GatewayConfig;
143157
private logger: Logger;
144158
private queryPlanStore: InMemoryLRUCache<QueryPlan>;
145-
private apolloConfig?: ApolloConfig;
159+
private apolloConfig?: ApolloConfigFromAS3;
146160
private onSchemaChangeListeners = new Set<SchemaChangeCallback>();
147161
private serviceDefinitions: ServiceDefinition[] = [];
148162
private compositionMetadata?: CompositionMetadata;
@@ -306,7 +320,7 @@ export class ApolloGateway implements GraphQLService {
306320
}
307321

308322
public async load(options?: {
309-
apollo?: ApolloConfig;
323+
apollo?: ApolloConfigFromAS2Or3;
310324
engine?: GraphQLServiceEngineConfig;
311325
}) {
312326
if (this.state.phase !== 'initialized') {
@@ -315,13 +329,22 @@ export class ApolloGateway implements GraphQLService {
315329
);
316330
}
317331
if (options?.apollo) {
318-
this.apolloConfig = options.apollo;
332+
const { key, keyHash, graphRef, graphId, graphVariant } = options.apollo;
333+
this.apolloConfig = {
334+
key,
335+
keyHash,
336+
graphRef:
337+
graphRef ??
338+
(graphId ? `${graphId}@${graphVariant ?? 'current'}` : undefined),
339+
};
319340
} else if (options?.engine) {
320341
// Older version of apollo-server-core that isn't passing 'apollo' yet.
342+
const { apiKeyHash, graphId, graphVariant } = options.engine;
321343
this.apolloConfig = {
322-
keyHash: options.engine.apiKeyHash,
323-
graphId: options.engine.graphId,
324-
graphVariant: options.engine.graphVariant || 'current',
344+
keyHash: apiKeyHash,
345+
graphRef: graphId
346+
? `${graphId}@${graphVariant ?? 'current'}`
347+
: undefined,
325348
};
326349
}
327350

@@ -363,8 +386,8 @@ export class ApolloGateway implements GraphQLService {
363386
const mode = isManagedConfig(this.config) ? 'managed' : 'unmanaged';
364387
this.logger.info(
365388
`Gateway successfully loaded schema.\n\t* Mode: ${mode}${
366-
this.apolloConfig && this.apolloConfig.graphId
367-
? `\n\t* Service: ${this.apolloConfig.graphId}@${this.apolloConfig.graphVariant}`
389+
this.apolloConfig && this.apolloConfig.graphRef
390+
? `\n\t* Service: ${this.apolloConfig.graphRef}`
368391
: ''
369392
}`,
370393
);
@@ -861,7 +884,7 @@ export class ApolloGateway implements GraphQLService {
861884
}
862885

863886
const canUseManagedConfig =
864-
this.apolloConfig?.graphId && this.apolloConfig?.keyHash;
887+
this.apolloConfig?.graphRef && this.apolloConfig?.keyHash;
865888
if (!canUseManagedConfig) {
866889
throw new Error(
867890
'When a manual configuration is not provided, gateway requires an Apollo ' +
@@ -877,26 +900,24 @@ export class ApolloGateway implements GraphQLService {
877900
!isPrecomposedManagedConfig(config)
878901
) {
879902
return getServiceDefinitionsFromStorage({
880-
graphId: this.apolloConfig!.graphId!,
903+
graphRef: this.apolloConfig!.graphRef!,
881904
apiKeyHash: this.apolloConfig!.keyHash!,
882-
graphVariant: this.apolloConfig!.graphVariant,
883905
federationVersion: config.federationVersion || 1,
884906
fetcher: this.fetcher,
885907
});
886908
}
887909

888910
return loadSupergraphSdlFromStorage({
889-
graphId: this.apolloConfig!.graphId!,
911+
graphRef: this.apolloConfig!.graphRef!,
890912
apiKey: this.apolloConfig!.key!,
891-
graphVariant: this.apolloConfig!.graphVariant,
892913
endpoint: this.experimental_schemaConfigDeliveryEndpoint!,
893914
fetcher: this.fetcher,
894915
});
895916
}
896917

897918
private maybeWarnOnConflictingConfig() {
898919
const canUseManagedConfig =
899-
this.apolloConfig?.graphId && this.apolloConfig?.keyHash;
920+
this.apolloConfig?.graphRef && this.apolloConfig?.keyHash;
900921

901922
// This might be a bit confusing just by reading, but `!isManagedConfig` just
902923
// means it's any of the other types of config. If it's any other config _and_

gateway-js/src/legacyLoadServicesFromStorage.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,22 @@ function fetchApolloGcs(
9898
}
9999

100100
export async function getServiceDefinitionsFromStorage({
101-
graphId,
101+
graphRef,
102102
apiKeyHash,
103-
graphVariant,
104103
federationVersion,
105104
fetcher,
106105
}: {
107-
graphId: string;
106+
graphRef: string;
108107
apiKeyHash: string;
109-
graphVariant: string;
110108
federationVersion: number;
111109
fetcher: typeof fetch;
112110
}): Promise<ServiceDefinitionUpdate> {
111+
// The protocol for talking to GCS requires us to split the graph ref
112+
// into ID and variant; sigh.
113+
const at = graphRef.indexOf('@');
114+
const graphId = at === -1 ? graphRef : graphRef.substring(0, at);
115+
const graphVariant = at === -1 ? 'current' : graphRef.substring(at + 1);
116+
113117
// fetch the storage secret
114118
const storageSecretUrl = getStorageSecretUrl(graphId, apiKeyHash);
115119

gateway-js/src/loadSupergraphSdlFromStorage.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,12 @@ const { name, version } = require('../package.json');
3737
const fetchErrorMsg = "An error occurred while fetching your schema from Apollo: ";
3838

3939
export async function loadSupergraphSdlFromStorage({
40-
graphId,
41-
graphVariant,
40+
graphRef,
4241
apiKey,
4342
endpoint,
4443
fetcher,
4544
}: {
46-
graphId: string;
47-
graphVariant: string;
45+
graphRef: string;
4846
apiKey: string;
4947
endpoint: string;
5048
fetcher: typeof fetch;
@@ -56,7 +54,7 @@ export async function loadSupergraphSdlFromStorage({
5654
body: JSON.stringify({
5755
query: SUPERGRAPH_SDL_QUERY,
5856
variables: {
59-
ref: `${graphId}@${graphVariant}`,
57+
ref: graphRef,
6058
apiKey,
6159
},
6260
}),

0 commit comments

Comments
 (0)