diff --git a/packages/client-sdk-nodejs/src/cache-client.ts b/packages/client-sdk-nodejs/src/cache-client.ts index 2f7d470b9..0316f12ee 100644 --- a/packages/client-sdk-nodejs/src/cache-client.ts +++ b/packages/client-sdk-nodejs/src/cache-client.ts @@ -33,15 +33,10 @@ export class CacheClient extends AbstractCacheClient implements ICacheClient { credentialProvider: props.credentialProvider, }); - // For high load, we get better performance with multiple clients. Here we - // are setting a default, hard-coded value for the number of clients to use, - // because we haven't yet designed the API for users to use to configure - // tunables: - // https://github.com/momentohq/dev-eco-issue-tracker/issues/85 - // The choice of 6 as the initial value is a rough guess at a reasonable - // default for the short-term, based on load testing results captured in: - // https://github.com/momentohq/oncall-tracker/issues/186 - const numClients = 6; + const numClients = props.configuration + .getTransportStrategy() + .getGrpcConfig() + .getNumClients(); const dataClients = range(numClients).map(() => new DataClient(props)); super(controlClient, dataClients); diff --git a/packages/client-sdk-nodejs/src/config/configurations.ts b/packages/client-sdk-nodejs/src/config/configurations.ts index 40a571b74..19954845a 100644 --- a/packages/client-sdk-nodejs/src/config/configurations.ts +++ b/packages/client-sdk-nodejs/src/config/configurations.ts @@ -73,6 +73,35 @@ export class Laptop extends CacheConfiguration { } } +export class Lambda extends CacheConfiguration { + /** + * Provides the latest recommended configuration for a lambda environment. NOTE: this configuration may + * change in future releases to take advantage of improvements we identify for default configurations. + * @param {MomentoLoggerFactory} [loggerFactory=defaultLoggerFactory] + * @returns {CacheConfiguration} + */ + static latest( + loggerFactory: MomentoLoggerFactory = defaultLoggerFactory + ): CacheConfiguration { + const deadlineMillis = 1100; + const grpcConfig: GrpcConfiguration = new StaticGrpcConfiguration({ + deadlineMillis: deadlineMillis, + maxSessionMemoryMb: defaultMaxSessionMemoryMb, + numClients: 1, + }); + const transportStrategy: TransportStrategy = new StaticTransportStrategy({ + grpcConfiguration: grpcConfig, + maxIdleMillis: defaultMaxIdleMillis, + }); + return new Lambda({ + loggerFactory: loggerFactory, + retryStrategy: defaultRetryStrategy(loggerFactory), + transportStrategy: transportStrategy, + middlewares: defaultMiddlewares, + }); + } +} + class InRegionDefault extends CacheConfiguration { /** * Provides the latest recommended configuration for a typical in-region environment. NOTE: this configuration may diff --git a/packages/client-sdk-nodejs/src/config/transport/grpc-configuration.ts b/packages/client-sdk-nodejs/src/config/transport/grpc-configuration.ts index 8abf4a68f..499f15b55 100644 --- a/packages/client-sdk-nodejs/src/config/transport/grpc-configuration.ts +++ b/packages/client-sdk-nodejs/src/config/transport/grpc-configuration.ts @@ -9,6 +9,12 @@ export interface GrpcConfigurationProps { * more than this amount will return a ResourceExhausted error. */ maxSessionMemoryMb: number; + + /** + * The number of internal clients a cache client will create to communicate with Momento. More of them allows + * more concurrent requests, at the cost of more open connections and the latency of setting up each client. + */ + numClients?: number; } /** @@ -42,4 +48,17 @@ export interface GrpcConfiguration { * @returns {GrpcConfiguration} a new GrpcConfiguration with the specified maximum memory */ withMaxSessionMemoryMb(maxSessionMemoryMb: number): GrpcConfiguration; + + /** + * @returns {number} the number of internal clients a cache client will create to communicate with Momento. More of + * them will allow for more concurrent requests. + */ + getNumClients(): number; + + /** + * Copy constructor for overriding the number of clients to create + * @param {number} numClients the number of internal clients to create + * @returns {GrpcConfiguration} a new GrpcConfiguration with the specified number of clients + */ + withNumClients(numClients: number): GrpcConfiguration; } diff --git a/packages/client-sdk-nodejs/src/config/transport/transport-strategy.ts b/packages/client-sdk-nodejs/src/config/transport/transport-strategy.ts index 290acd344..83c254433 100644 --- a/packages/client-sdk-nodejs/src/config/transport/transport-strategy.ts +++ b/packages/client-sdk-nodejs/src/config/transport/transport-strategy.ts @@ -61,9 +61,16 @@ export interface TransportStrategyProps { export class StaticGrpcConfiguration implements GrpcConfiguration { private readonly deadlineMillis: number; private readonly maxSessionMemoryMb: number; + private readonly numClients: number; constructor(props: GrpcConfigurationProps) { this.deadlineMillis = props.deadlineMillis; this.maxSessionMemoryMb = props.maxSessionMemoryMb; + if (props.numClients !== undefined && props.numClients !== null) { + this.numClients = props.numClients; + } else { + // This is the previously hardcoded value and a safe default for most environments. + this.numClients = 6; + } } getDeadlineMillis(): number { @@ -78,6 +85,7 @@ export class StaticGrpcConfiguration implements GrpcConfiguration { return new StaticGrpcConfiguration({ deadlineMillis: deadlineMillis, maxSessionMemoryMb: this.maxSessionMemoryMb, + numClients: this.numClients, }); } @@ -85,6 +93,19 @@ export class StaticGrpcConfiguration implements GrpcConfiguration { return new StaticGrpcConfiguration({ deadlineMillis: this.deadlineMillis, maxSessionMemoryMb: maxSessionMemoryMb, + numClients: this.numClients, + }); + } + + getNumClients(): number { + return this.numClients; + } + + withNumClients(numClients: number): GrpcConfiguration { + return new StaticGrpcConfiguration({ + deadlineMillis: this.deadlineMillis, + maxSessionMemoryMb: this.maxSessionMemoryMb, + numClients: numClients, }); } } diff --git a/packages/client-sdk-nodejs/test/unit/config/configuration.test.ts b/packages/client-sdk-nodejs/test/unit/config/configuration.test.ts index feafbb079..9ffe3d563 100644 --- a/packages/client-sdk-nodejs/test/unit/config/configuration.test.ts +++ b/packages/client-sdk-nodejs/test/unit/config/configuration.test.ts @@ -16,6 +16,7 @@ describe('configuration.ts', () => { const testGrpcConfiguration = new StaticGrpcConfiguration({ deadlineMillis: 90210, maxSessionMemoryMb: 90211, + numClients: 2, }); const testMaxIdleMillis = 90212; const testTransportStrategy = new StaticTransportStrategy({ @@ -52,6 +53,7 @@ describe('configuration.ts', () => { const newGrpcConfiguration = new StaticGrpcConfiguration({ deadlineMillis: 5000, maxSessionMemoryMb: 5001, + numClients: 3, }); const newMaxIdleMillis = 5002; const newTransportStrategy = new StaticTransportStrategy({ @@ -77,6 +79,7 @@ describe('configuration.ts', () => { grpcConfiguration: new StaticGrpcConfiguration({ deadlineMillis: newClientTimeoutMillis, maxSessionMemoryMb: testGrpcConfiguration.getMaxSessionMemoryMb(), + numClients: testGrpcConfiguration.getNumClients(), }), maxIdleMillis: testMaxIdleMillis, }); diff --git a/packages/client-sdk-nodejs/test/unit/config/transport/transport-strategy.test.ts b/packages/client-sdk-nodejs/test/unit/config/transport/transport-strategy.test.ts index 6f6f380ce..bb5100a2f 100644 --- a/packages/client-sdk-nodejs/test/unit/config/transport/transport-strategy.test.ts +++ b/packages/client-sdk-nodejs/test/unit/config/transport/transport-strategy.test.ts @@ -6,9 +6,11 @@ import { describe('StaticGrpcConfiguration', () => { const testDeadlineMillis = 90210; const testMaxSessionMemoryMb = 90211; + const testNumClients = 4; const testGrpcConfiguration = new StaticGrpcConfiguration({ deadlineMillis: testDeadlineMillis, maxSessionMemoryMb: testMaxSessionMemoryMb, + numClients: testNumClients, }); it('should support overriding deadline millis', () => { @@ -34,14 +36,26 @@ describe('StaticGrpcConfiguration', () => { newMaxSessionMemory ); }); + + it('should support overriding num clients', () => { + const newNumClients = 9; + const configWithNewDeadline = + testGrpcConfiguration.withNumClients(newNumClients); + expect(configWithNewDeadline.getNumClients()).toEqual(newNumClients); + expect(configWithNewDeadline.getMaxSessionMemoryMb()).toEqual( + testMaxSessionMemoryMb + ); + }); }); describe('StaticTransportStrategy', () => { const testDeadlineMillis = 90210; const testMaxSessionMemoryMb = 90211; + const testNumClients = 5; const testGrpcConfiguration = new StaticGrpcConfiguration({ deadlineMillis: testDeadlineMillis, maxSessionMemoryMb: testMaxSessionMemoryMb, + numClients: testNumClients, }); const testMaxIdleMillis = 90212; @@ -56,6 +70,7 @@ describe('StaticTransportStrategy', () => { const newGrpcConfig = new StaticGrpcConfiguration({ deadlineMillis: newDeadlineMillis, maxSessionMemoryMb: newMaxSessionMemoryMb, + numClients: testNumClients, }); const strategyWithNewGrpcConfig = testTransportStrategy.withGrpcConfig(newGrpcConfig); @@ -82,6 +97,7 @@ describe('StaticTransportStrategy', () => { const expectedGrpcConfig = new StaticGrpcConfiguration({ deadlineMillis: newClientTimeout, maxSessionMemoryMb: testMaxSessionMemoryMb, + numClients: testNumClients, }); const strategyWithNewClientTimeout = testTransportStrategy.withClientTimeoutMillis(newClientTimeout);