ultra-smart-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "redis/hash_ring"
4
+
5
+ class Redis
6
+ class Distributed
7
+ class CannotDistribute < RuntimeError
8
+ def initialize(command)
9
+ @command = command
10
+ end
11
+
12
+ def message
13
+ "#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need " \
14
+ "to be on the same server or because we cannot guarantee that the operation will be atomic."
15
+ end
16
+ end
17
+
18
+ attr_reader :ring
19
+
20
+ def initialize(node_configs, options = {})
21
+ @tag = options[:tag] || /^\{(.+?)\}/
22
+ @ring = options[:ring] || HashRing.new
23
+ @node_configs = node_configs.map(&:dup)
24
+ @default_options = options.dup
25
+ node_configs.each { |node_config| add_node(node_config) }
26
+ @subscribed_node = nil
27
+ @watch_key = nil
28
+ end
29
+
30
+ def node_for(key)
31
+ key = key_tag(key.to_s) || key.to_s
32
+ raise CannotDistribute, :watch if @watch_key && @watch_key != key
33
+
34
+ @ring.get_node(key)
35
+ end
36
+
37
+ def nodes
38
+ @ring.nodes
39
+ end
40
+
41
+ def add_node(options)
42
+ options = { url: options } if options.is_a?(String)
43
+ options = @default_options.merge(options)
44
+ options.delete(:tag)
45
+ options.delete(:ring)
46
+ @ring.add_node Redis.new(options)
47
+ end
48
+
49
+ # Change the selected database for the current connection.
50
+ def select(db)
51
+ on_each_node :select, db
52
+ end
53
+
54
+ # Ping the server.
55
+ def ping
56
+ on_each_node :ping
57
+ end
58
+
59
+ # Echo the given string.
60
+ def echo(value)
61
+ on_each_node :echo, value
62
+ end
63
+
64
+ # Close the connection.
65
+ def quit
66
+ on_each_node :quit
67
+ end
68
+
69
+ def close
70
+ on_each_node :close
71
+ end
72
+
73
+ # Asynchronously save the dataset to disk.
74
+ def bgsave
75
+ on_each_node :bgsave
76
+ end
77
+
78
+ # Return the number of keys in the selected database.
79
+ def dbsize
80
+ on_each_node :dbsize
81
+ end
82
+
83
+ # Remove all keys from all databases.
84
+ def flushall
85
+ on_each_node :flushall
86
+ end
87
+
88
+ # Remove all keys from the current database.
89
+ def flushdb
90
+ on_each_node :flushdb
91
+ end
92
+
93
+ # Get information and statistics about the server.
94
+ def info(cmd = nil)
95
+ on_each_node :info, cmd
96
+ end
97
+
98
+ # Get the UNIX time stamp of the last successful save to disk.
99
+ def lastsave
100
+ on_each_node :lastsave
101
+ end
102
+
103
+ # Listen for all requests received by the server in real time.
104
+ def monitor
105
+ raise NotImplementedError
106
+ end
107
+
108
+ # Synchronously save the dataset to disk.
109
+ def save
110
+ on_each_node :save
111
+ end
112
+
113
+ # Get server time: an UNIX timestamp and the elapsed microseconds in the current second.
114
+ def time
115
+ on_each_node :time
116
+ end
117
+
118
+ # Remove the expiration from a key.
119
+ def persist(key)
120
+ node_for(key).persist(key)
121
+ end
122
+
123
+ # Set a key's time to live in seconds.
124
+ def expire(key, seconds, **kwargs)
125
+ node_for(key).expire(key, seconds, **kwargs)
126
+ end
127
+
128
+ # Set the expiration for a key as a UNIX timestamp.
129
+ def expireat(key, unix_time, **kwargs)
130
+ node_for(key).expireat(key, unix_time, **kwargs)
131
+ end
132
+
133
+ # Get the expiration for a key as a UNIX timestamp.
134
+ def expiretime(key)
135
+ node_for(key).expiretime(key)
136
+ end
137
+
138
+ # Get the time to live (in seconds) for a key.
139
+ def ttl(key)
140
+ node_for(key).ttl(key)
141
+ end
142
+
143
+ # Set a key's time to live in milliseconds.
144
+ def pexpire(key, milliseconds, **kwarg)
145
+ node_for(key).pexpire(key, milliseconds, **kwarg)
146
+ end
147
+
148
+ # Set the expiration for a key as number of milliseconds from UNIX Epoch.
149
+ def pexpireat(key, ms_unix_time, **kwarg)
150
+ node_for(key).pexpireat(key, ms_unix_time, **kwarg)
151
+ end
152
+
153
+ # Get the expiration for a key as number of milliseconds from UNIX Epoch.
154
+ def pexpiretime(key)
155
+ node_for(key).pexpiretime(key)
156
+ end
157
+
158
+ # Get the time to live (in milliseconds) for a key.
159
+ def pttl(key)
160
+ node_for(key).pttl(key)
161
+ end
162
+
163
+ # Return a serialized version of the value stored at a key.
164
+ def dump(key)
165
+ node_for(key).dump(key)
166
+ end
167
+
168
+ # Create a key using the serialized value, previously obtained using DUMP.
169
+ def restore(key, ttl, serialized_value, **options)
170
+ node_for(key).restore(key, ttl, serialized_value, **options)
171
+ end
172
+
173
+ # Transfer a key from the connected instance to another instance.
174
+ def migrate(_key, _options)
175
+ raise CannotDistribute, :migrate
176
+ end
177
+
178
+ # Delete a key.
179
+ def del(*args)
180
+ args.flatten!(1)
181
+ keys_per_node = args.group_by { |key| node_for(key) }
182
+ keys_per_node.inject(0) do |sum, (node, keys)|
183
+ sum + node.del(*keys)
184
+ end
185
+ end
186
+
187
+ # Unlink keys.
188
+ def unlink(*args)
189
+ args.flatten!(1)
190
+ keys_per_node = args.group_by { |key| node_for(key) }
191
+ keys_per_node.inject(0) do |sum, (node, keys)|
192
+ sum + node.unlink(*keys)
193
+ end
194
+ end
195
+
196
+ # Determine if a key exists.
197
+ def exists(*args)
198
+ args.flatten!(1)
199
+ keys_per_node = args.group_by { |key| node_for(key) }
200
+ keys_per_node.inject(0) do |sum, (node, keys)|
201
+ sum + node.exists(*keys)
202
+ end
203
+ end
204
+
205
+ # Determine if any of the keys exists.
206
+ def exists?(*args)
207
+ args.flatten!(1)
208
+ keys_per_node = args.group_by { |key| node_for(key) }
209
+ keys_per_node.each do |node, keys|
210
+ return true if node.exists?(*keys)
211
+ end
212
+ false
213
+ end
214
+
215
+ # Find all keys matching the given pattern.
216
+ def keys(glob = "*")
217
+ on_each_node(:keys, glob).flatten
218
+ end
219
+
220
+ # Move a key to another database.
221
+ def move(key, db)
222
+ node_for(key).move(key, db)
223
+ end
224
+
225
+ # Copy a value from one key to another.
226
+ def copy(source, destination, **options)
227
+ ensure_same_node(:copy, [source, destination]) do |node|
228
+ node.copy(source, destination, **options)
229
+ end
230
+ end
231
+
232
+ # Return a random key from the keyspace.
233
+ def randomkey
234
+ raise CannotDistribute, :randomkey
235
+ end
236
+
237
+ # Rename a key.
238
+ def rename(old_name, new_name)
239
+ ensure_same_node(:rename, [old_name, new_name]) do |node|
240
+ node.rename(old_name, new_name)
241
+ end
242
+ end
243
+
244
+ # Rename a key, only if the new key does not exist.
245
+ def renamenx(old_name, new_name)
246
+ ensure_same_node(:renamenx, [old_name, new_name]) do |node|
247
+ node.renamenx(old_name, new_name)
248
+ end
249
+ end
250
+
251
+ # Sort the elements in a list, set or sorted set.
252
+ def sort(key, **options)
253
+ keys = [key, options[:by], options[:store], *Array(options[:get])].compact
254
+
255
+ ensure_same_node(:sort, keys) do |node|
256
+ node.sort(key, **options)
257
+ end
258
+ end
259
+
260
+ # Determine the type stored at key.
261
+ def type(key)
262
+ node_for(key).type(key)
263
+ end
264
+
265
+ # Decrement the integer value of a key by one.
266
+ def decr(key)
267
+ node_for(key).decr(key)
268
+ end
269
+
270
+ # Decrement the integer value of a key by the given number.
271
+ def decrby(key, decrement)
272
+ node_for(key).decrby(key, decrement)
273
+ end
274
+
275
+ # Increment the integer value of a key by one.
276
+ def incr(key)
277
+ node_for(key).incr(key)
278
+ end
279
+
280
+ # Increment the integer value of a key by the given integer number.
281
+ def incrby(key, increment)
282
+ node_for(key).incrby(key, increment)
283
+ end
284
+
285
+ # Increment the numeric value of a key by the given float number.
286
+ def incrbyfloat(key, increment)
287
+ node_for(key).incrbyfloat(key, increment)
288
+ end
289
+
290
+ # Set the string value of a key.
291
+ def set(key, value, **options)
292
+ node_for(key).set(key, value, **options)
293
+ end
294
+
295
+ # Set the time to live in seconds of a key.
296
+ def setex(key, ttl, value)
297
+ node_for(key).setex(key, ttl, value)
298
+ end
299
+
300
+ # Set the time to live in milliseconds of a key.
301
+ def psetex(key, ttl, value)
302
+ node_for(key).psetex(key, ttl, value)
303
+ end
304
+
305
+ # Set the value of a key, only if the key does not exist.
306
+ def setnx(key, value)
307
+ node_for(key).setnx(key, value)
308
+ end
309
+
310
+ # Set multiple keys to multiple values.
311
+ def mset(*)
312
+ raise CannotDistribute, :mset
313
+ end
314
+
315
+ def mapped_mset(_hash)
316
+ raise CannotDistribute, :mapped_mset
317
+ end
318
+
319
+ # Set multiple keys to multiple values, only if none of the keys exist.
320
+ def msetnx(*)
321
+ raise CannotDistribute, :msetnx
322
+ end
323
+
324
+ def mapped_msetnx(_hash)
325
+ raise CannotDistribute, :mapped_msetnx
326
+ end
327
+
328
+ # Get the value of a key.
329
+ def get(key)
330
+ node_for(key).get(key)
331
+ end
332
+
333
+ # Get the value of a key and delete it.
334
+ def getdel(key)
335
+ node_for(key).getdel(key)
336
+ end
337
+
338
+ # Get the value of a key and sets its time to live based on options.
339
+ def getex(key, **options)
340
+ node_for(key).getex(key, **options)
341
+ end
342
+
343
+ # Get the values of all the given keys as an Array.
344
+ def mget(*keys)
345
+ keys.flatten!(1)
346
+ mapped_mget(*keys).values_at(*keys)
347
+ end
348
+
349
+ # Get the values of all the given keys as a Hash.
350
+ def mapped_mget(*keys)
351
+ keys.flatten!(1)
352
+ keys.group_by { |k| node_for k }.inject({}) do |results, (node, subkeys)|
353
+ results.merge! node.mapped_mget(*subkeys)
354
+ end
355
+ end
356
+
357
+ # Overwrite part of a string at key starting at the specified offset.
358
+ def setrange(key, offset, value)
359
+ node_for(key).setrange(key, offset, value)
360
+ end
361
+
362
+ # Get a substring of the string stored at a key.
363
+ def getrange(key, start, stop)
364
+ node_for(key).getrange(key, start, stop)
365
+ end
366
+
367
+ # Sets or clears the bit at offset in the string value stored at key.
368
+ def setbit(key, offset, value)
369
+ node_for(key).setbit(key, offset, value)
370
+ end
371
+
372
+ # Returns the bit value at offset in the string value stored at key.
373
+ def getbit(key, offset)
374
+ node_for(key).getbit(key, offset)
375
+ end
376
+
377
+ # Append a value to a key.
378
+ def append(key, value)
379
+ node_for(key).append(key, value)
380
+ end
381
+
382
+ # Count the number of set bits in a range of the string value stored at key.
383
+ def bitcount(key, start = 0, stop = -1, scale: nil)
384
+ node_for(key).bitcount(key, start, stop, scale: scale)
385
+ end
386
+
387
+ # Perform a bitwise operation between strings and store the resulting string in a key.
388
+ def bitop(operation, destkey, *keys)
389
+ keys.flatten!(1)
390
+ ensure_same_node(:bitop, [destkey] + keys) do |node|
391
+ node.bitop(operation, destkey, keys)
392
+ end
393
+ end
394
+
395
+ # Return the position of the first bit set to 1 or 0 in a string.
396
+ def bitpos(key, bit, start = nil, stop = nil, scale: nil)
397
+ node_for(key).bitpos(key, bit, start, stop, scale: scale)
398
+ end
399
+
400
+ # Set the string value of a key and return its old value.
401
+ def getset(key, value)
402
+ node_for(key).getset(key, value)
403
+ end
404
+
405
+ # Get the length of the value stored in a key.
406
+ def strlen(key)
407
+ node_for(key).strlen(key)
408
+ end
409
+
410
+ def [](key)
411
+ get(key)
412
+ end
413
+
414
+ def []=(key, value)
415
+ set(key, value)
416
+ end
417
+
418
+ # Get the length of a list.
419
+ def llen(key)
420
+ node_for(key).llen(key)
421
+ end
422
+
423
+ # Remove the first/last element in a list, append/prepend it to another list and return it.
424
+ def lmove(source, destination, where_source, where_destination)
425
+ ensure_same_node(:lmove, [source, destination]) do |node|
426
+ node.lmove(source, destination, where_source, where_destination)
427
+ end
428
+ end
429
+
430
+ # Remove the first/last element in a list and append/prepend it
431
+ # to another list and return it, or block until one is available.
432
+ def blmove(source, destination, where_source, where_destination, timeout: 0)
433
+ ensure_same_node(:lmove, [source, destination]) do |node|
434
+ node.blmove(source, destination, where_source, where_destination, timeout: timeout)
435
+ end
436
+ end
437
+
438
+ # Prepend one or more values to a list.
439
+ def lpush(key, value)
440
+ node_for(key).lpush(key, value)
441
+ end
442
+
443
+ # Prepend a value to a list, only if the list exists.
444
+ def lpushx(key, value)
445
+ node_for(key).lpushx(key, value)
446
+ end
447
+
448
+ # Append one or more values to a list.
449
+ def rpush(key, value)
450
+ node_for(key).rpush(key, value)
451
+ end
452
+
453
+ # Append a value to a list, only if the list exists.
454
+ def rpushx(key, value)
455
+ node_for(key).rpushx(key, value)
456
+ end
457
+
458
+ # Remove and get the first elements in a list.
459
+ def lpop(key, count = nil)
460
+ node_for(key).lpop(key, count)
461
+ end
462
+
463
+ # Remove and get the last elements in a list.
464
+ def rpop(key, count = nil)
465
+ node_for(key).rpop(key, count)
466
+ end
467
+
468
+ # Remove the last element in a list, append it to another list and return
469
+ # it.
470
+ def rpoplpush(source, destination)
471
+ ensure_same_node(:rpoplpush, [source, destination]) do |node|
472
+ node.rpoplpush(source, destination)
473
+ end
474
+ end
475
+
476
+ def _bpop(cmd, args)
477
+ timeout = if args.last.is_a?(Hash)
478
+ options = args.pop
479
+ options[:timeout]
480
+ end
481
+
482
+ args.flatten!(1)
483
+
484
+ ensure_same_node(cmd, args) do |node|
485
+ if timeout
486
+ node.__send__(cmd, args, timeout: timeout)
487
+ else
488
+ node.__send__(cmd, args)
489
+ end
490
+ end
491
+ end
492
+
493
+ # Remove and get the first element in a list, or block until one is
494
+ # available.
495
+ def blpop(*args)
496
+ _bpop(:blpop, args)
497
+ end
498
+
499
+ def bzpopmax(*args)
500
+ _bpop(:bzpopmax, args) do |reply|
501
+ reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
502
+ end
503
+ end
504
+
505
+ def bzpopmin(*args)
506
+ _bpop(:bzpopmin, args) do |reply|
507
+ reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
508
+ end
509
+ end
510
+
511
+ # Remove and get the last element in a list, or block until one is
512
+ # available.
513
+ def brpop(*args)
514
+ _bpop(:brpop, args)
515
+ end
516
+
517
+ # Pop a value from a list, push it to another list and return it; or block
518
+ # until one is available.
519
+ def brpoplpush(source, destination, **options)
520
+ ensure_same_node(:brpoplpush, [source, destination]) do |node|
521
+ node.brpoplpush(source, destination, **options)
522
+ end
523
+ end
524
+
525
+ # Get an element from a list by its index.
526
+ def lindex(key, index)
527
+ node_for(key).lindex(key, index)
528
+ end
529
+
530
+ # Insert an element before or after another element in a list.
531
+ def linsert(key, where, pivot, value)
532
+ node_for(key).linsert(key, where, pivot, value)
533
+ end
534
+
535
+ # Get a range of elements from a list.
536
+ def lrange(key, start, stop)
537
+ node_for(key).lrange(key, start, stop)
538
+ end
539
+
540
+ # Remove elements from a list.
541
+ def lrem(key, count, value)
542
+ node_for(key).lrem(key, count, value)
543
+ end
544
+
545
+ # Set the value of an element in a list by its index.
546
+ def lset(key, index, value)
547
+ node_for(key).lset(key, index, value)
548
+ end
549
+
550
+ # Trim a list to the specified range.
551
+ def ltrim(key, start, stop)
552
+ node_for(key).ltrim(key, start, stop)
553
+ end
554
+
555
+ # Iterate over keys, blocking and removing elements from the first non empty liist found.
556
+ def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
557
+ ensure_same_node(:blmpop, keys) do |node|
558
+ node.blmpop(timeout, *keys, modifier: modifier, count: count)
559
+ end
560
+ end
561
+
562
+ # Iterate over keys, removing elements from the first non list found.
563
+ def lmpop(*keys, modifier: "LEFT", count: nil)
564
+ ensure_same_node(:lmpop, keys) do |node|
565
+ node.lmpop(*keys, modifier: modifier, count: count)
566
+ end
567
+ end
568
+
569
+ # Get the number of members in a set.
570
+ def scard(key)
571
+ node_for(key).scard(key)
572
+ end
573
+
574
+ # Add one or more members to a set.
575
+ def sadd(key, *members)
576
+ node_for(key).sadd(key, *members)
577
+ end
578
+
579
+ # Add one or more members to a set.
580
+ def sadd?(key, *members)
581
+ node_for(key).sadd?(key, *members)
582
+ end
583
+
584
+ # Remove one or more members from a set.
585
+ def srem(key, *members)
586
+ node_for(key).srem(key, *members)
587
+ end
588
+
589
+ # Remove one or more members from a set.
590
+ def srem?(key, *members)
591
+ node_for(key).srem?(key, *members)
592
+ end
593
+
594
+ # Remove and return a random member from a set.
595
+ def spop(key, count = nil)
596
+ node_for(key).spop(key, count)
597
+ end
598
+
599
+ # Get a random member from a set.
600
+ def srandmember(key, count = nil)
601
+ node_for(key).srandmember(key, count)
602
+ end
603
+
604
+ # Move a member from one set to another.
605
+ def smove(source, destination, member)
606
+ ensure_same_node(:smove, [source, destination]) do |node|
607
+ node.smove(source, destination, member)
608
+ end
609
+ end
610
+
611
+ # Determine if a given value is a member of a set.
612
+ def sismember(key, member)
613
+ node_for(key).sismember(key, member)
614
+ end
615
+
616
+ # Determine if multiple values are members of a set.
617
+ def smismember(key, *members)
618
+ node_for(key).smismember(key, *members)
619
+ end
620
+
621
+ # Get all the members in a set.
622
+ def smembers(key)
623
+ node_for(key).smembers(key)
624
+ end
625
+
626
+ # Scan a set
627
+ def sscan(key, cursor, **options)
628
+ node_for(key).sscan(key, cursor, **options)
629
+ end
630
+
631
+ # Scan a set and return an enumerator
632
+ def sscan_each(key, **options, &block)
633
+ node_for(key).sscan_each(key, **options, &block)
634
+ end
635
+
636
+ # Subtract multiple sets.
637
+ def sdiff(*keys)
638
+ keys.flatten!(1)
639
+ ensure_same_node(:sdiff, keys) do |node|
640
+ node.sdiff(keys)
641
+ end
642
+ end
643
+
644
+ # Subtract multiple sets and store the resulting set in a key.
645
+ def sdiffstore(destination, *keys)
646
+ keys.flatten!(1)
647
+ ensure_same_node(:sdiffstore, [destination].concat(keys)) do |node|
648
+ node.sdiffstore(destination, keys)
649
+ end
650
+ end
651
+
652
+ # Intersect multiple sets.
653
+ def sinter(*keys)
654
+ keys.flatten!(1)
655
+ ensure_same_node(:sinter, keys) do |node|
656
+ node.sinter(keys)
657
+ end
658
+ end
659
+
660
+ # Intersect multiple sets and store the resulting set in a key.
661
+ def sinterstore(destination, *keys)
662
+ keys.flatten!(1)
663
+ ensure_same_node(:sinterstore, [destination].concat(keys)) do |node|
664
+ node.sinterstore(destination, keys)
665
+ end
666
+ end
667
+
668
+ # Add multiple sets.
669
+ def sunion(*keys)
670
+ keys.flatten!(1)
671
+ ensure_same_node(:sunion, keys) do |node|
672
+ node.sunion(keys)
673
+ end
674
+ end
675
+
676
+ # Add multiple sets and store the resulting set in a key.
677
+ def sunionstore(destination, *keys)
678
+ keys.flatten!(1)
679
+ ensure_same_node(:sunionstore, [destination].concat(keys)) do |node|
680
+ node.sunionstore(destination, keys)
681
+ end
682
+ end
683
+
684
+ # Get the number of members in a sorted set.
685
+ def zcard(key)
686
+ node_for(key).zcard(key)
687
+ end
688
+
689
+ # Add one or more members to a sorted set, or update the score for members
690
+ # that already exist.
691
+ def zadd(key, *args)
692
+ node_for(key).zadd(key, *args)
693
+ end
694
+ ruby2_keywords(:zadd) if respond_to?(:ruby2_keywords, true)
695
+
696
+ # Increment the score of a member in a sorted set.
697
+ def zincrby(key, increment, member)
698
+ node_for(key).zincrby(key, increment, member)
699
+ end
700
+
701
+ # Remove one or more members from a sorted set.
702
+ def zrem(key, member)
703
+ node_for(key).zrem(key, member)
704
+ end
705
+
706
+ # Get the score associated with the given member in a sorted set.
707
+ def zscore(key, member)
708
+ node_for(key).zscore(key, member)
709
+ end
710
+
711
+ # Get one or more random members from a sorted set.
712
+ def zrandmember(key, count = nil, **options)
713
+ node_for(key).zrandmember(key, count, **options)
714
+ end
715
+
716
+ # Get the scores associated with the given members in a sorted set.
717
+ def zmscore(key, *members)
718
+ node_for(key).zmscore(key, *members)
719
+ end
720
+
721
+ # Iterate over keys, blocking and removing members from the first non empty sorted set found.
722
+ def bzmpop(timeout, *keys, modifier: "MIN", count: nil)
723
+ ensure_same_node(:bzmpop, keys) do |node|
724
+ node.bzmpop(timeout, *keys, modifier: modifier, count: count)
725
+ end
726
+ end
727
+
728
+ # Iterate over keys, removing members from the first non empty sorted set found.
729
+ def zmpop(*keys, modifier: "MIN", count: nil)
730
+ ensure_same_node(:zmpop, keys) do |node|
731
+ node.zmpop(*keys, modifier: modifier, count: count)
732
+ end
733
+ end
734
+
735
+ # Return a range of members in a sorted set, by index, score or lexicographical ordering.
736
+ def zrange(key, start, stop, **options)
737
+ node_for(key).zrange(key, start, stop, **options)
738
+ end
739
+
740
+ # Select a range of members in a sorted set, by index, score or lexicographical ordering
741
+ # and store the resulting sorted set in a new key.
742
+ def zrangestore(dest_key, src_key, start, stop, **options)
743
+ ensure_same_node(:zrangestore, [dest_key, src_key]) do |node|
744
+ node.zrangestore(dest_key, src_key, start, stop, **options)
745
+ end
746
+ end
747
+
748
+ # Return a range of members in a sorted set, by index, with scores ordered
749
+ # from high to low.
750
+ def zrevrange(key, start, stop, **options)
751
+ node_for(key).zrevrange(key, start, stop, **options)
752
+ end
753
+
754
+ # Determine the index of a member in a sorted set.
755
+ def zrank(key, member, **options)
756
+ node_for(key).zrank(key, member, **options)
757
+ end
758
+
759
+ # Determine the index of a member in a sorted set, with scores ordered from
760
+ # high to low.
761
+ def zrevrank(key, member, **options)
762
+ node_for(key).zrevrank(key, member, **options)
763
+ end
764
+
765
+ # Remove all members in a sorted set within the given indexes.
766
+ def zremrangebyrank(key, start, stop)
767
+ node_for(key).zremrangebyrank(key, start, stop)
768
+ end
769
+
770
+ # Return a range of members in a sorted set, by score.
771
+ def zrangebyscore(key, min, max, **options)
772
+ node_for(key).zrangebyscore(key, min, max, **options)
773
+ end
774
+
775
+ # Return a range of members in a sorted set, by score, with scores ordered
776
+ # from high to low.
777
+ def zrevrangebyscore(key, max, min, **options)
778
+ node_for(key).zrevrangebyscore(key, max, min, **options)
779
+ end
780
+
781
+ # Remove all members in a sorted set within the given scores.
782
+ def zremrangebyscore(key, min, max)
783
+ node_for(key).zremrangebyscore(key, min, max)
784
+ end
785
+
786
+ # Get the number of members in a particular score range.
787
+ def zcount(key, min, max)
788
+ node_for(key).zcount(key, min, max)
789
+ end
790
+
791
+ # Get the intersection of multiple sorted sets
792
+ def zinter(*keys, **options)
793
+ keys.flatten!(1)
794
+ ensure_same_node(:zinter, keys) do |node|
795
+ node.zinter(keys, **options)
796
+ end
797
+ end
798
+
799
+ # Intersect multiple sorted sets and store the resulting sorted set in a new
800
+ # key.
801
+ def zinterstore(destination, *keys, **options)
802
+ keys.flatten!(1)
803
+ ensure_same_node(:zinterstore, [destination].concat(keys)) do |node|
804
+ node.zinterstore(destination, keys, **options)
805
+ end
806
+ end
807
+
808
+ # Return the union of multiple sorted sets.
809
+ def zunion(*keys, **options)
810
+ keys.flatten!(1)
811
+ ensure_same_node(:zunion, keys) do |node|
812
+ node.zunion(keys, **options)
813
+ end
814
+ end
815
+
816
+ # Add multiple sorted sets and store the resulting sorted set in a new key.
817
+ def zunionstore(destination, *keys, **options)
818
+ keys.flatten!(1)
819
+ ensure_same_node(:zunionstore, [destination].concat(keys)) do |node|
820
+ node.zunionstore(destination, keys, **options)
821
+ end
822
+ end
823
+
824
+ # Return the difference between the first and all successive input sorted sets.
825
+ def zdiff(*keys, **options)
826
+ keys.flatten!(1)
827
+ ensure_same_node(:zdiff, keys) do |node|
828
+ node.zdiff(keys, **options)
829
+ end
830
+ end
831
+
832
+ # Compute the difference between the first and all successive input sorted sets
833
+ # and store the resulting sorted set in a new key.
834
+ def zdiffstore(destination, *keys, **options)
835
+ keys.flatten!(1)
836
+ ensure_same_node(:zdiffstore, [destination] + keys) do |node|
837
+ node.zdiffstore(destination, keys, **options)
838
+ end
839
+ end
840
+
841
+ # Get the number of fields in a hash.
842
+ def hlen(key)
843
+ node_for(key).hlen(key)
844
+ end
845
+
846
+ # Set multiple hash fields to multiple values.
847
+ def hset(key, *attrs)
848
+ node_for(key).hset(key, *attrs)
849
+ end
850
+
851
+ # Set the value of a hash field, only if the field does not exist.
852
+ def hsetnx(key, field, value)
853
+ node_for(key).hsetnx(key, field, value)
854
+ end
855
+
856
+ # Set multiple hash fields to multiple values.
857
+ def hmset(key, *attrs)
858
+ node_for(key).hmset(key, *attrs)
859
+ end
860
+
861
+ def mapped_hmset(key, hash)
862
+ node_for(key).hmset(key, hash)
863
+ end
864
+
865
+ # Get the value of a hash field.
866
+ def hget(key, field)
867
+ node_for(key).hget(key, field)
868
+ end
869
+
870
+ # Get the values of all the given hash fields.
871
+ def hmget(key, *fields)
872
+ fields.flatten!(1)
873
+ node_for(key).hmget(key, fields)
874
+ end
875
+
876
+ def mapped_hmget(key, *fields)
877
+ fields.flatten!(1)
878
+ node_for(key).mapped_hmget(key, fields)
879
+ end
880
+
881
+ def hrandfield(key, count = nil, **options)
882
+ node_for(key).hrandfield(key, count, **options)
883
+ end
884
+
885
+ # Delete one or more hash fields.
886
+ def hdel(key, *fields)
887
+ fields.flatten!(1)
888
+ node_for(key).hdel(key, fields)
889
+ end
890
+
891
+ # Determine if a hash field exists.
892
+ def hexists(key, field)
893
+ node_for(key).hexists(key, field)
894
+ end
895
+
896
+ # Increment the integer value of a hash field by the given integer number.
897
+ def hincrby(key, field, increment)
898
+ node_for(key).hincrby(key, field, increment)
899
+ end
900
+
901
+ # Increment the numeric value of a hash field by the given float number.
902
+ def hincrbyfloat(key, field, increment)
903
+ node_for(key).hincrbyfloat(key, field, increment)
904
+ end
905
+
906
+ # Get all the fields in a hash.
907
+ def hkeys(key)
908
+ node_for(key).hkeys(key)
909
+ end
910
+
911
+ # Get all the values in a hash.
912
+ def hvals(key)
913
+ node_for(key).hvals(key)
914
+ end
915
+
916
+ # Get all the fields and values in a hash.
917
+ def hgetall(key)
918
+ node_for(key).hgetall(key)
919
+ end
920
+
921
+ # Post a message to a channel.
922
+ def publish(channel, message)
923
+ node_for(channel).publish(channel, message)
924
+ end
925
+
926
+ def subscribed?
927
+ !!@subscribed_node
928
+ end
929
+
930
+ # Listen for messages published to the given channels.
931
+ def subscribe(channel, *channels, &block)
932
+ if channels.empty?
933
+ @subscribed_node = node_for(channel)
934
+ @subscribed_node.subscribe(channel, &block)
935
+ else
936
+ ensure_same_node(:subscribe, [channel] + channels) do |node|
937
+ @subscribed_node = node
938
+ node.subscribe(channel, *channels, &block)
939
+ end
940
+ end
941
+ end
942
+
943
+ # Stop listening for messages posted to the given channels.
944
+ def unsubscribe(*channels)
945
+ raise SubscriptionError, "Can't unsubscribe if not subscribed." unless subscribed?
946
+
947
+ @subscribed_node.unsubscribe(*channels)
948
+ end
949
+
950
+ # Listen for messages published to channels matching the given patterns.
951
+ # See the [Redis Server PSUBSCRIBE documentation](https://redis.io/docs/latest/commands/psubscribe/)
952
+ # for further details
953
+ def psubscribe(*channels, &block)
954
+ raise NotImplementedError
955
+ end
956
+
957
+ # Stop listening for messages posted to channels matching the given
958
+ # patterns.
959
+ # See the [Redis Server PUNSUBSCRIBE documentation](https://redis.io/docs/latest/commands/punsubscribe/)
960
+ # for further details
961
+ def punsubscribe(*channels)
962
+ raise NotImplementedError
963
+ end
964
+
965
+ # Watch the given keys to determine execution of the MULTI/EXEC block.
966
+ def watch(*keys, &block)
967
+ ensure_same_node(:watch, keys) do |node|
968
+ @watch_key = key_tag(keys.first) || keys.first.to_s
969
+
970
+ begin
971
+ node.watch(*keys, &block)
972
+ rescue StandardError
973
+ @watch_key = nil
974
+ raise
975
+ end
976
+ end
977
+ end
978
+
979
+ # Forget about all watched keys.
980
+ def unwatch
981
+ raise CannotDistribute, :unwatch unless @watch_key
982
+
983
+ result = node_for(@watch_key).unwatch
984
+ @watch_key = nil
985
+ result
986
+ end
987
+
988
+ def pipelined
989
+ raise CannotDistribute, :pipelined
990
+ end
991
+
992
+ # Mark the start of a transaction block.
993
+ def multi(&block)
994
+ raise CannotDistribute, :multi unless @watch_key
995
+
996
+ node_for(@watch_key).multi(&block)
997
+ end
998
+
999
+ # Execute all commands issued after MULTI.
1000
+ def exec
1001
+ raise CannotDistribute, :exec unless @watch_key
1002
+
1003
+ result = node_for(@watch_key).exec
1004
+ @watch_key = nil
1005
+ result
1006
+ end
1007
+
1008
+ # Discard all commands issued after MULTI.
1009
+ def discard
1010
+ raise CannotDistribute, :discard unless @watch_key
1011
+
1012
+ result = node_for(@watch_key).discard
1013
+ @watch_key = nil
1014
+ result
1015
+ end
1016
+
1017
+ # Control remote script registry.
1018
+ def script(subcommand, *args)
1019
+ on_each_node(:script, subcommand, *args)
1020
+ end
1021
+
1022
+ # Add one or more members to a HyperLogLog structure.
1023
+ def pfadd(key, member)
1024
+ node_for(key).pfadd(key, member)
1025
+ end
1026
+
1027
+ # Get the approximate cardinality of members added to HyperLogLog structure.
1028
+ def pfcount(*keys)
1029
+ ensure_same_node(:pfcount, keys.flatten(1)) do |node|
1030
+ node.pfcount(keys)
1031
+ end
1032
+ end
1033
+
1034
+ # Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
1035
+ # the observed Sets of the source HyperLogLog structures.
1036
+ def pfmerge(dest_key, *source_key)
1037
+ ensure_same_node(:pfmerge, [dest_key, *source_key]) do |node|
1038
+ node.pfmerge(dest_key, *source_key)
1039
+ end
1040
+ end
1041
+
1042
+ def _eval(cmd, args)
1043
+ script = args.shift
1044
+ options = args.pop if args.last.is_a?(Hash)
1045
+ options ||= {}
1046
+
1047
+ keys = args.shift || options[:keys] || []
1048
+ argv = args.shift || options[:argv] || []
1049
+
1050
+ ensure_same_node(cmd, keys) do |node|
1051
+ node.send(cmd, script, keys, argv)
1052
+ end
1053
+ end
1054
+
1055
+ # Evaluate Lua script.
1056
+ def eval(*args)
1057
+ _eval(:eval, args)
1058
+ end
1059
+
1060
+ # Evaluate Lua script by its SHA.
1061
+ def evalsha(*args)
1062
+ _eval(:evalsha, args)
1063
+ end
1064
+
1065
+ def inspect
1066
+ "#<Redis client v#{Redis::VERSION} for #{nodes.map(&:id).join(', ')}>"
1067
+ end
1068
+
1069
+ def dup
1070
+ self.class.new(@node_configs, @default_options)
1071
+ end
1072
+
1073
+ protected
1074
+
1075
+ def on_each_node(command, *args)
1076
+ nodes.map do |node|
1077
+ node.send(command, *args)
1078
+ end
1079
+ end
1080
+
1081
+ def node_index_for(key)
1082
+ nodes.index(node_for(key))
1083
+ end
1084
+
1085
+ def key_tag(key)
1086
+ key = key.to_s
1087
+ key[@tag, 1] if key.match?(@tag)
1088
+ end
1089
+
1090
+ def ensure_same_node(command, keys)
1091
+ all = true
1092
+
1093
+ tags = keys.map do |key|
1094
+ tag = key_tag(key)
1095
+ all = false unless tag
1096
+ tag
1097
+ end
1098
+
1099
+ if (all && tags.uniq.size != 1) || (!all && keys.uniq.size != 1)
1100
+ # Not 1 unique tag or not 1 unique key
1101
+ raise CannotDistribute, command
1102
+ end
1103
+
1104
+ yield(node_for(keys.first))
1105
+ end
1106
+ end
1107
+ end