@apollo/gateway 0.48.1 → 0.50.0

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.
Files changed (46) hide show
  1. package/README.md +7 -5
  2. package/dist/__generated__/graphqlTypes.d.ts +4 -0
  3. package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
  4. package/dist/__generated__/graphqlTypes.js.map +1 -1
  5. package/dist/config.d.ts +6 -2
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +1 -0
  8. package/dist/config.js.map +1 -1
  9. package/dist/executeQueryPlan.d.ts.map +1 -1
  10. package/dist/executeQueryPlan.js +4 -3
  11. package/dist/executeQueryPlan.js.map +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +19 -8
  14. package/dist/index.js.map +1 -1
  15. package/dist/schema-helper/index.js +5 -1
  16. package/dist/schema-helper/index.js.map +1 -1
  17. package/dist/supergraphManagers/IntrospectAndCompose/index.js.map +1 -1
  18. package/dist/supergraphManagers/LegacyFetcher/index.js.map +1 -1
  19. package/dist/supergraphManagers/LocalCompose/index.js.map +1 -1
  20. package/dist/supergraphManagers/UplinkFetcher/index.d.ts +3 -1
  21. package/dist/supergraphManagers/UplinkFetcher/index.d.ts.map +1 -1
  22. package/dist/supergraphManagers/UplinkFetcher/index.js +20 -4
  23. package/dist/supergraphManagers/UplinkFetcher/index.js.map +1 -1
  24. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts +3 -2
  25. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts.map +1 -1
  26. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js +9 -3
  27. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js.map +1 -1
  28. package/package.json +6 -6
  29. package/src/__generated__/graphqlTypes.ts +11 -2
  30. package/src/__tests__/CucumberREADME.md +1 -0
  31. package/src/__tests__/build-query-plan-fragmentization.feature +10 -0
  32. package/src/__tests__/build-query-plan.feature +84 -16
  33. package/src/__tests__/buildQueryPlan.test.ts +272 -1
  34. package/src/__tests__/gateway/lifecycle-hooks.test.ts +3 -3
  35. package/src/__tests__/gateway/reporting.test.ts +5 -0
  36. package/src/__tests__/gateway/supergraphSdl.test.ts +3 -3
  37. package/src/__tests__/integration/abstract-types.test.ts +3 -3
  38. package/src/__tests__/integration/configuration.test.ts +0 -11
  39. package/src/__tests__/integration/requires.test.ts +1 -1
  40. package/src/__tests__/integration/value-types.test.ts +1 -1
  41. package/src/config.ts +11 -6
  42. package/src/executeQueryPlan.ts +4 -0
  43. package/src/index.ts +12 -6
  44. package/src/supergraphManagers/UplinkFetcher/__tests__/loadSupergraphSdlFromStorage.test.ts +41 -0
  45. package/src/supergraphManagers/UplinkFetcher/index.ts +37 -18
  46. package/src/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts +9 -1
@@ -6,7 +6,7 @@ import { SubgraphHealthCheckFunction, SupergraphSdlUpdateFunction } from '../..'
6
6
  import { loadSupergraphSdlFromUplinks } from './loadSupergraphSdlFromStorage';
7
7
 
8
8
  export interface UplinkFetcherOptions {
9
- pollIntervalInMs: number;
9
+ fallbackPollIntervalInMs: number;
10
10
  subgraphHealthCheck?: boolean;
11
11
  graphRef: string;
12
12
  apiKey: string;
@@ -31,6 +31,8 @@ export class UplinkFetcher implements SupergraphManager {
31
31
  process.env.APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT ?? undefined;
32
32
  private compositionId?: string;
33
33
  private fetchCount: number = 0;
34
+ private minDelayMs: number | null = null;
35
+ private earliestFetchTime: Date | null = null;
34
36
 
35
37
  constructor(options: UplinkFetcherOptions) {
36
38
  this.config = options;
@@ -46,7 +48,12 @@ export class UplinkFetcher implements SupergraphManager {
46
48
 
47
49
  let initialSupergraphSdl: string | null = null;
48
50
  try {
49
- initialSupergraphSdl = await this.updateSupergraphSdl();
51
+ const result = await this.updateSupergraphSdl();
52
+ initialSupergraphSdl = result?.supergraphSdl || null;
53
+ if (result?.minDelaySeconds) {
54
+ this.minDelayMs = 1000 * result?.minDelaySeconds;
55
+ this.earliestFetchTime = new Date(Date.now() + this.minDelayMs);
56
+ }
50
57
  } catch (e) {
51
58
  this.logUpdateFailure(e);
52
59
  throw e;
@@ -83,6 +90,7 @@ export class UplinkFetcher implements SupergraphManager {
83
90
  compositionId: this.compositionId ?? null,
84
91
  maxRetries: this.config.maxRetries,
85
92
  roundRobinSeed: this.fetchCount++,
93
+ earliestFetchTime: this.earliestFetchTime,
86
94
  });
87
95
 
88
96
  if (!result) {
@@ -91,7 +99,8 @@ export class UplinkFetcher implements SupergraphManager {
91
99
  this.compositionId = result.id;
92
100
  // the healthCheck fn is only assigned if it's enabled in the config
93
101
  await this.healthCheck?.(result.supergraphSdl);
94
- return result.supergraphSdl;
102
+ const { supergraphSdl, minDelaySeconds } = result;
103
+ return { supergraphSdl, minDelaySeconds };
95
104
  }
96
105
  }
97
106
 
@@ -101,24 +110,34 @@ export class UplinkFetcher implements SupergraphManager {
101
110
  }
102
111
 
103
112
  private poll() {
104
- this.timerRef = setTimeout(async () => {
105
- if (this.state.phase === 'polling') {
106
- const pollingPromise = resolvable();
107
-
108
- this.state.pollingPromise = pollingPromise;
109
- try {
110
- const maybeNewSupergraphSdl = await this.updateSupergraphSdl();
111
- if (maybeNewSupergraphSdl) {
112
- this.update?.(maybeNewSupergraphSdl);
113
+ this.timerRef = setTimeout(
114
+ async () => {
115
+ if (this.state.phase === 'polling') {
116
+ const pollingPromise = resolvable();
117
+
118
+ this.state.pollingPromise = pollingPromise;
119
+ try {
120
+ const result = await this.updateSupergraphSdl();
121
+ const maybeNewSupergraphSdl = result?.supergraphSdl || null;
122
+ if (result?.minDelaySeconds) {
123
+ this.minDelayMs = 1000 * result?.minDelaySeconds;
124
+ this.earliestFetchTime = new Date(Date.now() + this.minDelayMs);
125
+ }
126
+ if (maybeNewSupergraphSdl) {
127
+ this.update?.(maybeNewSupergraphSdl);
128
+ }
129
+ } catch (e) {
130
+ this.logUpdateFailure(e);
113
131
  }
114
- } catch (e) {
115
- this.logUpdateFailure(e);
132
+ pollingPromise.resolve();
116
133
  }
117
- pollingPromise.resolve();
118
- }
119
134
 
120
- this.poll();
121
- }, this.config.pollIntervalInMs);
135
+ this.poll();
136
+ },
137
+ this.minDelayMs
138
+ ? Math.max(this.minDelayMs, this.config.fallbackPollIntervalInMs)
139
+ : this.config.fallbackPollIntervalInMs,
140
+ );
122
141
  }
123
142
 
124
143
  private logUpdateFailure(e: any) {
@@ -13,6 +13,7 @@ export const SUPERGRAPH_SDL_QUERY = /* GraphQL */`#graphql
13
13
  ... on RouterConfigResult {
14
14
  id
15
15
  supergraphSdl: supergraphSDL
16
+ minDelaySeconds
16
17
  }
17
18
  ... on FetchError {
18
19
  code
@@ -56,6 +57,7 @@ export async function loadSupergraphSdlFromUplinks({
56
57
  compositionId,
57
58
  maxRetries,
58
59
  roundRobinSeed,
60
+ earliestFetchTime,
59
61
  }: {
60
62
  graphRef: string;
61
63
  apiKey: string;
@@ -65,6 +67,7 @@ export async function loadSupergraphSdlFromUplinks({
65
67
  compositionId: string | null;
66
68
  maxRetries: number,
67
69
  roundRobinSeed: number,
70
+ earliestFetchTime: Date | null
68
71
  }) : Promise<SupergraphSdlUpdate | null> {
69
72
  // This Promise resolves with either an updated supergraph or null if no change.
70
73
  // This Promise can reject in the case that none of the retries are successful,
@@ -81,6 +84,10 @@ export async function loadSupergraphSdlFromUplinks({
81
84
  }),
82
85
  {
83
86
  retries: maxRetries,
87
+ onRetry: async () => {
88
+ const delayMS = earliestFetchTime ? earliestFetchTime.getTime() - Date.now(): 0;
89
+ if (delayMS > 0) await new Promise(resolve => setTimeout(resolve, delayMS));
90
+ }
84
91
  },
85
92
  );
86
93
 
@@ -176,9 +183,10 @@ export async function loadSupergraphSdlFromStorage({
176
183
  const {
177
184
  id,
178
185
  supergraphSdl,
186
+ minDelaySeconds,
179
187
  // messages,
180
188
  } = routerConfig;
181
- return { id, supergraphSdl: supergraphSdl! };
189
+ return { id, supergraphSdl: supergraphSdl!, minDelaySeconds };
182
190
  } else if (routerConfig.__typename === 'FetchError') {
183
191
  // FetchError case
184
192
  const { code, message } = routerConfig;