redis-script_manager 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5a3988633cfd5315a4591a70edc873c902fe829
4
+ data.tar.gz: 9e279ed9af52df46d347c69a7f51ce21bf3cfc47
5
+ SHA512:
6
+ metadata.gz: 4408f0dd1575e24f23cd5888d44ce7d539d47955cd9c19100237e886ead48b0b4fd49d3d6f84e79478c307e47d0ee69e5d77ca468029704b18bc30357adddf51
7
+ data.tar.gz: 754d3250762ec2fbbd0e058b403ba0797aa4d1899a0ba1bc04d79430574ed7d71e882242fbd81f39134a43b1f6b0aa88b58ae7b883e23c175cb3cb87fc54e307
data/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.1.6
5
+ before_install: gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in redis-script_manager.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ redis-script_manager (0.0.2)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.10.3)
10
+ rake (10.5.0)
11
+ redis (3.3.3)
12
+ redis-namespace (1.5.3)
13
+ redis (~> 3.0, >= 3.0.4)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ bundler (~> 1.14)
20
+ minitest (~> 5.0)
21
+ rake (~> 10.0)
22
+ redis (~> 3.2)
23
+ redis-namespace (~> 1.5)
24
+ redis-script_manager!
25
+
26
+ BUNDLED WITH
27
+ 1.15.3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 ProsperWorks
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # Redis::ScriptManager
2
+
3
+ Redis::ScriptManager executes your Lua scripts in your Redis
4
+ infrastructure while managing trade-offs between bandwidth and
5
+ statefulness.
6
+
7
+ ## Other Packages With Related Functionality
8
+
9
+ ### resque-scheduler
10
+
11
+ https://github.com/resque/resque-scheduler
12
+
13
+ Resque::Scheduler::Lock::Resiliant manages its scripts with
14
+ load-on-init and EVALSHA-else-SCRIPT-LOAD-and-re-EVALSHA.
15
+
16
+ This is robust if there are no SCRIPT FLUSH or no pipelines, but it
17
+ will fail if a SCRIPT FLUSH can happen after init, then we run in a
18
+ pipeline.
19
+
20
+ The Lua scripts in resque-scheduler are only a few 100s of bytes in
21
+ size, so there is little to be gained by avoiding simply using EVAL.
22
+
23
+ Warning: resque-scheduler embeds "#{timeout}" in its Lua scripts. One
24
+ is unlikely to change resque-scheduler lock timeouts frequently, but
25
+ if so it could be possible to fill the Redis script cache with tons of
26
+ abandoned scripts.
27
+
28
+ ### wolverine
29
+
30
+ https://github.com/Shopify/wolverine
31
+ http://shopify.github.io/wolverine/
32
+
33
+ Wolverine does load-on-init and EVALSHA-only. Assuming you have only
34
+ one Redis connection and SCRIPT FLUSH is never called, this is fine
35
+ even in a pipeline.
36
+
37
+ If you juggle multiple Redis connections or are worried about
38
+ inconsistent script cache contents, Wolverine might have some gaps.
39
+
40
+ Wolverine also has nice support for keeping your Lua scripts in a
41
+ repository of related .lua files, with support for common code
42
+ folding.
43
+
44
+ ### redis-lua
45
+
46
+ https://github.com/chanks/redis-lua
47
+
48
+ Redis-lua does EVALSHA-else-SCRIPT-LOAD-and-re-EVALSHA when not in a
49
+ pipeline, simple EVAL otherwise.
50
+
51
+ This is great: this is always correct regardless of how many Redises
52
+ you are talking to, and calls outside of a pipeline will tend toward
53
+ minimal bandwith as the script cache gets warmed up.
54
+
55
+ However, if most of your scripting is done within a pipeline,
56
+ bandwidth use will stay high.
57
+
58
+ Early iterations of redis-script_manager were inspired by redis-lua.
59
+
60
+ ### redis-rb-scripting
61
+
62
+ https://github.com/codekitchen/redis-rb-scripting
63
+
64
+ redis-rb-scripting does load-on-init plus EVALSHA-else-EVAL. It is
65
+ correct when the script cache is inconsistent but does not tend to
66
+ repopulate the cache in these cases.
67
+
68
+ redis-rb-scripting has no special provision for pipelines. Called in
69
+ a pipeline it will fail to recover from a cold cache.
70
+
71
+ Like wolverine, redis-rb-scripting also supports a repository of .lua
72
+ files, but without the common code folding.
73
+
74
+ ### led
75
+
76
+ https://github.com/ciconia/led
77
+
78
+ Like redis-rb-scripting, led does load-on-init plus EVALSHA-else-EVAL.
79
+ It is correct when the script cache is inconsistent but does not tend
80
+ to repopulate the cache in these cases. It has no special provision
81
+ for pipelines. Called in a pipeline it will fail to recover from a
82
+ cold cache.
83
+
84
+ Like wolverine, redis-rb-scripting also supports a repository of .lua
85
+ files with common code folding.
86
+
87
+
88
+ ## Installation
89
+
90
+ Add this line to your application's Gemfile:
91
+
92
+ ```ruby
93
+ gem 'redis-script_manager'
94
+ ```
95
+
96
+ And then execute:
97
+
98
+ $ bundle
99
+
100
+ Or install it yourself as:
101
+
102
+ $ gem install redis-script_manager
103
+
104
+ ## Usage
105
+
106
+ TODO: Write usage instructions here
107
+
108
+ ## Development
109
+
110
+ After checking out the repo, run `bin/setup` to install
111
+ dependencies. Then, run `rake test` to run the tests. You can also run
112
+ `bin/console` for an interactive prompt that will allow you to
113
+ experiment.
114
+
115
+ To install this gem onto your local machine, run `bundle exec rake
116
+ install`. To release a new version, update the version number in
117
+ `version.rb`, and then run `bundle exec rake release`, which will
118
+ create a git tag for the version, push git commits and tags, and push
119
+ the `.gem` file to [rubygems.org](https://rubygems.org).
120
+
121
+ ## Contributing
122
+
123
+ Bug reports and pull requests are welcome on GitHub at
124
+ https://github.com/[USERNAME]/redis-script_manager.
125
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "redis/script_manager"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,334 @@
1
+ require "redis/script_manager/version"
2
+
3
+ class Redis
4
+ class ScriptManager
5
+
6
+ # TODO: rubocop
7
+
8
+ # TODO: rdoc
9
+
10
+ # Efficiently evaluates a Lua script on Redis.
11
+ #
12
+ # Makes a best effort to moderate bandwidth by leveraging EVALSHA
13
+ # and managing the SCRIPT LOAD state.
14
+ #
15
+ # @param redis a Redis to call, must respond to :eval, :evalsha,
16
+ # and :script
17
+ #
18
+ # @param lua a String, the Lua script to execute on redis
19
+ #
20
+ # @param keys a list of String, the keys which will bind to the KEYS
21
+ # list in the lua script.
22
+ #
23
+ # @param args a list of arguments which will bind to ARGV list in
24
+ # the lua script.
25
+ #
26
+ # @return the return result of evaluating lua against keys and args
27
+ # on redis
28
+ #
29
+ # TODO: Should this just monkey-patch over Redis.eval?
30
+ #
31
+ def self.eval_gently(redis,lua,keys=[],args=[])
32
+ [:eval,:evalsha,:script,:client].each do |method|
33
+ if !redis.respond_to?(method) || !redis.respond_to?(:script)
34
+ raise ArgumentError, "bogus redis #{redis}, no #{method}"
35
+ end
36
+ end
37
+ if !lua.is_a?(String)
38
+ raise ArgumentError, "bogus lua #{lua}"
39
+ end
40
+ if !keys.is_a?(Array)
41
+ raise ArgumentError, "bogus keys #{keys}: non-array"
42
+ end
43
+ keys_classes = keys.map(&:class).uniq
44
+ if [] != keys_classes - [String,Symbol]
45
+ raise ArgumentError, "bogus keys #{keys}: bad types in #{keys_classes}"
46
+ end
47
+ if !args.is_a?(Array)
48
+ raise ArgumentError, "bogus args #{args}"
49
+ end
50
+ if keys.size < 1
51
+ raise ArgumentError, 'Twemproxy intolerant of 0 keys in EVAL or EVALSHA'
52
+ end
53
+ #
54
+ # Per http://redis.io/commands/eval:
55
+ #
56
+ # Redis does not need to recompile the script every time as it
57
+ # uses an internal caching mechanism, however paying the cost of
58
+ # the additional bandwidth may not be optimal in many contexts."
59
+ #
60
+ # So, where the bandwidth imposed by uploading a short script is
61
+ # small, we will just use EVAL. Also, in MONITOR streams it can
62
+ # be nice to see the Lua instead of a bunch of noisy shas.
63
+ #
64
+ # However, where the script is long we try to conserve bandwidth
65
+ # by trying EVALSHA first. In case our script has never been
66
+ # uploaded before, or if the Redis suffered a FLUSHDB or SCRIPT
67
+ # FLUSH, we catch NOSCRIPT error, recover with SCRIPT LOAD, and
68
+ # repeat the EVALSHA.
69
+ #
70
+ # Caveat: if all of this is wrapped in a Redis pipeline, then the
71
+ # first EVALSHA returns a Redis::Future, not a result. We won't
72
+ # know whether it throws an error until after the pipeline - and
73
+ # after we've committed to the rest of our stream of commands.
74
+ # Thus, we can't recover from a NOSCRIPT error.
75
+ #
76
+ # To be safe in this pipelined-but-not-in-script-database edge
77
+ # case, we stick with simple EVAL when we detect we are running
78
+ # within a pipeline.
79
+ #
80
+ if configuration.do_minify_lua
81
+ lua = self.minify_lua(lua)
82
+ end
83
+ if lua.size < configuration.max_tiny_lua
84
+ _statsd_increment("eval")
85
+ return redis.eval(lua,keys,args)
86
+ end
87
+ if configuration.do_preload
88
+ #
89
+ # I tested RLEC in ali-staging with this script:
90
+ #
91
+ # sha = Redis.current.script(:load,'return redis.call("get",KEYS[1])')
92
+ # 100.times.map { |n| "foo-#{n}" }.each do |key|
93
+ # set = Redis.current.set(key,key)
94
+ # get = Redis.current.evalsha(sha,[key])
95
+ # puts "%7s %7s %7s" % [key,get,set]
96
+ # end
97
+ #
98
+ # Sure enough, all 100 EVALSHA worked. Since ali-staging is a
99
+ # full-weight sharded RLEC, this tells me that SCRIPT LOAD
100
+ # propagates to all Redis shards in RLEC.
101
+ #
102
+ # Thus, we can trust that any script need only be sent down a
103
+ # particular Redis connection once. Thereafter we can assume
104
+ # EVALSHA will work.
105
+ #
106
+ # I do not know if the same thing will happen in Redis Cluster,
107
+ # and I am just about certain that the more primitive
108
+ # Twemproxy-over-array-of-plain-Redis will *not* propagate
109
+ # SCRIPT this way.
110
+ #
111
+ # Here is an twemproxy issue which tracks this question
112
+ # https://github.com/twitter/twemproxy/issues/68.
113
+ #
114
+ # This implementation is meant to transmit each script to each
115
+ # Redis no more than once per process, and thereafter be
116
+ # pure-EVALSHA.
117
+ #
118
+ sha = Digest::SHA1.hexdigest(lua)
119
+ sha_connection_key = [redis.object_id,sha]
120
+ if !@@preloaded_shas.include?(sha_connection_key)
121
+ _statsd_increment("preloaded_shas.cache_miss")
122
+ new_sha = redis.script(:load,lua)
123
+ if !new_sha.is_a?(Redis::Future)
124
+ if sha != new_sha
125
+ raise RuntimeError, "mismatch #{sha} vs #{new_sha} for lua #{lua}"
126
+ end
127
+ end
128
+ @@preloaded_shas << sha_connection_key
129
+ else
130
+ _statsd_increment("preloaded_shas.cache_hit")
131
+ end
132
+ result = redis.evalsha(sha,keys,args)
133
+ if configuration.preload_cache_size < @@preloaded_shas.size
134
+ #
135
+ # To defend against unbound cache size, at a predetermined
136
+ # limit throw away half of them.
137
+ #
138
+ # It is benign to re-load a script, just a performance blip.
139
+ #
140
+ # If these caches are running away in size, we have a worse
141
+ # time: redis.info.used_memory_lua could be growing without
142
+ # bound.
143
+ #
144
+ _statsd_increment("preloaded_shas.cache_purge")
145
+ num_to_keep = @@preloaded_shas.size / 2
146
+ @@preloaded_shas = @@preloaded_shas.to_a.sample(num_to_keep)
147
+ end
148
+ cache_size = @@preloaded_shas.size
149
+ _statsd_timing("preloaded_shas.cache_size",cache_size)
150
+ return result
151
+ end
152
+ in_pipeline = redis.client.is_a?(Redis::Pipeline) # thanks @marshall
153
+ if in_pipeline
154
+ _statsd_increment("pipeline_eval")
155
+ return redis.eval(lua,keys,args)
156
+ end
157
+ sha = Digest::SHA1.hexdigest(lua)
158
+ begin
159
+ _statsd_increment("evalsha1")
160
+ result = redis.evalsha(sha,keys,args)
161
+ if result.is_a?(Redis::Future)
162
+ #
163
+ # We should have detected this above where we checked whether
164
+ # redis.client was a pipeline.
165
+ #
166
+ raise "internal error: unexpected Redis::Future from evalsha"
167
+ end
168
+ result
169
+ rescue Redis::CommandError => ex
170
+ if nil != ex.to_s.index('NOSCRIPT') # some vulerability to change in msg
171
+ _statsd_increment("script_load")
172
+ new_sha = redis.script(:load,lua)
173
+ if sha != new_sha
174
+ raise RuntimeError, "mismatch #{sha} vs #{new_sha} for lua #{lua}"
175
+ end
176
+ _statsd_increment("evalsha2")
177
+ return redis.evalsha(sha,keys,args)
178
+ end
179
+ raise ex
180
+ end
181
+ end
182
+
183
+ @@preloaded_shas = Set[] # [redis.object_id,sha(lua)] which have been loaded
184
+
185
+ def self.purge_preloaded_shas # for test, clean state
186
+ @@preloaded_shas = Set[]
187
+ end
188
+
189
+ # To save bandwidth, minify the Lua code.
190
+ #
191
+ def self.minify_lua(lua)
192
+ lua
193
+ .split("\n")
194
+ .map { |l| l.gsub(/\s*--[^'"]*$/,'').strip } # rest-of-line comments
195
+ .reject { |l| /^\s*$/ =~ l } # blank lines
196
+ .join("\n")
197
+ end
198
+
199
+ # Reports a single count on the requested metric to statsd (if
200
+ # any).
201
+ #
202
+ # @param metric String
203
+ #
204
+ def self._statsd_increment(metric)
205
+ if configuration.statsd
206
+ configuration.statsd.increment(configuration.stats_prefix+metric)
207
+ end
208
+ end
209
+
210
+ # Reports a timing on the requested metric to statsd (if any).
211
+ #
212
+ # @param metric String
213
+ #
214
+ def self._statsd_timing(metric,timing)
215
+ if configuration.statsd
216
+ configuration.statsd.timing(configuration.stats_prefix+metric,timing)
217
+ end
218
+ end
219
+
220
+ # @returns the current Redis::ScriptManager::Configuration.
221
+ #
222
+ def self.configuration
223
+ @configuration ||= Configuration.new
224
+ end
225
+
226
+ # Sets the current Redis::ScriptManager::Configuration.
227
+ #
228
+ def self.configuration=(configuration)
229
+ @configuration = configuration
230
+ end
231
+
232
+ # Yields the current Redis::ScriptManager::Configuration, supports
233
+ # the typical gem configuration pattern:
234
+ #
235
+ # Redis::ScriptManager.configure do |config|
236
+ # config.statsd = $statsd
237
+ # config.stats_prefix = 'foo'
238
+ # config.minify_lua = true
239
+ # config.max_tiny_lua = 1235
240
+ # config.preload_shas = true
241
+ # config.preload_cache_size = 10
242
+ # end
243
+ #
244
+ def self.configure
245
+ yield configuration
246
+ end
247
+
248
+ class Configuration
249
+
250
+ # Defaults to nil. If non-nil, lots of stats will be tracked via
251
+ # statsd.increment and statsd.timing.
252
+ #
253
+ def statsd
254
+ @statsd || nil
255
+ end
256
+ def statsd=(statsd)
257
+ if statsd && !statsd.respond_to?(:increment)
258
+ raise ArgumentError, "bogus statsd A #{statsd}"
259
+ end
260
+ if statsd && !statsd.respond_to?(:timing)
261
+ raise ArgumentError, "bogus statsd B #{statsd}"
262
+ end
263
+ @statsd = statsd
264
+ end
265
+
266
+ # Defaults to ''.
267
+ #
268
+ # Prefixed onto all metrics.
269
+ #
270
+ def stats_prefix
271
+ @stats_prefix || ''
272
+ end
273
+ def stats_prefix=(stats_prefix)
274
+ if stats_prefix && !stats_prefix.is_a?(String)
275
+ raise ArgumentError, "bogus stats_prefix"
276
+ end
277
+ @stats_prefix = stats_prefix || ''
278
+ end
279
+
280
+ # Defaults to false.
281
+ #
282
+ # If true, all Lua is minified conservatively to save bandwidth
283
+ # before any other logic or evaluation.
284
+ #
285
+ def do_minify_lua
286
+ @do_minify_lua || false
287
+ end
288
+ def do_minify_lua=(do_minify_lua)
289
+ @do_minify_lua = [true,'true'].include?(do_minify_lua)
290
+ end
291
+
292
+ # Scripts shorter than max_tiny_lua are always EVALed.
293
+ #
294
+ # We skip all logic regarding EVALSHA, extra round-trips for
295
+ # SCRIPT LOAD, etc.
296
+ #
297
+ # Defaults to 512. Integers and Strings which convert to Integers OK.
298
+ #
299
+ def max_tiny_lua
300
+ @max_tiny_lua || 512
301
+ end
302
+ def max_tiny_lua=(max_tiny_lua)
303
+ @max_tiny_lua = max_tiny_lua.to_i
304
+ end
305
+
306
+ # Defaults to false.
307
+ #
308
+ # If true, shas are preloaded for each Redis connection (which
309
+ # make safe to use EVALSHA even in pipelines).
310
+ #
311
+ def do_preload
312
+ @do_preload || false
313
+ end
314
+ def do_preload=(do_preload)
315
+ @do_preload = [true,'true'].include?(do_preload)
316
+ end
317
+
318
+ # The cache of shas which have been preloaded is not allowed to
319
+ # grow larger than this value.
320
+ #
321
+ # Defaults to 1000.
322
+ #
323
+ def preload_cache_size
324
+ @preload_cache_size || 1000
325
+ end
326
+ def preload_cache_size=(preload_cache_size)
327
+ @preload_cache_size = preload_cache_size.to_i
328
+ end
329
+
330
+ end
331
+
332
+ end
333
+
334
+ end
@@ -0,0 +1,17 @@
1
+ class Redis
2
+ class ScriptManager
3
+ #
4
+ # Version plan:
5
+ #
6
+ # 0.0.1 - still in Prosperworks/ALI/vendor/gems/redis-script_manager
7
+ #
8
+ # 0.0.2 - broke out into Prosperworks/redis-script_manager
9
+ #
10
+ # 0.1.0 - big README.md and Rdoc update, open repo
11
+ #
12
+ # 0.2.0 - solicit and incorporate initial feedback from select
13
+ # beta external users
14
+ #
15
+ VERSION = "0.0.2" # broken into standalone repo, not polished
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'redis/script_manager/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+
7
+ spec.name = "redis-script_manager"
8
+ spec.version = Redis::ScriptManager::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+
11
+ spec.authors = ["jhwillett"]
12
+ spec.email = ["jhw@prosperworks.com"]
13
+
14
+ spec.summary = 'Manage Lua script execution in Redis'
15
+ spec.homepage = 'https://github.com/ProsperWorks/redis-script_manager'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.14'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'minitest', '~> 5.0'
27
+ spec.add_development_dependency 'redis', '~> 3.2'
28
+ spec.add_development_dependency 'redis-namespace', '~> 1.5'
29
+
30
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis-script_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - jhwillett
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redis-namespace
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.5'
83
+ description:
84
+ email:
85
+ - jhw@prosperworks.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/setup
99
+ - lib/redis/script_manager.rb
100
+ - lib/redis/script_manager/version.rb
101
+ - redis-script_manager.gemspec
102
+ homepage: https://github.com/ProsperWorks/redis-script_manager
103
+ licenses: []
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.4.8
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Manage Lua script execution in Redis
125
+ test_files: []