Skip to content

Commit

Permalink
feat: add incr api (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
rishtigupta authored May 2, 2024
1 parent 4e9fcbe commit 32d7817
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
test-momento:
strategy:
matrix:
node: [14, 16, 18]
node: [16, 18, 20]
name: Test on Node ${{ matrix.node }}
runs-on: macos-latest
env:
Expand Down Expand Up @@ -59,7 +59,7 @@ jobs:
# TODO the redis tests are flaky when run all in parallel.
max-parallel: 2
matrix:
node: [14, 16, 18]
node: [16, 18, 20]
name: Test on Node ${{ matrix.node }}
runs-on: ubuntu-latest
services:
Expand Down
30 changes: 29 additions & 1 deletion src/momento-redis-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
CacheDictionaryGetField,
CacheDictionaryGetFields,
SdkError,
CacheIncrement,
} from '@gomomento/sdk';

import {ClientCommandOptions} from '@redis/client/dist/lib/client';
Expand Down Expand Up @@ -50,6 +51,7 @@ type HMGetParams = [
type HSetParams = Parameters<
(typeof RedisCommands)['HSET']['transformArguments']
>;
type IncrementParams = [key: RedisCommandArgument];

type CommandParams =
| GetParams
Expand All @@ -59,7 +61,8 @@ type CommandParams =
| HSetParams
| HGetAllParams
| HMGetParams
| HGetParams;
| HGetParams
| IncrementParams;
type WithOptionalOptions<T extends CommandParams> =
| T
| [options: ClientCommandOptions, ...args: T];
Expand Down Expand Up @@ -102,6 +105,8 @@ export interface IMomentoRedisClient {
HMGET: IMomentoRedisClient['hmGet'];
hSet(...args: WithOptionalOptions<HSetParams>): Promise<number>;
HSET: IMomentoRedisClient['hSet'];
incr(...args: WithOptionalOptions<IncrementParams>): Promise<number | null>;
INCR: IMomentoRedisClient['incr'];
}

export class MomentoRedisClient
Expand Down Expand Up @@ -481,6 +486,29 @@ export class MomentoRedisClient
return 0;
}

public async incr(
...args: WithOptionalOptions<IncrementParams>
): Promise<number | null> {
const [, otherArgs] =
MomentoRedisClient.extractReturnBuffersOptionFromArgs(args);
return await this.sendIncr(otherArgs as IncrementParams);
}

// eslint-disable-next-line @typescript-eslint/unbound-method
public INCR = this.incr;

private async sendIncr([key]: IncrementParams): Promise<number | null> {
const response = await this.client.increment(this.cacheName, key);
if (response instanceof CacheIncrement.Success) {
return response.value();
} else if (response instanceof CacheIncrement.Error) {
this.emitError(response.innerException());
} else {
this.emitError(UNEXPECTED_RESPONSE);
}
return null;
}

private emitError(error: SdkError | ErrorReply): void {
const errorReply =
error instanceof ErrorReply
Expand Down
62 changes: 62 additions & 0 deletions test/increment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {SetupIntegrationTest} from './integration-setup';
import {v4} from 'uuid';

const {client} = SetupIntegrationTest();

describe('increment', () => {
it('should increment the value of the key by 1 if the key exists', async () => {
const key = v4();
const value = 5;
// set initial key value
await client.set(key, value);
// increment key value
const incrementResult = await client.incr(key);
expect(incrementResult).toEqual(value + 1);
});

it('should increment the value of the key to 1 if the key does not exists', async () => {
const key = v4();
// increment key value
const incrementResult = await client.incr(key);
expect(incrementResult).toEqual(1);
});

it('should error out if the key contains a value of wrong type or contains a string that can be represented as integer', async () => {
const key = v4();
const value = 'monkey';
// Set initial key value
await client.set(key, value);
// Increment the value of the key that is not set
try {
await client.incr(key);
} catch (error) {
if (process.env.TEST_REDIS === 'false') {
const momentoError = error as {
code: string;
context: {code: string; msg: string; op: string; platform: string};
};
expect(momentoError.code).toBe('ERR_UNHANDLED_ERROR');
expect(momentoError.context.code).toBe('FAILED_PRECONDITION_ERROR');
expect(momentoError.context.msg).toBe(
"System is not in a state required for the operation's execution: 9 FAILED_PRECONDITION: failed to parse value into long"
);
expect(momentoError.context.op).toBe('incr');
expect(momentoError.context.platform).toBe('momento');
} else if (process.env.TEST_REDIS === 'true') {
expect((error as Error).message).toBe(
'ERR value is not an integer or out of range'
);
}
}
});

it('should increment the value of key that contains a string that can be represented as integer', async () => {
const key = v4();
const value = '10';
// Set initial key value
await client.set(key, value);
// Increment the value of the key that is not set
const incrResp = await client.incr(key);
expect(incrResp).toBe(11);
});
});

0 comments on commit 32d7817

Please sign in to comment.