redtastic 0.2.1 → 0.2.2
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 +8 -8
- data/.gitignore +10 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +84 -0
- data/README.md +275 -0
- data/lib/redtastic/connection.rb +14 -0
- data/lib/redtastic/model.rb +285 -0
- data/lib/redtastic/script_manager.rb +32 -0
- data/lib/redtastic/scripts/data_points_for_keys.lua +37 -0
- data/lib/redtastic/scripts/hmfind.lua +14 -0
- data/lib/redtastic/scripts/hmincrby.lua +9 -0
- data/lib/redtastic/scripts/msadd.lua +3 -0
- data/lib/redtastic/scripts/msismember.lua +7 -0
- data/lib/redtastic/scripts/msrem.lua +3 -0
- data/lib/redtastic/scripts/msunion.lua +28 -0
- data/lib/redtastic/scripts/sum.lua +13 -0
- data/lib/redtastic/scripts/union_data_points_for_keys.lua +51 -0
- data/lib/redtastic/version.rb +3 -0
- data/redtastic.gemspec +27 -0
- data/spec/connection_spec.rb +42 -0
- data/spec/model_spec.rb +776 -0
- data/spec/sample_scripts/sample.lua +1 -0
- data/spec/sample_scripts/sample_with_args.lua +1 -0
- data/spec/script_manager_spec.rb +24 -0
- data/spec/spec_helper.rb +26 -0
- metadata +34 -2
@@ -0,0 +1,285 @@
|
|
1
|
+
module Redtastic
|
2
|
+
class Model
|
3
|
+
class << self
|
4
|
+
# Recording
|
5
|
+
|
6
|
+
def increment(params)
|
7
|
+
key_data = fill_keys_for_update(params)
|
8
|
+
if @_type == :unique
|
9
|
+
argv = []
|
10
|
+
argv << params[:unique_id]
|
11
|
+
Redtastic::ScriptManager.msadd(key_data[0], argv)
|
12
|
+
else
|
13
|
+
Redtastic::ScriptManager.hmincrby(key_data[0], key_data[1].unshift(1))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def decrement(params)
|
18
|
+
key_data = fill_keys_for_update(params)
|
19
|
+
if @_type == :unique
|
20
|
+
argv = []
|
21
|
+
argv << params[:unique_id]
|
22
|
+
Redtastic::ScriptManager.msrem(key_data[0], argv)
|
23
|
+
else
|
24
|
+
Redtastic::ScriptManager.hmincrby(key_data[0], key_data[1].unshift(-1))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Retrieving
|
29
|
+
|
30
|
+
def find(params)
|
31
|
+
keys = []
|
32
|
+
argv = []
|
33
|
+
|
34
|
+
# Construct the key's timestamp from inputed date parameters
|
35
|
+
timestamp = ''
|
36
|
+
timestamp += "#{params[:year]}"
|
37
|
+
timestamp += "-#{zeros(params[:month])}" if params[:month].present?
|
38
|
+
timestamp += "-W#{params[:week]}" if params[:week].present?
|
39
|
+
timestamp += "-#{zeros(params[:day])}" if params[:day].present?
|
40
|
+
params.merge!(timestamp: timestamp)
|
41
|
+
|
42
|
+
# Handle multiple ids
|
43
|
+
ids = param_to_array(params[:id])
|
44
|
+
|
45
|
+
ids.each do |id|
|
46
|
+
params[:id] = id
|
47
|
+
keys << key(params)
|
48
|
+
argv << index(id)
|
49
|
+
end
|
50
|
+
|
51
|
+
if @_type == :unique
|
52
|
+
unique_argv = []
|
53
|
+
unique_argv << params[:unique_id]
|
54
|
+
result = Redtastic::ScriptManager.msismember(keys, unique_argv)
|
55
|
+
else
|
56
|
+
result = Redtastic::ScriptManager.hmfind(keys, argv)
|
57
|
+
end
|
58
|
+
|
59
|
+
# If only for a single id, just return the value rather than an array
|
60
|
+
if result.size == 1
|
61
|
+
result[0]
|
62
|
+
else
|
63
|
+
result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def aggregate(params)
|
68
|
+
key_data = fill_keys_and_dates(params)
|
69
|
+
keys = key_data[0]
|
70
|
+
|
71
|
+
# If interval is present, we return a hash including the total as well as a data point for each interval.
|
72
|
+
# Example: Visits.aggregate(start_date: 2014-01-05, end_date: 2013-01-06, id: 1, interval: :days)
|
73
|
+
# {
|
74
|
+
# visits: 2
|
75
|
+
# days: [
|
76
|
+
# {
|
77
|
+
# created_at: 2014-01-05,
|
78
|
+
# visits: 1
|
79
|
+
# },
|
80
|
+
# {
|
81
|
+
# created_at: 2014-01-06,
|
82
|
+
# visits: 1
|
83
|
+
# }
|
84
|
+
# ]
|
85
|
+
# }
|
86
|
+
if params[:interval].present? && @_resolution.present?
|
87
|
+
if @_type == :unique
|
88
|
+
argv = []
|
89
|
+
argv << key_data[1].shift # Only need the # of business ids (which is 1st element) from key_data[1]
|
90
|
+
argv << temp_key
|
91
|
+
if params[:attributes].present?
|
92
|
+
attributes = param_to_array(params[:attributes])
|
93
|
+
attributes.each do |attribute|
|
94
|
+
keys << attribute_key(attribute)
|
95
|
+
argv << 1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
data_points = Redtastic::ScriptManager.union_data_points_for_keys(keys, argv)
|
99
|
+
else
|
100
|
+
data_points = Redtastic::ScriptManager.data_points_for_keys(keys, key_data[1])
|
101
|
+
end
|
102
|
+
|
103
|
+
result = HashWithIndifferentAccess.new
|
104
|
+
dates = key_data[2]
|
105
|
+
# The data_points_for_keys lua script returns an array of all the data points, with one exception:
|
106
|
+
# the value at index 0 is the total across all the data points, so we pop it off of the data points array.
|
107
|
+
result[model_name] = data_points.shift
|
108
|
+
result[params[:interval]] = []
|
109
|
+
|
110
|
+
data_points.each_with_index do |data_point, index|
|
111
|
+
point_hash = HashWithIndifferentAccess.new
|
112
|
+
point_hash[model_name] = data_point
|
113
|
+
point_hash[:date] = dates[index]
|
114
|
+
result[params[:interval]] << point_hash
|
115
|
+
end
|
116
|
+
result
|
117
|
+
else
|
118
|
+
# If interval is not present, we just return the total as an integer
|
119
|
+
if @_type == :unique
|
120
|
+
argv = []
|
121
|
+
argv << temp_key
|
122
|
+
if params[:attributes].present?
|
123
|
+
attributes = param_to_array(params[:attributes])
|
124
|
+
attributes.each do |attribute|
|
125
|
+
keys << attribute_key(attribute)
|
126
|
+
argv << 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
Redtastic::ScriptManager.msunion(keys, argv)
|
130
|
+
else
|
131
|
+
key_data[1].shift # Remove the number of ids from the argv array (don't need it in the sum method)
|
132
|
+
Redtastic::ScriptManager.sum(keys, key_data[1]).to_i
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def type(type_name)
|
140
|
+
types = [:counter, :unique, :mosaic]
|
141
|
+
fail "#{type_name} is not a valid type" unless types.include?(type_name)
|
142
|
+
@_type = type_name
|
143
|
+
end
|
144
|
+
|
145
|
+
def resolution(resolution_name)
|
146
|
+
resolutions = [:days, :weeks, :months, :years]
|
147
|
+
fail "#{resolution_name} is not a valid resolution" unless resolutions.include?(resolution_name)
|
148
|
+
@_resolution = resolution_name
|
149
|
+
end
|
150
|
+
|
151
|
+
def fill_keys_for_update(params)
|
152
|
+
keys = []
|
153
|
+
argv = []
|
154
|
+
|
155
|
+
# Handle multiple keys
|
156
|
+
ids = param_to_array(params[:id])
|
157
|
+
|
158
|
+
ids.each do |id|
|
159
|
+
params[:id] = id
|
160
|
+
if params[:timestamp].present?
|
161
|
+
# This is for an update, so we want to build a key for each resolution that is applicable to the model
|
162
|
+
scoped_resolutions.each do |resolution|
|
163
|
+
keys << key(params, resolution)
|
164
|
+
argv << index(id)
|
165
|
+
end
|
166
|
+
else
|
167
|
+
keys << key(params)
|
168
|
+
argv << index(id)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
[keys, argv]
|
172
|
+
end
|
173
|
+
|
174
|
+
def fill_keys_and_dates(params)
|
175
|
+
keys = []
|
176
|
+
dates = []
|
177
|
+
argv = []
|
178
|
+
ids = param_to_array(params[:id])
|
179
|
+
|
180
|
+
argv << ids.size
|
181
|
+
start_date = Date.parse(params[:start_date]) if params[:start_date].is_a?(String)
|
182
|
+
end_date = Date.parse(params[:end_date]) if params[:end_date].is_a?(String)
|
183
|
+
|
184
|
+
if params[:interval].present?
|
185
|
+
interval = params[:interval]
|
186
|
+
else
|
187
|
+
interval = @_resolution
|
188
|
+
end
|
189
|
+
|
190
|
+
current_date = start_date
|
191
|
+
while current_date <= end_date
|
192
|
+
params[:timestamp] = current_date
|
193
|
+
dates << formatted_timestamp(current_date, interval)
|
194
|
+
ids.each do |id|
|
195
|
+
params[:id] = id
|
196
|
+
keys << key(params, interval)
|
197
|
+
argv << index(id)
|
198
|
+
end
|
199
|
+
current_date = current_date.advance(interval => +1)
|
200
|
+
end
|
201
|
+
[keys, argv, dates]
|
202
|
+
end
|
203
|
+
|
204
|
+
def key(params, interval = nil)
|
205
|
+
key = ''
|
206
|
+
key += "#{Redtastic::Connection.namespace}:" if Redtastic::Connection.namespace.present?
|
207
|
+
key += "#{model_name}"
|
208
|
+
if params[:timestamp].present?
|
209
|
+
timestamp = params[:timestamp]
|
210
|
+
timestamp = formatted_timestamp(params[:timestamp], interval) if interval.present?
|
211
|
+
key += ":#{timestamp}"
|
212
|
+
end
|
213
|
+
if @_type == :counter
|
214
|
+
key += ":#{bucket(params[:id])}"
|
215
|
+
else
|
216
|
+
key += ":#{params[:id]}" if params[:id].present?
|
217
|
+
end
|
218
|
+
key
|
219
|
+
end
|
220
|
+
|
221
|
+
def formatted_timestamp(timestamp, interval)
|
222
|
+
timestamp = Date.parse(timestamp) if timestamp.is_a?(String)
|
223
|
+
case interval
|
224
|
+
when :days
|
225
|
+
timestamp.strftime('%Y-%m-%d')
|
226
|
+
when :weeks
|
227
|
+
week_number = timestamp.cweek
|
228
|
+
result = timestamp.strftime('%Y')
|
229
|
+
result + "-W#{week_number}"
|
230
|
+
when :months
|
231
|
+
timestamp.strftime('%Y-%m')
|
232
|
+
when :years
|
233
|
+
timestamp.strftime('%Y')
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def bucket(id)
|
238
|
+
@_type == :counter ? id / 1000 : id
|
239
|
+
end
|
240
|
+
|
241
|
+
def index(id)
|
242
|
+
id % 1000 if id.is_a?(Integer)
|
243
|
+
end
|
244
|
+
|
245
|
+
def zeros(number)
|
246
|
+
"0#{number}" if number < 10
|
247
|
+
end
|
248
|
+
|
249
|
+
def model_name
|
250
|
+
name.underscore
|
251
|
+
end
|
252
|
+
|
253
|
+
def scoped_resolutions
|
254
|
+
case @_resolution
|
255
|
+
when :days
|
256
|
+
[:days, :weeks, :months, :years]
|
257
|
+
when :weeks
|
258
|
+
[:weeks, :months, :years]
|
259
|
+
when :months
|
260
|
+
[:months, :years]
|
261
|
+
when :years
|
262
|
+
[:years]
|
263
|
+
else
|
264
|
+
[]
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def param_to_array(param)
|
269
|
+
result = []
|
270
|
+
param.is_a?(Array) ? result = param : result << param
|
271
|
+
end
|
272
|
+
|
273
|
+
def temp_key
|
274
|
+
seed = Array.new(8) { [*'a'..'z'].sample }.join
|
275
|
+
"temp:#{seed}"
|
276
|
+
end
|
277
|
+
|
278
|
+
def attribute_key(attribute)
|
279
|
+
key = ''
|
280
|
+
key += "#{Redtastic::Connection.namespace}:" if Redtastic::Connection.namespace.present?
|
281
|
+
key + attribute.to_s
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Redtastic
|
2
|
+
class ScriptManager
|
3
|
+
class << self
|
4
|
+
def load_scripts(script_path)
|
5
|
+
@stored_methods = HashWithIndifferentAccess.new unless @stored_methods.is_a?(Hash)
|
6
|
+
Dir["#{script_path}/*.lua"].map do |file|
|
7
|
+
method = File.basename(file, '.*')
|
8
|
+
unless @stored_methods.key?(method)
|
9
|
+
@stored_methods[method] = Redtastic::Connection.redis.script(:load, `cat #{file}`)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method_name, *args)
|
15
|
+
if @stored_methods.is_a?(Hash) && @stored_methods.key?(method_name)
|
16
|
+
Redtastic::Connection.redis.evalsha(@stored_methods[method_name], *args)
|
17
|
+
else
|
18
|
+
fail("Could not find script: #{method_name}.lua")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def flush_scripts
|
23
|
+
@stored_methods = nil
|
24
|
+
Redtastic::Connection.redis.script(:flush)
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_ary
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
-- Returns total combined sum accross all ids and keys, as well as the combined sum accross all ids for each
|
2
|
+
-- specified data point interval
|
3
|
+
|
4
|
+
local result = {}
|
5
|
+
local sum = 0
|
6
|
+
local number_of_ids = tonumber(ARGV[1])
|
7
|
+
local data_point_index = 2 -- Initialized to 2 since position 1 in result is reserved for the total sum
|
8
|
+
local count = 1 -- Used to track whether we should should move to the next data point
|
9
|
+
|
10
|
+
for index, key in ipairs(KEYS) do
|
11
|
+
-- Get the value associated with the KEY + INDEX pair
|
12
|
+
local value = tonumber(redis.call('HGET', key, ARGV[index+1]))
|
13
|
+
|
14
|
+
-- Initialize the total value for the data point if it hasn't been initialized already
|
15
|
+
if result[data_point_index] == nil then
|
16
|
+
result[data_point_index] = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
if value then
|
20
|
+
sum = sum + value
|
21
|
+
result[data_point_index] = result[data_point_index] + value
|
22
|
+
end
|
23
|
+
|
24
|
+
-- Check if we've accounted for each id for the current data point
|
25
|
+
-- If true, then move to the next data point
|
26
|
+
if count == number_of_ids then
|
27
|
+
count = 1
|
28
|
+
data_point_index = data_point_index + 1
|
29
|
+
else
|
30
|
+
count = count + 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
-- Position 1 in the result array is reserved for the sum
|
35
|
+
result[1] = sum
|
36
|
+
|
37
|
+
return result
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-- Returns an array of values for each corresponding key/index pair passed into KEYS & ARGV
|
2
|
+
|
3
|
+
local result = {}
|
4
|
+
|
5
|
+
for index, key in ipairs(KEYS) do
|
6
|
+
local value = tonumber(redis.call('HGET', key, ARGV[index]))
|
7
|
+
if value then
|
8
|
+
result[index] = value
|
9
|
+
else
|
10
|
+
result[index] = 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
return result
|
@@ -0,0 +1,9 @@
|
|
1
|
+
-- Increments each corresponding key/index pair passed into KEYS & ARGV
|
2
|
+
-- SPECIAL: the first index in ARGV needs to be set to the value to increment by
|
3
|
+
|
4
|
+
local incrby = ARGV[1]
|
5
|
+
|
6
|
+
for index, key in ipairs(KEYS) do
|
7
|
+
-- For each key / id increment by the passed in value
|
8
|
+
redis.call('HINCRBY', key, ARGV[index+1], incrby)
|
9
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
-- SPECIAL: ARGV[1] -> tempkey
|
2
|
+
-- SPECIAL: All ARGV[n], where n > 1, signify an attribute
|
3
|
+
-- SPECIAL: last n keys, where n is number of attributes, is keys associated with attributes
|
4
|
+
|
5
|
+
local num_attributes = table.getn(ARGV) - 1
|
6
|
+
local attribute_keys = {}
|
7
|
+
|
8
|
+
-- Remove keys associated with attributes and add them to our own attributes_keys array
|
9
|
+
for i=1,num_attributes do
|
10
|
+
table.insert(attribute_keys, table.remove(KEYS))
|
11
|
+
end
|
12
|
+
|
13
|
+
-- union all of the keys
|
14
|
+
redis.call('sunionstore', ARGV[1], unpack(KEYS))
|
15
|
+
|
16
|
+
-- If attributes are present, we want to get the intersect of the result + any attributes and store in ARGV[1]
|
17
|
+
if num_attributes > 0 then
|
18
|
+
table.insert(attribute_keys, ARGV[1])
|
19
|
+
redis.call('sinterstore', ARGV[1], unpack(attribute_keys))
|
20
|
+
end
|
21
|
+
|
22
|
+
-- get the cardinality of the resulting set
|
23
|
+
local count = redis.call('scard', ARGV[1])
|
24
|
+
|
25
|
+
-- delete the temp key
|
26
|
+
redis.call('del', ARGV[1])
|
27
|
+
|
28
|
+
return count
|
@@ -0,0 +1,13 @@
|
|
1
|
+
-- Returns the total sum of the values of each key/index pair passed into KEYS & ARGV
|
2
|
+
|
3
|
+
local sum = 0
|
4
|
+
|
5
|
+
for index, key in ipairs(KEYS) do
|
6
|
+
-- For each key, read the value and add it to the total
|
7
|
+
local value = tonumber(redis.call('HGET', key, ARGV[index]))
|
8
|
+
if value then
|
9
|
+
sum = sum + value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
return sum
|
@@ -0,0 +1,51 @@
|
|
1
|
+
-- SPECIAL: ARGV[1] -> number_of_ids
|
2
|
+
-- SPECIAL: ARGV[2] -> temp_key
|
3
|
+
-- SPECIAL: All ARGV[n], where n > 2, signify an attribute
|
4
|
+
-- SPECIAL: last n keys, where n is number of attributes, is keys associated with attributes
|
5
|
+
|
6
|
+
local result = {}
|
7
|
+
local number_of_ids = tonumber(ARGV[1])
|
8
|
+
local data_point_index = 2
|
9
|
+
local count = 1
|
10
|
+
local num_attributes = table.getn(ARGV) - 2
|
11
|
+
local attribute_keys = {}
|
12
|
+
|
13
|
+
-- Remove keys associated with attributes and add them to our own attributes_keys array
|
14
|
+
for i=1,num_attributes do
|
15
|
+
table.insert(attribute_keys, table.remove(KEYS))
|
16
|
+
end
|
17
|
+
|
18
|
+
-- union all of the keys
|
19
|
+
redis.call('sunionstore', ARGV[2], unpack(KEYS))
|
20
|
+
|
21
|
+
-- If attribute are present, we want to get the intersect of the result + any attributes and store in ARGV[2]
|
22
|
+
if num_attributes > 0 then
|
23
|
+
redis.call('sinterstore', ARGV[2], ARGV[2], unpack(attribute_keys))
|
24
|
+
end
|
25
|
+
|
26
|
+
-- get the cardinality of the resulting set
|
27
|
+
result[1] = redis.call('scard', ARGV[2])
|
28
|
+
|
29
|
+
-- This loop returns the union of all the keys (for any number of ids) for each data point interval
|
30
|
+
local index = 1
|
31
|
+
while KEYS[index] do
|
32
|
+
local keys = {}
|
33
|
+
for i=0,(number_of_ids-1) do
|
34
|
+
keys[i+1] = KEYS[index+i]
|
35
|
+
end
|
36
|
+
redis.call('sunionstore', ARGV[2], unpack(keys))
|
37
|
+
|
38
|
+
-- If attributes are present, we want to get the interset of this data points result + any attributes
|
39
|
+
if num_attributes > 0 then
|
40
|
+
redis.call('sinterstore', ARGV[2], ARGV[2], unpack(attribute_keys))
|
41
|
+
end
|
42
|
+
|
43
|
+
result[data_point_index] = redis.call('scard', ARGV[2])
|
44
|
+
data_point_index = data_point_index + 1
|
45
|
+
index = index + number_of_ids
|
46
|
+
end
|
47
|
+
|
48
|
+
-- delete the temp key
|
49
|
+
redis.call('del', ARGV[2])
|
50
|
+
|
51
|
+
return result
|
data/redtastic.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/redtastic/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'redtastic'
|
6
|
+
gem.version = Redtastic::VERSION
|
7
|
+
gem.date = '2013-01-15'
|
8
|
+
gem.authors = ['Joe DiVita']
|
9
|
+
gem.email = ['joediv31@gmail.com']
|
10
|
+
gem.description = %q{ A simple, Redis-backed interface for storing, retrieving, and aggregating analytics }
|
11
|
+
gem.summary = %q{ A simple, Redis-backed interface for storing, retrieving, and aggregating analytics }
|
12
|
+
gem.homepage = 'https://github.com/bellycard/redtastic'
|
13
|
+
gem.files = `git ls-files`.split($\)
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
|
17
|
+
gem.add_dependency 'redis'
|
18
|
+
gem.add_dependency 'activesupport'
|
19
|
+
|
20
|
+
gem.add_development_dependency 'dotenv'
|
21
|
+
gem.add_development_dependency 'rspec'
|
22
|
+
gem.add_development_dependency 'pry'
|
23
|
+
gem.add_development_dependency 'git'
|
24
|
+
gem.add_development_dependency 'rubocop'
|
25
|
+
gem.add_development_dependency 'simplecov'
|
26
|
+
gem.add_development_dependency 'coveralls'
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Redtastic::Connection do
|
4
|
+
before do
|
5
|
+
# Reset any connections
|
6
|
+
Redtastic::Connection.redis = nil
|
7
|
+
Redtastic::Connection.namespace = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#establish_connection' do
|
11
|
+
before do
|
12
|
+
Redtastic::ScriptManager.stub(:load_scripts)
|
13
|
+
redis = Redis.new(host: 'foo', port: 9000)
|
14
|
+
Redtastic::Connection.establish_connection(redis, 'bar')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'properly sets the redis connection' do
|
18
|
+
expect(Redtastic::Connection.redis.client.host).to eq('foo')
|
19
|
+
expect(Redtastic::Connection.redis.client.port).to eq(9000)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'properly sets the namespace' do
|
23
|
+
expect(Redtastic::Connection.namespace).to eq('bar')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when setting options one at a time' do
|
28
|
+
before do
|
29
|
+
Redtastic::Connection.redis = Redis.new(host: 'foo', port: 1111)
|
30
|
+
Redtastic::Connection.namespace = 'bar'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'properly sets the redis connection' do
|
34
|
+
expect(Redtastic::Connection.redis.client.host).to eq('foo')
|
35
|
+
expect(Redtastic::Connection.redis.client.port).to eq(1111)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'properly sets the namespace' do
|
39
|
+
expect(Redtastic::Connection.namespace).to eq('bar')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|