diff --git a/commands/hexpire.md b/commands/hexpire.md new file mode 100644 index 000000000..f0143259c --- /dev/null +++ b/commands/hexpire.md @@ -0,0 +1,26 @@ +The `HEXPIRE` command allows manipulating the expiration time for existing hash fields. +When set, the expiration time of a hash field will determine when the field will be automatically deleted. +Note, that providing a millisecond time of '0' will cause immediate expiration and deletion of the field(s). + +## Options + +The `HEXPIRE` command supports a set of options that modify its behavior: + +* NX — For each specified field, set expiration only when the field has no expiration. +* XX — For each specified field, set expiration only when the field has an existing expiration. +* GT — For each specified field, set expiration only when the new expiration is greater than current one. +* LT — For each specified field, set expiration only when the new expiration is less than current one. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HEXPIRE myhash 10 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 8 +3) (integer) 8 +``` diff --git a/commands/hexpireat.md b/commands/hexpireat.md new file mode 100644 index 000000000..32b575cea --- /dev/null +++ b/commands/hexpireat.md @@ -0,0 +1,30 @@ +`HEXPIREAT` has the same effect and semantic as [`HEXPIRE`](hexpire.md), but instead of +specifying the number of seconds representing the TTL (time to live), it takes +an absolute Unix timestamp (seconds since January 1, 1970). A +timestamp in the past will delete the key immediately. + +For the specific semantics of the command refer to the documentation of +[`HEXPIRE`](hexpire.md). + +## Options + +The `HEXPIREAT` command supports a set of options that modify its behavior: + +* NX — For each specified field, set expiration only when the field has no expiration. +* XX — For each specified field, set expiration only when the field has an existing expiration. +* GT — For each specified field, set expiration only when the new expiration is greater than current one. +* LT — For each specified field, set expiration only when the new expiration is less than current one. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HEXPIREAT myhash 1754846600 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HEXPIRETIME myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 1754846600 +3) (integer) 1754846600 +``` diff --git a/commands/hexpiretime.md b/commands/hexpiretime.md new file mode 100644 index 000000000..2fc020a86 --- /dev/null +++ b/commands/hexpiretime.md @@ -0,0 +1,18 @@ +The `HEXPIRETIME` command returns the absolute Unix timestamp (since January 1, 1970) in seconds at which the given hash field(s) will expire or -1 if the hash field doesn't have expiration time. + +See also the [`HPEXPIRETIME`](hpexpiretime.md) command that returns the same information with milliseconds resolution. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HEXPIREAT myhash 1754846600 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HEXPIRETIME myhash FIELDS 4 f1 f2 f3 non-exist +1) (integer) -1 +2) (integer) 1754846600 +3) (integer) 1754846600 +4) (integer) -2 +``` diff --git a/commands/hgetex.md b/commands/hgetex.md new file mode 100644 index 000000000..95b6868bf --- /dev/null +++ b/commands/hgetex.md @@ -0,0 +1,41 @@ +The `HGETEX` command returns the value of one or more fields of a given hash key, and optionally manipulates their expiration time. +The command will return an array in the size of the number of requested fields. +Without providing any optional flags, this command behaves exactly like a normal [`HMGET`](hmget.md) command. + +## Options + +The `HGETEX` command supports a set of options that modify its behavior: + +* EX seconds — Set the specified expiration time, in seconds. +* PX milliseconds — Set the specified expiration time, in milliseconds. +* EXAT `unix-time-seconds` — Set the specified Unix time at which the fields will expire, in seconds. +* PXAT `unix-time-milliseconds` — Set the specified Unix time at which the fields will expire, in milliseconds. +* PERSIST — Remove the expiration time associated with the fields. + +Note for the following: + +1. The EX, PX, EXAT, PXAT, and PERSIST options are mutually exclusive. +2. Providing '0' expiration TTL via `EX` or `PX` optional arguments will cause the specified fields to expire immediately and be removed from the hash. +3. Providing past expiration time via `EXAT` or `PXAT` optional arguments will cause the specified fields to expire immediately and be removed from the hash. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HGETEX myhash EX 10 FIELDS 2 f2 f3 +1) "v2" +2) "v3" +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 8 +3) (integer) 8 +127.0.0.1:6379> HGETEX myhash EX 0 FIELDS 3 f1 f2 f3 +1) "v1" +2) "v2" +3) "v3" +127.0.0.1:6379> HGETEX myhash FIELDS 3 f1 f2 f3 +1) (nil) +2) (nil) +3) (nil) +``` diff --git a/commands/hpersist.md b/commands/hpersist.md new file mode 100644 index 000000000..9daa1ecfe --- /dev/null +++ b/commands/hpersist.md @@ -0,0 +1,24 @@ +The `HPERSIST` remove the existing expiration on a hash key's field(s), turning the field(s) from volatile (a field with expiration set) +to persistent (a field that will never expire as no TTL (time to live) is associated). + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HEXPIRE myhash 1000 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 998 +3) (integer) 998 +127.0.0.1:6379> HPERSIST myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 1 +3) (integer) 1 +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) -1 +3) (integer) -1 +``` diff --git a/commands/hpexpire.md b/commands/hpexpire.md new file mode 100644 index 000000000..64fc09b31 --- /dev/null +++ b/commands/hpexpire.md @@ -0,0 +1,26 @@ +This command works exactly like [`HEXPIRE`](hexpire.md) but the time to live of the key is +specified in milliseconds instead of seconds. +Note, that providing a millisecond time of '0' will cause immediate expiration and reclamation of the field(s). + +## Options + +The `HPXPIRE` command supports a set of options that modify its behavior: + +* NX — For each specified field, set expiration only when the field has no expiration. +* XX — For each specified field, set expiration only when the field has an existing expiration. +* GT — For each specified field, set expiration only when the new expiration is greater than current one. +* LT — For each specified field, set expiration only when the new expiration is less than current one. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HPEXPIRE myhash 10000 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HPTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 9597 +3) (integer) 9597 +``` diff --git a/commands/hpexpireat.md b/commands/hpexpireat.md new file mode 100644 index 000000000..50a577285 --- /dev/null +++ b/commands/hpexpireat.md @@ -0,0 +1,30 @@ +`HEXPIREAT` has the same effect and semantic as [`HPEXPIRE`](hpexpire.md), but instead of +specifying the number of milliseconds representing the TTL (time to live), it takes +an absolute Unix timestamp (milliseconds since January 1, 1970). A +timestamp in the past will delete the key immediately. + +For the specific semantics of the command refer to the documentation of +[`HPEXPIRE`](hpexpire.md). + +## Options + +The `HPEXPIREAT` command supports a set of options that modify its behavior: + +* NX — For each specified field, set expiration only when the field has no expiration. +* XX — For each specified field, set expiration only when the field has an existing expiration. +* GT — For each specified field, set expiration only when the new expiration is greater than current one. +* LT — For each specified field, set expiration only when the new expiration is less than current one. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HPEXPIREAT myhash 1754847944000 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HPEXPIRETIME myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 1754847944000 +3) (integer) 1754847944000 +``` diff --git a/commands/hpexpiretime.md b/commands/hpexpiretime.md new file mode 100644 index 000000000..c6c969632 --- /dev/null +++ b/commands/hpexpiretime.md @@ -0,0 +1,18 @@ +The `HPEXPIRETIME` command returns the absolute Unix timestamp (since January 1, 1970) in milliseconds at which the given hash field(s) will expire. + +See also the [`HEXPIRETIME`](hexpiretime.md) command which returns the same information with seconds resolution. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HPEXPIREAT myhash 1754847944000 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HPEXPIRETIME myhash FIELDS 4 f1 f2 f3 non-exist +1) (integer) -1 +2) (integer) 1754847944000 +3) (integer) 1754847944000 +4) (integer) -2 +``` diff --git a/commands/hpttl.md b/commands/hpttl.md new file mode 100644 index 000000000..223027c58 --- /dev/null +++ b/commands/hpttl.md @@ -0,0 +1,19 @@ +Like [`HTTL`](httl.md) this command returns the remaining time to live of hash field(s) that has an associated expiration time, +with the sole difference that `HTTL` returns the amount of remaining +time in seconds while `HPTTL` returns it in milliseconds. + +See also the [`HTTL`](httl.md) command that returns the same information with seconds resolution. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HPEXPIRE myhash 10000 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HPTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 9597 +3) (integer) 9597 +``` diff --git a/commands/hsetex.md b/commands/hsetex.md new file mode 100644 index 000000000..6d95f4666 --- /dev/null +++ b/commands/hsetex.md @@ -0,0 +1,74 @@ +The `HSETEX` command allows setting the value of one or more fields of a given hash key, and optionally manipulating their expiration time. +The command will return 1 in case all provided fields have been set or 0 in case `FNX` or `FXX` were provided and non of the specified fields were set. +Without providing any optional flags, this command behaves exactly like a normal [`HSET`](hset.md) command. + +## Options + +The `HSETEX` command supports a set of options that modify its behavior: + +* FNX — Only set the fields if none of them already exist. +* FXX — Only set the fields if all of them already exist. +* EX seconds — Set the specified expiration time in seconds. +* PX milliseconds — Set the specified expiration time in milliseconds. +* EXAT `unix-time-seconds` — Set the specified Unix time in seconds for when the fields will expire. +* PXAT `unix-time-milliseconds` — Set the specified Unix time in milliseconds at which the fields will expire. +* KEEPTTL — Retain the TTL associated with the fields. + +Note for the following: + +1. The EX, PX, EXAT, PXAT, and KEEPTTL options are mutually exclusive. +2. Setting a value on a volatile hash field (A field which has an assigned expiration time) will remove the expiration for that field. +3. Providing '0' expiration TTL via `EX` or `PX` optional arguments will result in the specified fields immediately expiring and being removed from the hash. +4. Providing past expiration time via `EXAT` or `PXAT` optional arguments will result in the specified fields immediately expiring and being removed from the hash. + +## Examples + +Add 3 new items without expiration time to a 'myhash' +``` +127.0.0.1:6379> HSETEX myhash FIELDS 3 f1 v1 f2 v2 f3 v3 +(integer) 1 +``` + +Unsuccessful attempt setting expiration time on EXISTING fields +``` +127.0.0.1:6379> HSETEX myhash FNX EX 10 FIELDS 2 f2 v2 f3 v3 +(integer) 0 +``` + +Successful attempt setting expiration time on EXISTING fields +``` +127.0.0.1:6379> HSETEX myhash FXX EX 10 FIELDS 2 f2 v2 f3 v3 +(integer) 1 +``` + +Verify hash fields expiration time: +``` +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) 8 +3) (integer) 8 +``` + +Override all hash items will also persist the fields +``` +127.0.0.1:6379> HSETEX myhash FIELDS 3 f1 v1 f2 v2 f3 v3 +(integer) 1 +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -1 +2) (integer) -1 +3) (integer) -1 +``` + +Setting expiration time in the past will remove all the elements in the hash: +``` +127.0.0.1:6379> HSETEX EX 0 myhash FIELDS 3 f1 v1 f2 v2 f3 v3 +(integer) 1 +127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3 +1) (integer) -2 +2) (integer) -2 +3) (integer) -2 +127.0.0.1:6379> HLEN myhash +(integer) 0 +127.0.0.1:6379> EXISTS myhash +(integer) 0 +``` diff --git a/commands/httl.md b/commands/httl.md new file mode 100644 index 000000000..d27bc8b1b --- /dev/null +++ b/commands/httl.md @@ -0,0 +1,20 @@ +The `HTTL` command returns the remaining time to live of hash field(s) with associated expiration time(s). +This introspection capability allows a Valkey client to check how many seconds a +given hash field will continue to be part of the hash object. + +See also the [`HPTTL`](hpttl.md) command that returns the same information with milliseconds resolution. + +## Examples + +``` +127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3 +(integer) 3 +27.0.0.1:6379> HEXPIRE myhash 10 FIELDS 2 f2 f3 +1) (integer) 1 +2) (integer) 1 +127.0.0.1:6379> HTTL myhash FIELDS 4 f1 f2 f3 non-exist +1) (integer) -1 +2) (integer) 8 +3) (integer) 8 +4) (integer) -2 +``` diff --git a/resp2_replies.json b/resp2_replies.json index b6c4ad43d..0c1bffc1f 100644 --- a/resp2_replies.json +++ b/resp2_replies.json @@ -661,6 +661,72 @@ "HVALS": [ "[Array reply](../topics/protocol.md#arrays): a list of values in the hash, or an empty list when the key does not exist." ], + "HSETEX": [ + "One of the following:", + "* [Integer reply](../topics/protocol.md#integers): `0` if none of the provided fields' values and/or expiration times were set.", + "* [Integer reply](../topics/protocol.md#integers): `1` if all the fields' values and/or expiration times were set." + ], + "HGETEX": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the given fields, in the same order as they are requested." + ], + "HEXPIRE": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HPEXPIRE": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HEXPIREAT": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HPEXPIREAT": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HPERSIST": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key does not exist.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* 1: The expiration time was removed from the hash key field." + ], + "HTTL": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the remaining time-to-live of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in seconds." + ], + "HPTTL": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the remaining time-to-live of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in milliseconds." + ], + "HEXPIRETIME": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the absolute expiry timestamp of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in seconds." + ], + "HPEXPIRETIME": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the absolute expiry timestamp of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in milliseconds." + ], "INCR": [ "[Integer reply](../topics/protocol.md#integers): the value of the key after the increment." ], diff --git a/resp3_replies.json b/resp3_replies.json index 167e4b013..b522a2163 100644 --- a/resp3_replies.json +++ b/resp3_replies.json @@ -663,6 +663,72 @@ "HVALS": [ "[Array reply](../topics/protocol.md#arrays): a list of values in the hash, or an empty list when the key does not exist." ], + "HSETEX": [ + "One of the following:", + "* [Integer reply](../topics/protocol.md#integers): `0` if none of the provided fields value and or expiration time was set.", + "* [Integer reply](../topics/protocol.md#integers): `1` if all the fields value and or expiration time was set." + ], + "HGETEX": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the given fields, in the same order as they are requested." + ], + "HEXPIRE": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HPEXPIRE": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HEXPIREAT": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HPEXPIREAT": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the HASH, or key does not exist.", + "* 0: The specified NX | XX | GT | LT condition has not been met.", + "* 1: The expiration time was applied.", + "* 2: When called with 0 seconds." + ], + "HPERSIST": [ + "[Array reply](../topics/protocol.md#arrays): a list of integer codes indicating the result of setting expiry on each specified field, in the same order as the fields are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key does not exist.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* 1: The expiration time was removed from the hash key field." + ], + "HTTL": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the remaining time-to-live of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in seconds." + ], + "HPTTL": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the remaining time-to-live of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in milliseconds." + ], + "HEXPIRETIME": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the absolute expiry timestamp of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in seconds." + ], + "HPEXPIRETIME": [ + "[Array reply](../topics/protocol.md#arrays): a list of values associated with the result of getting the absolute expiry timestamp of the specific fields, in the same order as they are requested.", + "* -2: Field does not exist in the provided hash key, or the hash key is empty.", + "* -1: Field exists in the provided hash key, but has no expiration associated with it.", + "* [Integer](../topics/protocol.md#integers): The expiration time associated with the hash key field, in milliseconds." + ], "INCR": [ "[Integer reply](../topics/protocol.md#integers): the value of the key after the increment." ], diff --git a/topics/hashes.md b/topics/hashes.md index f5242ffcc..b0abb34fb 100644 --- a/topics/hashes.md +++ b/topics/hashes.md @@ -82,6 +82,27 @@ See the [complete list of hash commands](../commands/#hash). 2) "1" ``` +## Field expiration + +In Valkey 9.0 we added the ability to associate an expiration time with a hash field. When set, the field and it's corresponding value are automatically deleted after the time has past. +Once a hash field expiration time is past, it will no longer be available and all of the hash command APIs will treat this field as "nonexistent". +Note that expired hash fields are deleted via a periodic job. +For this reason it might take time between when fields logically expire and when hash fields are deleted. +During this time, logically expired fields still consume memory and some some hash commands (e.g. [`HLEN`](../commands/hlen.md)) might still take logically expired fields into account in hash object cardinality calculations. +Another side effect of using volatile fields (fields with time to live) in hash objects, is the ability to randomly choose from hash objects. When large hash objects have most of their volatile fields logically expired, some commands like [`HRANDFIELD`](../commands/hrandfield.md) might not be able to collect elements which are not logically expired and may return an empty reply. + +### Command API + +[`HEXPIRE`](../commands/hexpire.md), [`HPEXPIRE`](../commands/hpexpire.md), [`HEXPIREAT`](../commands/hexpireat.md), [`HPEXPIREAT`](../commands/hpexpireat.md) and [`HPERSIST`](../commands/hpersist.md) commands are used in order to set or manipulate the expiration time of specific hash fields. + +[`HEXPIRETIME`](../commands/hexpiretime.md), [`HEXPIRETIME`](../commands/hpexpiretime.md), [`HTTL`](../commands/httl.md) and [`HPTTL]`(../commands/hpttl.md) commands are used in order to query the expiration time of specific hash fields. + +[`HSETEX`](../commands/hsetex.md) allows setting multiple hash fields and values while also associate an expiration time with each field. + +[`HGETEX`](../commands/hgetex.md) allows fetching multiple hash fields values while also mutating their expiration time. + +Note that some commands which override hash fields (e.g. `HSET` and `HMSET`) will remove an expiration time associated with a hash field. +The [`HSETEX`](../commands/hsetex.md) supports the `KEEPTTL` flag, which allows overriding hash fields without mutating their expiration time. ## Performance diff --git a/topics/notifications.md b/topics/notifications.md index 5cbdda492..700c35ac6 100644 --- a/topics/notifications.md +++ b/topics/notifications.md @@ -108,9 +108,12 @@ Different commands generate different kind of events according to the following * `LTRIM` generates an `ltrim` event, and additionally a `del` event if the resulting list is empty and the key is removed. * `RPOPLPUSH` and `BRPOPLPUSH` generate an `rpop` event and an `lpush` event. In both cases the order is guaranteed (the `lpush` event will always be delivered after the `rpop` event). Additionally a `del` event will be generated if the resulting list is zero length and the key is removed. * `LMOVE` and `BLMOVE` generate an `lpop`/`rpop` event (depending on the wherefrom argument) and an `lpush`/`rpush` event (depending on the whereto argument). In both cases the order is guaranteed (the `lpush`/`rpush` event will always be delivered after the `lpop`/`rpop` event). Additionally a `del` event will be generated if the resulting list is zero length and the key is removed. -* `HSET`, `HSETNX` and `HMSET` all generate a single `hset` event. +* `HSET`, `HSETNX`, `HMSET` and `HSETEX` generate a single `hset` event if the specified fields were added or modified. * `HINCRBY` generates an `hincrby` event. * `HINCRBYFLOAT` generates an `hincrbyfloat` event. +* `HEXPIRE` and all its variants (`HPEXPIRE`, `HPEXPIRE`, `HEXPIREAT` and `HPEXPIREAT`) generate a single `hexpire` event when called with a positive timeout (or a future timestamp). Note that when these commands are called with a negative timeout value or timestamp in the past, only a single `hexpired` event is generated and if the hash object has no more items left it will be deleted and a `del` event is generated as well. +* `HSETEX` and `HGETEX` generate a single `hexpire` event when called with a positive timeout (or a future timestamp). Note that when these commands are called with a negative timeout value or timestamp in the past, only a single `hexpired` event is generated and if the hash object has no more items left it will be deleted and a `del` event is generated as well. +* `HPERSIST` and `HGETEX`, will generate an `hpersist` event if at least 1 hash field expiration time was removed. * `HDEL` generates a single `hdel` event, and an additional `del` event if the resulting hash is empty and the key is removed. * `SADD` generates a single `sadd` event, even in the variadic case. * `SREM` generates a single `srem` event, and an additional `del` event if the resulting set is empty and the key is removed. @@ -163,9 +166,12 @@ Keys with a time to live associated are expired by Valkey in two ways: The `expired` events are generated when a key is accessed and is found to be expired by one of the above systems, as a result there are no guarantees that the Valkey server will be able to generate the `expired` event at the time the key time to live reaches the value of zero. -If no command targets the key constantly, and there are many keys with a TTL associated, there can be a significant delay between the time the key time to live drops to zero, and the time the `expired` event is generated. +Since Valkey 9.0, hash fields can also have an associated time to live. +Hash fields are deleted when explicitly provided an expiration time in the past or via the same background job which is also responsible to expire keys. For that reason, there are no guarantees that the Valkey server will be able to generate the `hexpired` event at the time the hash field time to live reaches the value of zero. + +Basically `expired` and `hexpired` events **are generated when the Valkey server deletes a key** and not when the time to live theoretically reaches the value of zero. +For that reason there can be a significant delay between the time the key time to live drops to zero, and the time the corresponding event is generated. -Basically `expired` events **are generated when the Valkey server deletes the key** and not when the time to live theoretically reaches the value of zero. ### Events in a cluster