@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
JavaScript
;
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