UNPKG

@apollo/gateway

Version:
214 lines 10.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UplinkSupergraphManager = void 0; const makeFetchHappen = __importStar(require("make-fetch-happen")); const resolvable_1 = __importDefault(require("@josephg/resolvable")); const logger_1 = require("../../logger"); const loadSupergraphSdlFromStorage_1 = require("./loadSupergraphSdlFromStorage"); class UplinkSupergraphManager { constructor({ apiKey, graphRef, debug, logger, uplinkEndpoints, fallbackPollIntervalInMs, maxRetries, initialMaxRetries, fetcher, shouldRunSubgraphHealthcheck, onFailureToFetchSupergraphSdlDuringInit, onFailureToFetchSupergraphSdlAfterInit, }) { this.uplinkEndpoints = UplinkSupergraphManager.getUplinkEndpoints(); this.fetcher = makeFetchHappen.defaults(); this.requestTimeoutMs = UplinkSupergraphManager.DEFAULT_REQUEST_TIMEOUT_MS; this.pollIntervalMs = UplinkSupergraphManager.MIN_POLL_INTERVAL_MS; this.shouldRunSubgraphHealthcheck = false; this.timerRef = null; this.fetchCount = 0; this.apiKey = apiKey; this.graphRef = graphRef; this.logger = logger !== null && logger !== void 0 ? logger : (0, logger_1.getDefaultLogger)(debug); this.uplinkEndpoints = uplinkEndpoints !== null && uplinkEndpoints !== void 0 ? uplinkEndpoints : this.uplinkEndpoints; this.maxRetries = maxRetries !== null && maxRetries !== void 0 ? maxRetries : this.uplinkEndpoints.length * 3 - 1; this.initialMaxRetries = initialMaxRetries !== null && initialMaxRetries !== void 0 ? initialMaxRetries : this.maxRetries; this.pollIntervalMs = fallbackPollIntervalInMs !== null && fallbackPollIntervalInMs !== void 0 ? fallbackPollIntervalInMs : this.pollIntervalMs; this.fallbackPollIntervalInMs = fallbackPollIntervalInMs; if (this.pollIntervalMs < UplinkSupergraphManager.MIN_POLL_INTERVAL_MS) { this.logger.warn('Polling Apollo services at a frequency of less than once per 10 seconds (10000) is disallowed. Instead, the minimum allowed pollInterval of 10000 will be used. Please reconfigure your `fallbackPollIntervalInMs` accordingly. If this is problematic for your team, please contact support.'); this.pollIntervalMs = UplinkSupergraphManager.MIN_POLL_INTERVAL_MS; } this.fetcher = fetcher !== null && fetcher !== void 0 ? fetcher : this.fetcher; this.shouldRunSubgraphHealthcheck = shouldRunSubgraphHealthcheck !== null && shouldRunSubgraphHealthcheck !== void 0 ? shouldRunSubgraphHealthcheck : this.shouldRunSubgraphHealthcheck; this.onFailureToFetchSupergraphSdlDuringInit = onFailureToFetchSupergraphSdlDuringInit; this.onFailureToFetchSupergraphSdlAfterInit = onFailureToFetchSupergraphSdlAfterInit; if (!!process.env.APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT) { this.logger.warn('Out-of-band error reporting is no longer used by Apollo. You may remove the `APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT` environment variable at your convenience.'); } this.state = { phase: 'constructed' }; } async initialize({ update, healthCheck }) { this.update = update; if (this.shouldRunSubgraphHealthcheck) { this.healthCheck = healthCheck; } let initialSupergraphSdl = null; try { initialSupergraphSdl = await this.updateSupergraphSdl(this.initialMaxRetries); if (!initialSupergraphSdl) { throw new Error('Invalid supergraph schema supplied during initialization.'); } } catch (e) { this.logUpdateFailure(e); throw e; } this.state = { phase: 'initialized' }; this.beginPolling(); return { supergraphSdl: initialSupergraphSdl, cleanup: async () => { if (this.state.phase === 'polling') { await this.state.pollingPromise; } this.state = { phase: 'stopped' }; if (this.timerRef) { clearTimeout(this.timerRef); this.timerRef = null; } }, }; } async nextFetch() { if (this.state.phase !== 'polling') { return; } return this.state.nextFetchPromise; } static getUplinkEndpoints() { var _a; const envEndpoints = (_a = process.env.APOLLO_SCHEMA_CONFIG_DELIVERY_ENDPOINT) === null || _a === void 0 ? void 0 : _a.split(','); return envEndpoints !== null && envEndpoints !== void 0 ? envEndpoints : UplinkSupergraphManager.DEFAULT_UPLINK_ENDPOINTS; } async updateSupergraphSdl(maxRetries) { var _a, _b; let supergraphSdl; try { const result = await (0, loadSupergraphSdlFromStorage_1.loadSupergraphSdlFromUplinks)({ graphRef: this.graphRef, apiKey: this.apiKey, endpoints: this.uplinkEndpoints, fetcher: this.fetcher, compositionId: (_a = this.compositionId) !== null && _a !== void 0 ? _a : null, maxRetries, requestTimeoutMs: this.requestTimeoutMs, roundRobinSeed: this.fetchCount++, logger: this.logger, }); this.mostRecentSuccessfulFetchAt = new Date(); this.logger.debug(`Received Uplink response. Has updated SDL? ${!!(result === null || result === void 0 ? void 0 : result.supergraphSdl)}`); if (!result) { return null; } this.compositionId = result.id; supergraphSdl = result.supergraphSdl; if (result === null || result === void 0 ? void 0 : result.minDelaySeconds) { this.pollIntervalMs = result.minDelaySeconds * 1000; if (this.fallbackPollIntervalInMs) { this.pollIntervalMs = Math.max(this.pollIntervalMs, this.fallbackPollIntervalInMs); } } } catch (e) { this.logger.debug(`Error fetching supergraphSdl from Uplink during phase '${this.state.phase}'`); if (this.state.phase === 'constructed' && this.onFailureToFetchSupergraphSdlDuringInit) { supergraphSdl = await this.onFailureToFetchSupergraphSdlDuringInit({ error: e, graphRef: this.graphRef, logger: this.logger, fetchCount: this.fetchCount, }); } else if (this.state.phase === 'polling' && this.onFailureToFetchSupergraphSdlAfterInit) { supergraphSdl = await this.onFailureToFetchSupergraphSdlAfterInit({ error: e, graphRef: this.graphRef, logger: this.logger, fetchCount: this.fetchCount, mostRecentSuccessfulFetchAt: this.mostRecentSuccessfulFetchAt, }); if (!supergraphSdl) { return null; } } else { throw e; } } await ((_b = this.healthCheck) === null || _b === void 0 ? void 0 : _b.call(this, supergraphSdl)); return supergraphSdl; } beginPolling() { this.state = { phase: 'polling' }; this.poll(); } poll() { if (this.state.phase !== 'polling') { this.logger.debug(`Stopped polling Uplink [phase: ${this.state.phase}]`); return; } this.state.nextFetchPromise = (0, resolvable_1.default)(); this.logger.debug(`Will poll Uplink after ${this.pollIntervalMs}ms [phase: ${this.state.phase}]`); this.timerRef = setTimeout(async () => { var _a, _b; if (this.state.phase === 'polling') { const pollingPromise = (0, resolvable_1.default)(); this.state.pollingPromise = pollingPromise; try { const supergraphSdl = await this.updateSupergraphSdl(this.maxRetries); if (supergraphSdl) { (_a = this.update) === null || _a === void 0 ? void 0 : _a.call(this, supergraphSdl); } } catch (e) { this.logUpdateFailure(e); } pollingPromise.resolve(); (_b = this.state.nextFetchPromise) === null || _b === void 0 ? void 0 : _b.resolve(); } this.poll(); }, this.pollIntervalMs); } logUpdateFailure(e) { var _a; this.logger.error('UplinkSupergraphManager failed to update supergraph with the following error: ' + ((_a = e.message) !== null && _a !== void 0 ? _a : e)); } } exports.UplinkSupergraphManager = UplinkSupergraphManager; UplinkSupergraphManager.DEFAULT_REQUEST_TIMEOUT_MS = 30000; UplinkSupergraphManager.MIN_POLL_INTERVAL_MS = 10000; UplinkSupergraphManager.DEFAULT_UPLINK_ENDPOINTS = [ 'https://uplink.api.apollographql.com/', 'https://aws.uplink.api.apollographql.com/', ]; //# sourceMappingURL=index.js.map