shavaluator 0.1

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: 43d2339fcfa21cdc7ab98bd19be457c4ec1675d4
4
+ data.tar.gz: 441c001a06b3b2fb0f642a4c8b0bfaf7804fa91f
5
+ SHA512:
6
+ metadata.gz: de247f58819511ee9006857985677815fff46d39bd0ad61eac46661d0446e7a7917d5dd238eb97024dc83f8262d45cc3e37b943abdf8f97200b97ba1fecf6583
7
+ data.tar.gz: f0bc3bbc2477d69842301b1d69e1bbd43ef58ce58411ba030fb8a5b76759f60c77498492af69cf3ad11a664d6892699d1c9549650570ff56a1e03492066ca390
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Jeff Lee <jeffomatic@gmail.com>
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,104 @@
1
+ # shavaluator
2
+
3
+ This library provides a convenient wrapper for sending Lua scripts to a Redis server via `EVALSHA`.
4
+
5
+ ## What is EVALSHA?
6
+
7
+ `EVALSHA` allows you to send Lua scripts to a Redis server by sending the SHA-1 hashes instead of actual script content. As long as the body of your script was previously sent to Redis via `EVAL` or `SCRIPT LOAD`, you can use `EVALSHA` to avoid the overhead of sending your entire Lua script over the network.
8
+
9
+ A Shavaluator object wraps a Redis client for executing Lua scripts. When executing Lua scripts, a shavaluator will always attempt `EVALSHA` first, falling back on `EVAL` if the script has not yet been cached by the Redis server.
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ require 'redis'
15
+ require 'shavaluator'
16
+
17
+ # 1. Initialize a shavaluator with a Redis client
18
+ redis = Redis.new(:host => '127.0.0.1', :port => 6379)
19
+ shavaluator = Shavaluator.new(:redis => redis)
20
+
21
+ # 2. Add a series of named Lua scripts to the shavaluator.
22
+ shavaluator.add(
23
+ :delequal => """
24
+ if redis.call('GET', KEYS[1]) == ARGV[1] then
25
+ return redis.call('DEL', KEYS[i])
26
+ end
27
+ return 0
28
+ """
29
+ )
30
+
31
+ # 3. The 'delequal' script is now added to the shavaluator and bound
32
+ # as a method. When you call this, the shavaluator will first attempt
33
+ # an EVALSHA, and fall back onto EVAL.
34
+ shavaluator.delequal :keys => ['key'], :argv => ['val']
35
+ ```
36
+
37
+ ## Adding scripts
38
+
39
+ Before you can run Lua scripts, you should give each one a name and add them to a shavaluator.
40
+
41
+ ```ruby
42
+ scripts = {
43
+ :delequal => """
44
+ if redis.call('GET', KEYS[1]) == ARGV[1] then
45
+ return redis.call('DEL', KEYS[i])
46
+ end
47
+ return 0
48
+ """,
49
+
50
+ :zmembers => """
51
+ local key = KEYS[1]
52
+ local results = {}
53
+ if redis.call('ZCARD', key) == 0 then
54
+ return {}
55
+ end
56
+ for i = 1, #ARGV, 1 do
57
+ local memberName = ARGV[i]
58
+ if redis.call('ZSCORE', key, memberName) then
59
+ table.insert(results, memberName)
60
+ end
61
+ end
62
+ return results
63
+ """,
64
+ }
65
+
66
+ shavaluator.add scripts
67
+ ```
68
+
69
+ Adding a script does two things by default: it generates the SHA-1 of the script body, and binds the script name as a method on the shavaluator object. It **does not** perform any network operations, such as sending `SCRIPT LOAD` to the Redis server.
70
+
71
+ ## Executing scripts
72
+
73
+ By default, adding a script to a shavaluator will bind each script as a method on the shavaluator object. These methods preserve [redis-rb](https://github.com/redis/redis-rb)'s calling convention for Lua scripts, where keys and script arguments are either passed via a hash, or as a pair of arrays.
74
+
75
+ - **hash**: `shavaluator.your_script :keys => ['key1', 'key2'], :argv => ['arg1', 'arg2']`
76
+ - **array pair**: `shavaluator.your_script ['key1', 'key2'], ['arg1', 'arg2']`
77
+
78
+ If you don't like the auto-binding interface, you can use the `exec` function, which takes the name of a script.
79
+
80
+ ```ruby
81
+ shavaluator.exec 'your_script', :keys => ['key1', 'key2'], :argv => ['arg1', 'arg2']
82
+ ```
83
+
84
+ ## Class reference
85
+
86
+ ### new(opts)
87
+
88
+ Creates a new Shavaluator object.
89
+
90
+ Options:
91
+
92
+ - `:redis`: (required) an instance of a [redis-rb](https://github.com/redis/redis-rb) client that the Shavaluator will use to connect to a Redis server.
93
+
94
+ ### add(scripts, opts = {})
95
+
96
+ Adds Lua scripts to the shavaluator. scripts is a key/value object, mapping script names to script bodies.
97
+
98
+ Options:
99
+
100
+ - `:bind`: (defaults to `true`) new methods will be created for each script.
101
+
102
+ ### exec(script_name, params...)
103
+
104
+ Executes the script corresponding to the provided `script_name`. Script parameters can be passed in two different ways. See [Executing scripts](#executing-scripts) for usage examples.
@@ -0,0 +1,63 @@
1
+ require 'digest/sha1'
2
+
3
+ class Shavaluator
4
+ def initialize(opts)
5
+ @redis = opts[:redis]
6
+ @scripts = {}
7
+ end
8
+
9
+ def add(scripts, opts = {})
10
+ defaults = {:bind => true}
11
+ opts = {}.merge(defaults).merge(opts)
12
+
13
+ scripts.each do |name, lua|
14
+ name = name.to_sym
15
+
16
+ @scripts[name.to_sym] = {
17
+ :lua => lua,
18
+ :sha => Digest::SHA1.hexdigest(lua),
19
+ }
20
+
21
+ if opts[:bind]
22
+ raise "#{name} method already defined!" if respond_to?(name)
23
+ define_singleton_method(name) do |*args|
24
+ exec name, *args
25
+ end
26
+ end
27
+ end
28
+
29
+ nil
30
+ end
31
+
32
+ # This method calls a previously-added lua script. The argument syntax
33
+ # is the same as redis-rb's eval and evalsha methods.
34
+ #
35
+ # @example EVAL without KEYS nor ARGV
36
+ # shavaluator.exec(:script)
37
+ # # => 1
38
+ # @example EVAL with KEYS and ARGV as array arguments
39
+ # shavaluator.exec(:script, ["k1", "k2"], ["a1", "a2"])
40
+ # # => [["k1", "k2"], ["a1", "a2"]]
41
+ # @example EVAL with KEYS and ARGV in a hash argument
42
+ # shavaluator.exec(:script, :keys => ["k1", "k2"], :argv => ["a1", "a2"])
43
+ # # => [["k1", "k2"], ["a1", "a2"]]
44
+ def exec(script, *args)
45
+ begin
46
+ s = @scripts.fetch(script.to_sym)
47
+ rescue KeyError
48
+ raise "'#{script}' script has not been added yet!"
49
+ end
50
+
51
+ lua, sha = s.values_at(:lua, :sha)
52
+
53
+ begin
54
+ @redis.evalsha(s[:sha], *args)
55
+ rescue Redis::CommandError => e
56
+ if e.to_s.match /^NOSCRIPT/
57
+ @redis.eval(s[:lua], *args)
58
+ else
59
+ raise
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ class Shavaluator
2
+ VERSION = '0.1'
3
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ $:.unshift File.expand_path("../lib", __FILE__)
3
+ require 'shavaluator/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'shavaluator'
7
+ s.licenses = ['MIT']
8
+ s.summary = "Provides a convenient wrapper for sending Lua scripts to a Redis server via EVALSHA."
9
+ s.version = Shavaluator::VERSION
10
+ s.homepage = 'https://github.com/jeffomatic/shavaluator-rb'
11
+
12
+ s.authors = ["Jeff Lee"]
13
+ s.email = 'jeffomatic@gmail.com'
14
+
15
+ s.files = %w( README.md LICENSE shavaluator.gemspec )
16
+ s.files += Dir.glob('lib/**/*')
17
+
18
+ s.add_development_dependency('rspec', '~>3.1.0')
19
+ s.add_development_dependency('redis', '~>3.2.0')
20
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shavaluator
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Lee
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.2.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.2.0
41
+ description:
42
+ email: jeffomatic@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - lib/shavaluator.rb
50
+ - lib/shavaluator/version.rb
51
+ - shavaluator.gemspec
52
+ homepage: https://github.com/jeffomatic/shavaluator-rb
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.4.2
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Provides a convenient wrapper for sending Lua scripts to a Redis server via
76
+ EVALSHA.
77
+ test_files: []