diff --git a/CHANGELOG.md b/CHANGELOG.md index 28c26235ab..db4d89bdb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Node: Added ZREMRANGEBYRANK command ([#924](https://github.com/aws/glide-for-redis/pull/924)) * Node: Added Xadd, Xtrim commands. ([#1057](https://github.com/aws/glide-for-redis/pull/1057)) * Python: Added json module and JSON.SET JSON.GET commands ([#1056](https://github.com/aws/glide-for-redis/pull/1056)) +* Node: Added Time command. ([#1114](https://github.com/aws/glide-for-redis/pull/1114)) #### Features diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 805eae1f3e..652334fa7f 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -132,6 +132,7 @@ enum RequestType { JsonSet = 88; JsonGet = 89; ZRemRangeByScore = 90; + Time = 91; } message Command { diff --git a/glide-core/src/socket_listener.rs b/glide-core/src/socket_listener.rs index d64f890232..5c5bd3be7b 100644 --- a/glide-core/src/socket_listener.rs +++ b/glide-core/src/socket_listener.rs @@ -362,6 +362,7 @@ fn get_command(request: &Command) -> Option { RequestType::JsonSet => Some(cmd("JSON.SET")), RequestType::JsonGet => Some(cmd("JSON.GET")), RequestType::ZRemRangeByScore => Some(cmd("ZREMRANGEBYSCORE")), + RequestType::Time => Some(cmd("TIME")), } } diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 72a17c00ef..10d59ab058 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1041,3 +1041,10 @@ export function createXtrim( addTrimOptions(options, args); return createCommand(RequestType.XTrim, args); } + +/** + * @internal + */ +export function createTime(): redis_request.Command { + return createCommand(RequestType.Time, []); +} diff --git a/node/src/RedisClient.ts b/node/src/RedisClient.ts index 4196864150..ebbf11a525 100644 --- a/node/src/RedisClient.ts +++ b/node/src/RedisClient.ts @@ -16,6 +16,7 @@ import { createInfo, createPing, createSelect, + createTime, } from "./Commands"; import { connection_request } from "./ProtobufMessage"; import { Transaction } from "./Transaction"; @@ -213,4 +214,15 @@ export class RedisClient extends BaseClient { public configSet(parameters: Record): Promise<"OK"> { return this.createWritePromise(createConfigSet(parameters)); } + + /** Returns the server time + * See https://redis.io/commands/time/ for details. + * + * @returns - The current server time as a two items `array`: + * A Unix timestamp and the amount of microseconds already elapsed in the current second. + * The returned `array` is in a [Unix timestamp, Microseconds already elapsed] format. + */ + public time(): Promise<[string, string]> { + return this.createWritePromise(createTime()); + } } diff --git a/node/src/RedisClusterClient.ts b/node/src/RedisClusterClient.ts index f4477837ec..3aef7ae6bc 100644 --- a/node/src/RedisClusterClient.ts +++ b/node/src/RedisClusterClient.ts @@ -15,6 +15,7 @@ import { createCustomCommand, createInfo, createPing, + createTime, } from "./Commands"; import { RequestError } from "./Errors"; import { connection_request, redis_request } from "./ProtobufMessage"; @@ -386,4 +387,18 @@ export class RedisClusterClient extends BaseClient { toProtobufRoute(route), ); } + + /** Returns the server time. + * See https://redis.io/commands/time/ for details. + * + * @param route - The command will be routed to a random node, unless `route` is provided, in which + * case the client will route the command to the nodes defined by `route`. + * + * @returns - The current server time as a two items `array`: + * A Unix timestamp and the amount of microseconds already elapsed in the current second. + * The returned `array` is in a [Unix timestamp, Microseconds already elapsed] format. + */ + public time(route?: Routes): Promise<[string, string]> { + return this.createWritePromise(createTime(), toProtobufRoute(route)); + } } diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 6d671ab826..14f09b3980 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -65,6 +65,7 @@ import { createSismember, createStrlen, createTTL, + createTime, createType, createUnlink, createXadd, @@ -1081,6 +1082,17 @@ export class BaseTransaction> { public xtrim(key: string, options: StreamTrimOptions): T { return this.addAndReturn(createXtrim(key, options)); } + + /** Returns the server time. + * See https://redis.io/commands/time/ for details. + * + * @returns - The current server time as a two items `array`: + * A Unix timestamp and the amount of microseconds already elapsed in the current second. + * The returned `array` is in a [Unix timestamp, Microseconds already elapsed] format. + */ + public time(): T { + return this.addAndReturn(createTime()); + } } /** diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 92603ecad0..b11882a6eb 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -1888,6 +1888,23 @@ export function runBaseTests(config: { }, config.timeout, ); + + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + "time test_%p", + async (protocol) => { + await runTest(async (client: BaseClient) => { + // Take the time now, convert to 10 digits and subtract 1 second + const now = Math.floor(new Date().getTime() / 1000 - 1); + const result = await client.time(); + expect(result?.length).toEqual(2); + expect(Number(result?.at(0))).toBeGreaterThan(now); + // Test its not more than 1 second + expect(Number(result?.at(1))).toBeLessThan(1000000); + client.close(); + }, protocol); + }, + config.timeout, + ); } export function runCommonTests(config: {