Skip to content

Commit

Permalink
Merge pull request valkey-io#2063 from Bit-Quill/node/integ_cyip10_ex…
Browse files Browse the repository at this point in the history
…piretime_series

Node: add EXPIRETIME and PEXPIRETIME
  • Loading branch information
cyip10 authored Aug 2, 2024
2 parents 14ebf28 + cd290c5 commit 42cd2f6
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#### Changes
* Node: Added EXPIRETIME and PEXPIRETIME commands ([#2063](https://github.com/valkey-io/valkey-glide/pull/2063))
* Node: Added SORT commands ([#2028](https://github.com/valkey-io/valkey-glide/pull/2028))
* Node: Added LASTSAVE command ([#2059](https://github.com/valkey-io/valkey-glide/pull/2059))
* Node: Added LCS command ([#2049](https://github.com/valkey-io/valkey-glide/pull/2049))
Expand Down
59 changes: 59 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
createExists,
createExpire,
createExpireAt,
createExpireTime,
createFCall,
createFCallReadOnly,
createGeoAdd,
Expand Down Expand Up @@ -110,6 +111,7 @@ import {
createObjectRefcount,
createPExpire,
createPExpireAt,
createPExpireTime,
createPTTL,
createPersist,
createPfAdd,
Expand Down Expand Up @@ -2429,6 +2431,35 @@ export class BaseClient {
);
}

/**
* Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in seconds.
* To get the expiration with millisecond precision, use {@link pexpiretime}.
*
* See https://valkey.io/commands/expiretime/ for details.
*
* @param key - The `key` to determine the expiration value of.
* @returns The expiration Unix timestamp in seconds, `-2` if `key` does not exist or `-1` if `key` exists but has no associated expire.
*
* since Valkey version 7.0.0.
*
* @example
* ```typescript
* const result1 = await client.expiretime("myKey");
* console.log(result1); // Output: -2 - myKey doesn't exist.
*
* const result2 = await client.set(myKey, "value");
* const result3 = await client.expireTime(myKey);
* console.log(result2); // Output: -1 - myKey has no associated expiration.
*
* client.expire(myKey, 60);
* const result3 = await client.expireTime(myKey);
* console.log(result3); // Output: 123456 - the Unix timestamp (in seconds) when "myKey" will expire.
* ```
*/
public async expiretime(key: string): Promise<number> {
return this.createWritePromise(createExpireTime(key));
}

/** Sets a timeout on `key` in milliseconds. After the timeout has expired, the key will automatically be deleted.
* If `key` already has an existing expire set, the time to live is updated to the new value.
* If `milliseconds` is non-positive number, the key will be deleted rather than expired.
Expand Down Expand Up @@ -2487,6 +2518,34 @@ export class BaseClient {
);
}

/**
* Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in milliseconds.
*
* See https://valkey.io/commands/pexpiretime/ for details.
*
* @param key - The `key` to determine the expiration value of.
* @returns The expiration Unix timestamp in seconds, `-2` if `key` does not exist or `-1` if `key` exists but has no associated expire.
*
* since Valkey version 7.0.0.
*
* @example
* ```typescript
* const result1 = client.pexpiretime("myKey");
* console.log(result1); // Output: -2 - myKey doesn't exist.
*
* const result2 = client.set(myKey, "value");
* const result3 = client.pexpireTime(myKey);
* console.log(result2); // Output: -1 - myKey has no associated expiration.
*
* client.expire(myKey, 60);
* const result3 = client.pexpireTime(myKey);
* console.log(result3); // Output: 123456789 - the Unix timestamp (in milliseconds) when "myKey" will expire.
* ```
*/
public async pexpiretime(key: string): Promise<number> {
return this.createWritePromise(createPExpireTime(key));
}

/** Returns the remaining time to live of `key` that has a timeout.
* See https://valkey.io/commands/ttl/ for details.
*
Expand Down
14 changes: 14 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,13 @@ export function createExpireAt(
return createCommand(RequestType.ExpireAt, args);
}

/**
* @internal
*/
export function createExpireTime(key: string): command_request.Command {
return createCommand(RequestType.ExpireTime, [key]);
}

/**
* @internal
*/
Expand Down Expand Up @@ -1295,6 +1302,13 @@ export function createPExpireAt(
return createCommand(RequestType.PExpireAt, args);
}

/**
* @internal
*/
export function createPExpireTime(key: string): command_request.Command {
return createCommand(RequestType.PExpireTime, [key]);
}

/**
* @internal
*/
Expand Down
33 changes: 33 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import {
createExists,
createExpire,
createExpireAt,
createExpireTime,
createFCall,
createFCallReadOnly,
createFlushAll,
Expand Down Expand Up @@ -133,6 +134,7 @@ import {
createObjectRefcount,
createPExpire,
createPExpireAt,
createPExpireTime,
createPTTL,
createPersist,
createPfAdd,
Expand Down Expand Up @@ -1333,6 +1335,22 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createExpireAt(key, unixSeconds, option));
}

/**
* Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in seconds.
* To get the expiration with millisecond precision, use {@link pexpiretime}.
*
* See https://valkey.io/commands/expiretime/ for details.
*
* @param key - The `key` to determine the expiration value of.
*
* Command Response - The expiration Unix timestamp in seconds, `-2` if `key` does not exist or `-1` if `key` exists but has no associated expire.
*
* since Valkey version 7.0.0.
*/
public expireTime(key: string): T {
return this.addAndReturn(createExpireTime(key));
}

/** Sets a timeout on `key` in milliseconds. After the timeout has expired, the key will automatically be deleted.
* If `key` already has an existing expire set, the time to live is updated to the new value.
* If `milliseconds` is non-positive number, the key will be deleted rather than expired.
Expand Down Expand Up @@ -1377,6 +1395,21 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
);
}

/**
* Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in milliseconds.
*
* See https://valkey.io/commands/pexpiretime/ for details.
*
* @param key - The `key` to determine the expiration value of.
*
* Command Response - The expiration Unix timestamp in seconds, `-2` if `key` does not exist or `-1` if `key` exists but has no associated expire.
*
* since Valkey version 7.0.0.
*/
public pexpireTime(key: string): T {
return this.addAndReturn(createPExpireTime(key));
}

/** Returns the remaining time to live of `key` that has a timeout.
* See https://valkey.io/commands/ttl/ for details.
*
Expand Down
22 changes: 20 additions & 2 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2688,6 +2688,12 @@ export function runBaseTests<Context>(config: {
ExpireOptions.HasExistingExpiry,
),
).toEqual(true);
expect(await client.expiretime(key)).toBeGreaterThan(
Math.floor(Date.now() / 1000),
);
expect(await client.pexpiretime(key)).toBeGreaterThan(
Date.now(),
);
}

expect(await client.ttl(key)).toBeLessThanOrEqual(15);
Expand Down Expand Up @@ -2751,7 +2757,7 @@ export function runBaseTests<Context>(config: {
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`expire, pexpire, expireAt and pexpireAt with timestamp in the past or negative timeout_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
await runTest(async (client: BaseClient, cluster) => {
const key = uuidv4();
expect(await client.set(key, "foo")).toEqual("OK");
expect(await client.ttl(key)).toEqual(-1);
Expand All @@ -2769,6 +2775,13 @@ export function runBaseTests<Context>(config: {
).toEqual(true);
expect(await client.ttl(key)).toEqual(-2);
expect(await client.set(key, "foo")).toEqual("OK");

// no timeout set yet
if (!cluster.checkIfServerVersionLessThan("7.0.0")) {
expect(await client.expiretime(key)).toEqual(-1);
expect(await client.pexpiretime(key)).toEqual(-1);
}

expect(
await client.pexpireAt(
key,
Expand All @@ -2784,7 +2797,7 @@ export function runBaseTests<Context>(config: {
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`expire, pexpire, expireAt, pexpireAt and ttl with non-existing key_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
await runTest(async (client: BaseClient, cluster) => {
const key = uuidv4();
expect(await client.expire(key, 10)).toEqual(false);
expect(await client.pexpire(key, 10000)).toEqual(false);
Expand All @@ -2801,6 +2814,11 @@ export function runBaseTests<Context>(config: {
),
).toEqual(false);
expect(await client.ttl(key)).toEqual(-2);

if (!cluster.checkIfServerVersionLessThan("7.0.0")) {
expect(await client.expiretime(key)).toEqual(-2);
expect(await client.pexpiretime(key)).toEqual(-2);
}
}, protocol);
},
config.timeout,
Expand Down
9 changes: 9 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,15 @@ export async function transactionTest(
responseData.push(["echo(value)", value]);
baseTransaction.persist(key1);
responseData.push(["persist(key1)", false]);

if (gte(version, "7.0.0")) {
baseTransaction.expireTime(key1);
responseData.push(["expiretime(key1)", -1]);

baseTransaction.pexpireTime(key1);
responseData.push(["pexpiretime(key1)", -1]);
}

baseTransaction.set(key2, "baz", { returnOldValue: true });
responseData.push(['set(key2, "baz", { returnOldValue: true })', null]);
baseTransaction.customCommand(["MGET", key1, key2]);
Expand Down

0 comments on commit 42cd2f6

Please sign in to comment.