UNPKG

@the_pixelport/aws-lambda-graphql

Version:

Apollo server for AWS Lambda with WebSocket subscriptions support over API Gateway v1 + v2

121 lines 5.47 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisConnectionManager = void 0; const assert_1 = __importDefault(require("assert")); const client_apigatewaymanagementapi_1 = require("@aws-sdk/client-apigatewaymanagementapi"); const errors_1 = require("./errors"); const helpers_1 = require("./helpers"); /** * RedisConnectionManager * * Stores connections in Redis store */ class RedisConnectionManager { constructor({ apiGatewayManager, redisClient, subscriptions, }) { this.hydrateConnection = async (connectionId, options) => { const { retryCount = 0, timeout = 50 } = options || {}; // if connection is not found, throw so we can terminate connection let connection; for (let i = 0; i <= retryCount; i++) { const key = (0, helpers_1.prefixRedisKey)(`connection:${connectionId}`); const result = await this.redisClient.get(key); if (result) { // Jump out of loop connection = JSON.parse(result); break; } // wait for another round await new Promise((r) => setTimeout(r, timeout)); } if (!connection) { throw new errors_1.ConnectionNotFoundError(`Connection ${connectionId} not found`); } return connection; }; this.setConnectionData = async (data, connection) => { await this.redisClient.set((0, helpers_1.prefixRedisKey)(`connection:${connection.id}`), JSON.stringify({ ...connection, data, }), 'EX', 7200); }; this.registerConnection = async ({ connectionId, endpoint, }) => { const connection = { id: connectionId, data: { endpoint, context: {}, isInitialized: false }, }; console.log('[DEBUG] RedisConnectionManager.registerConnection:', { connectionId, endpoint, connectionData: connection.data, }); await this.redisClient.set((0, helpers_1.prefixRedisKey)(`connection:${connectionId}`), JSON.stringify({ createdAt: new Date().toString(), id: connection.id, data: connection.data, }), 'EX', 7200); return connection; }; this.sendToConnection = async (connection, payload) => { var _a; console.log('[DEBUG] RedisConnectionManager.sendToConnection:', { connectionId: connection.id, endpoint: connection.data.endpoint, payloadLength: payload.length, }); try { await this.createApiGatewayManager(connection.data.endpoint).send(new client_apigatewaymanagementapi_1.PostToConnectionCommand({ ConnectionId: connection.id, Data: payload, })); } catch (e) { // this is stale connection // remove it from store if (e && ((_a = e.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 410) { await this.unregisterConnection(connection); } else { throw e; } } }; this.unregisterConnection = async ({ id }) => { const key = (0, helpers_1.prefixRedisKey)(`connection:${id}`); await Promise.all([ this.redisClient.del(key), this.subscriptions.unsubscribeAllByConnectionId(id), ]); }; this.closeConnection = async ({ id, data }) => { await this.createApiGatewayManager(data.endpoint).send(new client_apigatewaymanagementapi_1.DeleteConnectionCommand({ ConnectionId: id })); }; assert_1.default.ok(typeof subscriptions === 'object', 'Please provide subscriptions to manage subscriptions.'); assert_1.default.ok(redisClient == null || typeof redisClient === 'object', 'Please provide redisClient as an instance of ioredis.Redis'); assert_1.default.ok(apiGatewayManager == null || typeof apiGatewayManager === 'object', 'Please provide apiGatewayManager as an instance of ApiGatewayManagementApiClient'); this.apiGatewayManager = apiGatewayManager; this.redisClient = redisClient; this.subscriptions = subscriptions; } /** * Creates api gateway manager * * If custom api gateway manager is provided, uses it instead */ createApiGatewayManager(endpoint) { console.log('[DEBUG] RedisConnectionManager.createApiGatewayManager:', { endpoint, isValidUrl: endpoint.startsWith('https://'), customManagerExists: !!this.apiGatewayManager, }); if (this.apiGatewayManager) { return this.apiGatewayManager; } this.apiGatewayManager = new client_apigatewaymanagementapi_1.ApiGatewayManagementApiClient({ endpoint }); return this.apiGatewayManager; } } exports.RedisConnectionManager = RedisConnectionManager; //# sourceMappingURL=RedisConnectionManager.js.map