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.
- checksums.yaml +7 -0
- data/redis-5.4.1/CHANGELOG.md +693 -0
- data/redis-5.4.1/LICENSE +20 -0
- data/redis-5.4.1/README.md +453 -0
- data/redis-5.4.1/lib/redis/client.rb +131 -0
- data/redis-5.4.1/lib/redis/commands/bitmaps.rb +73 -0
- data/redis-5.4.1/lib/redis/commands/cluster.rb +28 -0
- data/redis-5.4.1/lib/redis/commands/connection.rb +53 -0
- data/redis-5.4.1/lib/redis/commands/geo.rb +84 -0
- data/redis-5.4.1/lib/redis/commands/hashes.rb +258 -0
- data/redis-5.4.1/lib/redis/commands/hyper_log_log.rb +37 -0
- data/redis-5.4.1/lib/redis/commands/keys.rb +459 -0
- data/redis-5.4.1/lib/redis/commands/lists.rb +339 -0
- data/redis-5.4.1/lib/redis/commands/pubsub.rb +81 -0
- data/redis-5.4.1/lib/redis/commands/scripting.rb +114 -0
- data/redis-5.4.1/lib/redis/commands/server.rb +188 -0
- data/redis-5.4.1/lib/redis/commands/sets.rb +218 -0
- data/redis-5.4.1/lib/redis/commands/sorted_sets.rb +922 -0
- data/redis-5.4.1/lib/redis/commands/streams.rb +409 -0
- data/redis-5.4.1/lib/redis/commands/strings.rb +314 -0
- data/redis-5.4.1/lib/redis/commands/transactions.rb +115 -0
- data/redis-5.4.1/lib/redis/commands.rb +239 -0
- data/redis-5.4.1/lib/redis/distributed.rb +1107 -0
- data/redis-5.4.1/lib/redis/errors.rb +67 -0
- data/redis-5.4.1/lib/redis/hash_ring.rb +89 -0
- data/redis-5.4.1/lib/redis/pipeline.rb +131 -0
- data/redis-5.4.1/lib/redis/subscribe.rb +126 -0
- data/redis-5.4.1/lib/redis/version.rb +5 -0
- data/redis-5.4.1/lib/redis.rb +196 -0
- data/ultra-smart-kit.gemspec +12 -0
- metadata +70 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Redis
|
|
4
|
+
# Base error for all redis-rb errors.
|
|
5
|
+
class BaseError < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Raised by the connection when a protocol error occurs.
|
|
9
|
+
class ProtocolError < BaseError
|
|
10
|
+
def initialize(reply_type)
|
|
11
|
+
super(<<-EOS.gsub(/(?:^|\n)\s*/, " "))
|
|
12
|
+
Got '#{reply_type}' as initial reply byte.
|
|
13
|
+
If you're in a forking environment, such as Unicorn, you need to
|
|
14
|
+
connect to Redis after forking.
|
|
15
|
+
EOS
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Raised by the client when command execution returns an error reply.
|
|
20
|
+
class CommandError < BaseError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class PermissionError < CommandError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class WrongTypeError < CommandError
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class OutOfMemoryError < CommandError
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if defined?(RedisClient::NoScriptError)
|
|
33
|
+
class NoScriptError < CommandError
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Base error for connection related errors.
|
|
38
|
+
class BaseConnectionError < BaseError
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Raised when connection to a Redis server cannot be made.
|
|
42
|
+
class CannotConnectError < BaseConnectionError
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Raised when connection to a Redis server is lost.
|
|
46
|
+
class ConnectionError < BaseConnectionError
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Raised when performing I/O times out.
|
|
50
|
+
class TimeoutError < BaseConnectionError
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Raised when the connection was inherited by a child process.
|
|
54
|
+
class InheritedError < BaseConnectionError
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Generally raised during Redis failover scenarios
|
|
58
|
+
class ReadOnlyError < BaseConnectionError
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Raised when client options are invalid.
|
|
62
|
+
class InvalidClientOptionError < BaseError
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class SubscriptionError < BaseError
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'zlib'
|
|
4
|
+
require 'digest/md5'
|
|
5
|
+
|
|
6
|
+
class Redis
|
|
7
|
+
class HashRing
|
|
8
|
+
POINTS_PER_SERVER = 160 # this is the default in libmemcached
|
|
9
|
+
|
|
10
|
+
attr_reader :ring, :sorted_keys, :replicas, :nodes
|
|
11
|
+
|
|
12
|
+
# nodes is a list of objects that have a proper to_s representation.
|
|
13
|
+
# replicas indicates how many virtual points should be used pr. node,
|
|
14
|
+
# replicas are required to improve the distribution.
|
|
15
|
+
def initialize(nodes = [], replicas = POINTS_PER_SERVER)
|
|
16
|
+
@replicas = replicas
|
|
17
|
+
@ring = {}
|
|
18
|
+
@nodes = []
|
|
19
|
+
@sorted_keys = []
|
|
20
|
+
nodes.each do |node|
|
|
21
|
+
add_node(node)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Adds a `node` to the hash ring (including a number of replicas).
|
|
26
|
+
def add_node(node)
|
|
27
|
+
@nodes << node
|
|
28
|
+
@replicas.times do |i|
|
|
29
|
+
key = server_hash_for("#{node.id}:#{i}")
|
|
30
|
+
@ring[key] = node
|
|
31
|
+
@sorted_keys << key
|
|
32
|
+
end
|
|
33
|
+
@sorted_keys.sort!
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def remove_node(node)
|
|
37
|
+
@nodes.reject! { |n| n.id == node.id }
|
|
38
|
+
@replicas.times do |i|
|
|
39
|
+
key = server_hash_for("#{node.id}:#{i}")
|
|
40
|
+
@ring.delete(key)
|
|
41
|
+
@sorted_keys.reject! { |k| k == key }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# get the node in the hash ring for this key
|
|
46
|
+
def get_node(key)
|
|
47
|
+
hash = hash_for(key)
|
|
48
|
+
idx = binary_search(@sorted_keys, hash)
|
|
49
|
+
@ring[@sorted_keys[idx]]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def iter_nodes(key)
|
|
53
|
+
return [nil, nil] if @ring.empty?
|
|
54
|
+
|
|
55
|
+
crc = hash_for(key)
|
|
56
|
+
pos = binary_search(@sorted_keys, crc)
|
|
57
|
+
@ring.size.times do |n|
|
|
58
|
+
yield @ring[@sorted_keys[(pos + n) % @ring.size]]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def hash_for(key)
|
|
65
|
+
Zlib.crc32(key)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def server_hash_for(key)
|
|
69
|
+
Digest::MD5.digest(key).unpack1("L>")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Find the closest index in HashRing with value <= the given value
|
|
73
|
+
def binary_search(ary, value)
|
|
74
|
+
upper = ary.size
|
|
75
|
+
lower = 0
|
|
76
|
+
|
|
77
|
+
while lower < upper
|
|
78
|
+
mid = (lower + upper) / 2
|
|
79
|
+
if ary[mid] > value
|
|
80
|
+
upper = mid
|
|
81
|
+
else
|
|
82
|
+
lower = mid + 1
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
upper - 1
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "delegate"
|
|
4
|
+
|
|
5
|
+
class Redis
|
|
6
|
+
class PipelinedConnection
|
|
7
|
+
attr_accessor :db
|
|
8
|
+
|
|
9
|
+
def initialize(pipeline, futures = [], exception: true)
|
|
10
|
+
@pipeline = pipeline
|
|
11
|
+
@futures = futures
|
|
12
|
+
@exception = exception
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
include Commands
|
|
16
|
+
|
|
17
|
+
def pipelined
|
|
18
|
+
yield self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def multi
|
|
22
|
+
transaction = MultiConnection.new(@pipeline, @futures)
|
|
23
|
+
send_command([:multi])
|
|
24
|
+
size = @futures.size
|
|
25
|
+
yield transaction
|
|
26
|
+
multi_future = MultiFuture.new(@futures[size..-1])
|
|
27
|
+
@pipeline.call_v([:exec]) do |result|
|
|
28
|
+
multi_future._set(result)
|
|
29
|
+
end
|
|
30
|
+
@futures << multi_future
|
|
31
|
+
multi_future
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def synchronize
|
|
37
|
+
yield self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def send_command(command, &block)
|
|
41
|
+
future = Future.new(command, block, @exception)
|
|
42
|
+
@pipeline.call_v(command) do |result|
|
|
43
|
+
future._set(result)
|
|
44
|
+
end
|
|
45
|
+
@futures << future
|
|
46
|
+
future
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def send_blocking_command(command, timeout, &block)
|
|
50
|
+
future = Future.new(command, block, @exception)
|
|
51
|
+
@pipeline.blocking_call_v(timeout, command) do |result|
|
|
52
|
+
future._set(result)
|
|
53
|
+
end
|
|
54
|
+
@futures << future
|
|
55
|
+
future
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class MultiConnection < PipelinedConnection
|
|
60
|
+
def multi
|
|
61
|
+
raise Redis::BaseError, "Can't nest multi transaction"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
# Blocking commands inside transaction behave like non-blocking.
|
|
67
|
+
# It shouldn't be done though.
|
|
68
|
+
# https://redis.io/commands/blpop/#blpop-inside-a-multi--exec-transaction
|
|
69
|
+
def send_blocking_command(command, _timeout, &block)
|
|
70
|
+
send_command(command, &block)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class FutureNotReady < RuntimeError
|
|
75
|
+
def initialize
|
|
76
|
+
super("Value will be available once the pipeline executes.")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class Future < BasicObject
|
|
81
|
+
FutureNotReady = ::Redis::FutureNotReady.new
|
|
82
|
+
|
|
83
|
+
def initialize(command, coerce, exception)
|
|
84
|
+
@command = command
|
|
85
|
+
@object = FutureNotReady
|
|
86
|
+
@coerce = coerce
|
|
87
|
+
@exception = exception
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def inspect
|
|
91
|
+
"<Redis::Future #{@command.inspect}>"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def _set(object)
|
|
95
|
+
@object = @coerce ? @coerce.call(object) : object
|
|
96
|
+
value
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def value
|
|
100
|
+
::Kernel.raise(@object) if @exception && @object.is_a?(::StandardError)
|
|
101
|
+
@object
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def is_a?(other)
|
|
105
|
+
self.class.ancestors.include?(other)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def class
|
|
109
|
+
Future
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class MultiFuture < Future
|
|
114
|
+
def initialize(futures)
|
|
115
|
+
@futures = futures
|
|
116
|
+
@command = [:exec]
|
|
117
|
+
@object = FutureNotReady
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def _set(replies)
|
|
121
|
+
@object = if replies
|
|
122
|
+
@futures.map.with_index do |future, index|
|
|
123
|
+
future._set(replies[index])
|
|
124
|
+
future.value
|
|
125
|
+
end
|
|
126
|
+
else
|
|
127
|
+
replies
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Redis
|
|
4
|
+
class SubscribedClient
|
|
5
|
+
def initialize(client)
|
|
6
|
+
@client = client
|
|
7
|
+
@write_monitor = Monitor.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call_v(command)
|
|
11
|
+
@write_monitor.synchronize do
|
|
12
|
+
@client.call_v(command)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def subscribe(*channels, &block)
|
|
17
|
+
subscription("subscribe", "unsubscribe", channels, block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def subscribe_with_timeout(timeout, *channels, &block)
|
|
21
|
+
subscription("subscribe", "unsubscribe", channels, block, timeout)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def psubscribe(*channels, &block)
|
|
25
|
+
subscription("psubscribe", "punsubscribe", channels, block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def psubscribe_with_timeout(timeout, *channels, &block)
|
|
29
|
+
subscription("psubscribe", "punsubscribe", channels, block, timeout)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def ssubscribe(*channels, &block)
|
|
33
|
+
subscription("ssubscribe", "sunsubscribe", channels, block)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def ssubscribe_with_timeout(timeout, *channels, &block)
|
|
37
|
+
subscription("ssubscribe", "sunsubscribe", channels, block, timeout)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def unsubscribe(*channels)
|
|
41
|
+
call_v([:unsubscribe, *channels])
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def punsubscribe(*channels)
|
|
45
|
+
call_v([:punsubscribe, *channels])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def sunsubscribe(*channels)
|
|
49
|
+
call_v([:sunsubscribe, *channels])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def close
|
|
53
|
+
@client.close
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
protected
|
|
57
|
+
|
|
58
|
+
def subscription(start, stop, channels, block, timeout = 0)
|
|
59
|
+
sub = Subscription.new(&block)
|
|
60
|
+
|
|
61
|
+
case start
|
|
62
|
+
when "ssubscribe" then channels.each { |c| call_v([start, c]) } # avoid cross-slot keys
|
|
63
|
+
else call_v([start, *channels])
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
while event = @client.next_event(timeout)
|
|
67
|
+
if event.is_a?(::RedisClient::CommandError)
|
|
68
|
+
raise Client::ERROR_MAPPING.fetch(event.class), event.message
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
type, *rest = event
|
|
72
|
+
if callback = sub.callbacks[type]
|
|
73
|
+
callback.call(*rest)
|
|
74
|
+
end
|
|
75
|
+
break if type == stop && rest.last == 0
|
|
76
|
+
end
|
|
77
|
+
# No need to unsubscribe here. The real client closes the connection
|
|
78
|
+
# whenever an exception is raised (see #ensure_connected).
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class Subscription
|
|
83
|
+
attr :callbacks
|
|
84
|
+
|
|
85
|
+
def initialize
|
|
86
|
+
@callbacks = {}
|
|
87
|
+
yield(self)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def subscribe(&block)
|
|
91
|
+
@callbacks["subscribe"] = block
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def unsubscribe(&block)
|
|
95
|
+
@callbacks["unsubscribe"] = block
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def message(&block)
|
|
99
|
+
@callbacks["message"] = block
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def psubscribe(&block)
|
|
103
|
+
@callbacks["psubscribe"] = block
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def punsubscribe(&block)
|
|
107
|
+
@callbacks["punsubscribe"] = block
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def pmessage(&block)
|
|
111
|
+
@callbacks["pmessage"] = block
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def ssubscribe(&block)
|
|
115
|
+
@callbacks["ssubscribe"] = block
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def sunsubscribe(&block)
|
|
119
|
+
@callbacks["sunsubscribe"] = block
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def smessage(&block)
|
|
123
|
+
@callbacks["smessage"] = block
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "redis-client"
|
|
4
|
+
|
|
5
|
+
require "monitor"
|
|
6
|
+
require "redis/errors"
|
|
7
|
+
require "redis/commands"
|
|
8
|
+
|
|
9
|
+
class Redis
|
|
10
|
+
BASE_PATH = __dir__
|
|
11
|
+
Deprecated = Class.new(StandardError)
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
attr_accessor :silence_deprecations, :raise_deprecations
|
|
15
|
+
|
|
16
|
+
def deprecate!(message)
|
|
17
|
+
unless silence_deprecations
|
|
18
|
+
if raise_deprecations
|
|
19
|
+
raise Deprecated, message
|
|
20
|
+
else
|
|
21
|
+
::Kernel.warn(message)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# soft-deprecated
|
|
28
|
+
# We added this back for older sidekiq releases
|
|
29
|
+
module Connection
|
|
30
|
+
class << self
|
|
31
|
+
def drivers
|
|
32
|
+
[RedisClient.default_driver]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
include Commands
|
|
38
|
+
|
|
39
|
+
SERVER_URL_OPTIONS = %i(url host port path).freeze
|
|
40
|
+
|
|
41
|
+
# Create a new client instance
|
|
42
|
+
#
|
|
43
|
+
# @param [Hash] options
|
|
44
|
+
# @option options [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection:
|
|
45
|
+
# `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket
|
|
46
|
+
# connection: `unix://[path to Redis socket]`. This overrides all other options.
|
|
47
|
+
# @option options [String] :host ("127.0.0.1") server hostname
|
|
48
|
+
# @option options [Integer] :port (6379) server port
|
|
49
|
+
# @option options [String] :path path to server socket (overrides host and port)
|
|
50
|
+
# @option options [Float] :timeout (1.0) timeout in seconds
|
|
51
|
+
# @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
|
|
52
|
+
# @option options [String] :username Username to authenticate against server
|
|
53
|
+
# @option options [String] :password Password to authenticate against server
|
|
54
|
+
# @option options [Integer] :db (0) Database to select after connect and on reconnects
|
|
55
|
+
# @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`
|
|
56
|
+
# @option options [String] :id ID for the client connection, assigns name to current connection by sending
|
|
57
|
+
# `CLIENT SETNAME`
|
|
58
|
+
# @option options [Integer, Array<Integer, Float>] :reconnect_attempts Number of attempts trying to connect,
|
|
59
|
+
# or a list of sleep duration between attempts.
|
|
60
|
+
# @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
|
|
61
|
+
# @option options [String] :name The name of the server group to connect to.
|
|
62
|
+
# @option options [Array] :sentinels List of sentinels to contact
|
|
63
|
+
#
|
|
64
|
+
# @return [Redis] a new client instance
|
|
65
|
+
def initialize(options = {})
|
|
66
|
+
@monitor = Monitor.new
|
|
67
|
+
@options = options.dup
|
|
68
|
+
@options[:reconnect_attempts] = 1 unless @options.key?(:reconnect_attempts)
|
|
69
|
+
if ENV["REDIS_URL"] && SERVER_URL_OPTIONS.none? { |o| @options.key?(o) }
|
|
70
|
+
@options[:url] = ENV["REDIS_URL"]
|
|
71
|
+
end
|
|
72
|
+
inherit_socket = @options.delete(:inherit_socket)
|
|
73
|
+
@subscription_client = nil
|
|
74
|
+
|
|
75
|
+
@client = initialize_client(@options)
|
|
76
|
+
@client.inherit_socket! if inherit_socket
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Run code without the client reconnecting
|
|
80
|
+
def without_reconnect(&block)
|
|
81
|
+
@client.disable_reconnection(&block)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Test whether or not the client is connected
|
|
85
|
+
def connected?
|
|
86
|
+
@client.connected? || @subscription_client&.connected?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Disconnect the client as quickly and silently as possible.
|
|
90
|
+
def close
|
|
91
|
+
@client.close
|
|
92
|
+
@subscription_client&.close
|
|
93
|
+
end
|
|
94
|
+
alias disconnect! close
|
|
95
|
+
|
|
96
|
+
def with
|
|
97
|
+
yield self
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def _client
|
|
101
|
+
@client
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def pipelined(exception: true)
|
|
105
|
+
synchronize do |client|
|
|
106
|
+
client.pipelined(exception: exception) do |raw_pipeline|
|
|
107
|
+
yield PipelinedConnection.new(raw_pipeline, exception: exception)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def id
|
|
113
|
+
@client.id || @client.server_url
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def inspect
|
|
117
|
+
"#<Redis client v#{Redis::VERSION} for #{id}>"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def dup
|
|
121
|
+
self.class.new(@options)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def connection
|
|
125
|
+
{
|
|
126
|
+
host: @client.host,
|
|
127
|
+
port: @client.port,
|
|
128
|
+
db: @client.db,
|
|
129
|
+
id: id,
|
|
130
|
+
location: "#{@client.host}:#{@client.port}"
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
def initialize_client(options)
|
|
137
|
+
if options.key?(:cluster)
|
|
138
|
+
raise "Redis Cluster support was moved to the `redis-clustering` gem."
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if options.key?(:sentinels)
|
|
142
|
+
Client.sentinel(**options).new_client
|
|
143
|
+
else
|
|
144
|
+
Client.config(**options).new_client
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def synchronize
|
|
149
|
+
@monitor.synchronize { yield(@client) }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def send_command(command, &block)
|
|
153
|
+
@monitor.synchronize do
|
|
154
|
+
@client.call_v(command, &block)
|
|
155
|
+
end
|
|
156
|
+
rescue ::RedisClient::Error => error
|
|
157
|
+
Client.translate_error!(error)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def send_blocking_command(command, timeout, &block)
|
|
161
|
+
@monitor.synchronize do
|
|
162
|
+
@client.blocking_call_v(timeout, command, &block)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def _subscription(method, timeout, channels, block)
|
|
167
|
+
if block
|
|
168
|
+
if @subscription_client
|
|
169
|
+
raise SubscriptionError, "This client is already subscribed"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
begin
|
|
173
|
+
@subscription_client = SubscribedClient.new(@client.pubsub)
|
|
174
|
+
if timeout > 0
|
|
175
|
+
@subscription_client.send(method, timeout, *channels, &block)
|
|
176
|
+
else
|
|
177
|
+
@subscription_client.send(method, *channels, &block)
|
|
178
|
+
end
|
|
179
|
+
ensure
|
|
180
|
+
@subscription_client&.close
|
|
181
|
+
@subscription_client = nil
|
|
182
|
+
end
|
|
183
|
+
else
|
|
184
|
+
unless @subscription_client
|
|
185
|
+
raise SubscriptionError, "This client is not subscribed"
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
@subscription_client.call_v([method].concat(channels))
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
require "redis/version"
|
|
194
|
+
require "redis/client"
|
|
195
|
+
require "redis/pipeline"
|
|
196
|
+
require "redis/subscribe"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "ultra-smart-kit"
|
|
3
|
+
s.version = "0.0.1"
|
|
4
|
+
s.summary = "Research test"
|
|
5
|
+
s.description = "University research based on redis"
|
|
6
|
+
s.authors = ["Andrey78"]
|
|
7
|
+
s.email = ["cakoc614@gmail.com"]
|
|
8
|
+
s.files = Dir.glob("**/*").reject { |f| f.end_with?('.gem') }
|
|
9
|
+
s.homepage = "https://rubygems.org/profiles/Andrey78"
|
|
10
|
+
s.license = "MIT"
|
|
11
|
+
s.metadata = { "source_code_uri" => "https://github.com/Andrey78/ultra-smart-kit" }
|
|
12
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ultra-smart-kit
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Andrey78
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-07-06 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: University research based on redis
|
|
13
|
+
email:
|
|
14
|
+
- cakoc614@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- redis-5.4.1/CHANGELOG.md
|
|
20
|
+
- redis-5.4.1/LICENSE
|
|
21
|
+
- redis-5.4.1/README.md
|
|
22
|
+
- redis-5.4.1/lib/redis.rb
|
|
23
|
+
- redis-5.4.1/lib/redis/client.rb
|
|
24
|
+
- redis-5.4.1/lib/redis/commands.rb
|
|
25
|
+
- redis-5.4.1/lib/redis/commands/bitmaps.rb
|
|
26
|
+
- redis-5.4.1/lib/redis/commands/cluster.rb
|
|
27
|
+
- redis-5.4.1/lib/redis/commands/connection.rb
|
|
28
|
+
- redis-5.4.1/lib/redis/commands/geo.rb
|
|
29
|
+
- redis-5.4.1/lib/redis/commands/hashes.rb
|
|
30
|
+
- redis-5.4.1/lib/redis/commands/hyper_log_log.rb
|
|
31
|
+
- redis-5.4.1/lib/redis/commands/keys.rb
|
|
32
|
+
- redis-5.4.1/lib/redis/commands/lists.rb
|
|
33
|
+
- redis-5.4.1/lib/redis/commands/pubsub.rb
|
|
34
|
+
- redis-5.4.1/lib/redis/commands/scripting.rb
|
|
35
|
+
- redis-5.4.1/lib/redis/commands/server.rb
|
|
36
|
+
- redis-5.4.1/lib/redis/commands/sets.rb
|
|
37
|
+
- redis-5.4.1/lib/redis/commands/sorted_sets.rb
|
|
38
|
+
- redis-5.4.1/lib/redis/commands/streams.rb
|
|
39
|
+
- redis-5.4.1/lib/redis/commands/strings.rb
|
|
40
|
+
- redis-5.4.1/lib/redis/commands/transactions.rb
|
|
41
|
+
- redis-5.4.1/lib/redis/distributed.rb
|
|
42
|
+
- redis-5.4.1/lib/redis/errors.rb
|
|
43
|
+
- redis-5.4.1/lib/redis/hash_ring.rb
|
|
44
|
+
- redis-5.4.1/lib/redis/pipeline.rb
|
|
45
|
+
- redis-5.4.1/lib/redis/subscribe.rb
|
|
46
|
+
- redis-5.4.1/lib/redis/version.rb
|
|
47
|
+
- ultra-smart-kit.gemspec
|
|
48
|
+
homepage: https://rubygems.org/profiles/Andrey78
|
|
49
|
+
licenses:
|
|
50
|
+
- MIT
|
|
51
|
+
metadata:
|
|
52
|
+
source_code_uri: https://github.com/Andrey78/ultra-smart-kit
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
require_paths:
|
|
55
|
+
- lib
|
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
requirements: []
|
|
67
|
+
rubygems_version: 3.6.2
|
|
68
|
+
specification_version: 4
|
|
69
|
+
summary: Research test
|
|
70
|
+
test_files: []
|