11import {
2+ _stringMapEntries ,
23 AnyObject ,
34 CommonLogger ,
45 NullableBuffer ,
56 NullableString ,
67 Promisable ,
8+ StringMap ,
79 UnixTimestampNumber ,
810} from '@naturalcycles/js-lib'
911import { ReadableTyped } from '@naturalcycles/nodejs-lib'
@@ -157,6 +159,25 @@ export class RedisClient implements CommonClient {
157159 return await this . redis ( ) . hincrby ( key , field , increment )
158160 }
159161
162+ async hincrBatch ( key : string , incrementTuples : [ string , number ] [ ] ) : Promise < [ string , number ] [ ] > {
163+ const results : StringMap < number | undefined > = { }
164+
165+ await this . withPipeline ( async pipeline => {
166+ for ( const [ field , increment ] of incrementTuples ) {
167+ pipeline . hincrby ( key , field , increment , ( _err , newValue ) => {
168+ results [ field ] = newValue
169+ } )
170+ }
171+ } )
172+
173+ const validResults = _stringMapEntries ( results ) . filter ( ( [ _ , v ] ) => v !== undefined ) as [
174+ string ,
175+ number ,
176+ ] [ ]
177+
178+ return validResults
179+ }
180+
160181 async setWithTTL (
161182 key : string ,
162183 value : string | number | Buffer ,
@@ -165,14 +186,19 @@ export class RedisClient implements CommonClient {
165186 await this . redis ( ) . set ( key , value , 'EXAT' , expireAt )
166187 }
167188
168- async hsetWithTTL ( key : string , value : AnyObject , expireAt : UnixTimestampNumber ) : Promise < void > {
169- const valueKeys = Object . keys ( value )
170- const numberOfKeys = valueKeys . length
171- const keyList = valueKeys . join ( ' ' )
172- const commandString = `HEXPIREAT ${ key } ${ expireAt } FIELDS ${ numberOfKeys } ${ keyList } `
173- const [ command , ...args ] = commandString . split ( ' ' )
174- await this . redis ( ) . hset ( key , value )
175- await this . redis ( ) . call ( command ! , args )
189+ async hsetWithTTL (
190+ _key : string ,
191+ _value : AnyObject ,
192+ _expireAt : UnixTimestampNumber ,
193+ ) : Promise < void > {
194+ throw new Error ( 'Not supported until Redis 7.4.0' )
195+ // const valueKeys = Object.keys(value)
196+ // const numberOfKeys = valueKeys.length
197+ // const keyList = valueKeys.join(' ')
198+ // const commandString = `HEXPIREAT ${key} ${expireAt} FIELDS ${numberOfKeys} ${keyList}`
199+ // const [command, ...args] = commandString.split(' ')
200+ // await this.redis().hset(key, value)
201+ // await this.redis().call(command!, args)
176202 }
177203
178204 async mset ( obj : Record < string , string | number > ) : Promise < void > {
@@ -187,6 +213,25 @@ export class RedisClient implements CommonClient {
187213 return await this . redis ( ) . incrby ( key , by )
188214 }
189215
216+ async incrBatch ( incrementTuples : [ string , number ] [ ] ) : Promise < [ string , number ] [ ] > {
217+ const results : StringMap < number | undefined > = { }
218+
219+ await this . withPipeline ( async pipeline => {
220+ for ( const [ key , increment ] of incrementTuples ) {
221+ pipeline . incrby ( key , increment , ( _err , newValue ) => {
222+ results [ key ] = newValue
223+ } )
224+ }
225+ } )
226+
227+ const validResults = _stringMapEntries ( results ) . filter ( ( [ _ , v ] ) => v !== undefined ) as [
228+ string ,
229+ number ,
230+ ] [ ]
231+
232+ return validResults
233+ }
234+
190235 async ttl ( key : string ) : Promise < number > {
191236 return await this . redis ( ) . ttl ( key )
192237 }
0 commit comments