stal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (10) hide show
  1. checksums.yaml +7 -0
  2. data/.gems +2 -0
  3. data/LICENSE +19 -0
  4. data/README.md +99 -0
  5. data/lib/stal.rb +69 -0
  6. data/makefile +4 -0
  7. data/stal.gemspec +15 -0
  8. data/test/all.rb +37 -0
  9. data/test/helper.rb +1 -0
  10. metadata +80 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 01f32692fdb539b8eebbc7d2964ba275aecef27b
4
+ data.tar.gz: a971d29478038e640c0e94fd2636e0a57edd807f
5
+ SHA512:
6
+ metadata.gz: dc8a947141e7a9d84d8c78ba58097d5cdb002b2493fdbd5a9752cb98306cd661c4f49e6c2b353c4371bb28ff45f30368b255f200d56a467bfe265c69fe620bfd
7
+ data.tar.gz: 47e6bb79573cde80bce0ed2554ef135de38f52c45ce5303761886d41f2b14b4bb4994632d45007d342685f21c530241d111dc8abe7a2984ef2beebc4361b082d
data/.gems ADDED
@@ -0,0 +1,2 @@
1
+ redic -v 1.3.0
2
+ cutest -v 1.2.2
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015 Michel Martens
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,99 @@
1
+ Stal
2
+ ====
3
+
4
+ Set algebra solver for Redis.
5
+
6
+ Description
7
+ -----------
8
+
9
+ `Stal` receives an array with an s-expression composed of commands
10
+ and key names and resolves the set operations in [Redis][redis].
11
+
12
+ Community
13
+ ---------
14
+
15
+ Meet us on IRC: [#lesscode](irc://chat.freenode.net/#lesscode) on
16
+ [freenode.net](http://freenode.net/).
17
+
18
+ Getting started
19
+ ---------------
20
+
21
+ Install [Redis][redis]. On most platforms it's as easy as grabbing
22
+ the sources, running make and then putting the `redis-server` binary
23
+ in the PATH.
24
+
25
+ Once you have it installed, you can execute `redis-server` and it
26
+ will run on `localhost:6379` by default. Check the `redis.conf`
27
+ file that comes with the sources if you want to change some settings.
28
+
29
+ Usage
30
+ -----
31
+
32
+ `Stal` requires a [Redic][redic] compatible client. To make things
33
+ easier, `redic` is listed as a runtime dependency so the examples
34
+ in this document will work.
35
+
36
+ ```ruby
37
+ require "stal"
38
+
39
+ # Connect the client to the default host
40
+ redis = Redic.new
41
+
42
+ # Use the Redis client to populate some sets
43
+ redis.call("SADD", "foo", "a", "b", "c")
44
+ redis.call("SADD", "bar", "b", "c", "d")
45
+ redis.call("SADD", "baz", "c", "d", "e")
46
+ redis.call("SADD", "qux", "x", "y", "z")
47
+ ```
48
+
49
+ Now we can perform some set operations with `Stal`:
50
+
51
+ ```ruby
52
+ expr = [:union, "qux", [:diff, [:inter, "foo", "bar"], "baz"]]
53
+
54
+ Stal.solve(redis, expr)
55
+ #=> ["b", "x", "y", "z"]
56
+ ```
57
+
58
+ `Stal` translates the shortcuts `:union`, `:diff` and `:inter` into
59
+ `SDIFFSTORE`, `SINTERSTORE` and `SUNIONSTORE` to perform the
60
+ underlying operations. You can also use the explicit command
61
+ (lowercase works too).
62
+
63
+ ```ruby
64
+ expr = [:SUNIONSTORE, "qux", [:SDIFFSTORE, [:SINTERSTORE, "foo", "bar"], "baz"]]
65
+
66
+ Stal.solve(redis, expr)
67
+ #=> ["b", "x", "y", "z"]
68
+ ```
69
+
70
+ If you want to preview the commands `Stal` will send to generate
71
+ the results, you can use `Stal.compile`:
72
+
73
+ ```ruby
74
+ Stal.compile([:inter, [:union, "foo", "bar"], "baz"])
75
+ # [[:SUNIONSTORE, "stal:55f631dc-...", "foo", "bar"],
76
+ # [:SINTERSTORE,
77
+ # "stal:fe5aaec9-...",
78
+ # "stal:55f631dc-...",
79
+ # "baz"],
80
+ # [:SMEMBERS, "stal:fe5aaec9-..."],
81
+ # [:DEL,
82
+ # "stal:fe5aaec9-...",
83
+ # "stal:55f631dc-..."]]
84
+ ```
85
+
86
+ All commands are pipelined and wrapped in a `MULTI/EXEC` transaction.
87
+ The temporary keys, which have been shortened in the example, are
88
+ deleted immediately.
89
+
90
+
91
+ Installation
92
+ ------------
93
+
94
+ ```
95
+ $ gem install stal
96
+ ```
97
+
98
+ [redis]: http://redis.io
99
+ [redic]: https://github.com/amakawa/redic
data/lib/stal.rb ADDED
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+
3
+ require "redic"
4
+ require "securerandom"
5
+
6
+ module Stal
7
+ ALIASES = {
8
+ :diff => "SDIFFSTORE",
9
+ :inter => "SINTERSTORE",
10
+ :union => "SUNIONSTORE",
11
+ }
12
+
13
+ def self.tr(term)
14
+ ALIASES.fetch(term, term)
15
+ end
16
+
17
+ def self.compute(expr, ids, acc)
18
+ id = sprintf("stal:%s", SecureRandom.uuid)
19
+
20
+ # Keys we need to clean up later
21
+ ids.push(id)
22
+
23
+ # Add command with destination key
24
+ cmd = [tr(expr[0]), id]
25
+
26
+ expr[1..-1].each do |item|
27
+ if Array === item
28
+ cmd.push(compute(item, ids, acc))
29
+ else
30
+ cmd.push(item)
31
+ end
32
+ end
33
+
34
+ acc.push(cmd)
35
+
36
+ return id
37
+ end
38
+
39
+ def self.compile(expr)
40
+
41
+ # Commands to process
42
+ acc = []
43
+
44
+ # Keys to cleanup
45
+ ids = []
46
+
47
+ id = compute(expr, ids, acc)
48
+
49
+ acc.push([:SMEMBERS, id])
50
+ acc.push([:DEL, *ids])
51
+ acc
52
+ end
53
+
54
+ # Evaluate expression `expr` in the Redis client `c`.
55
+ def self.solve(c, expr)
56
+ operations = compile(expr)
57
+
58
+ c.queue("MULTI")
59
+
60
+ operations.each do |op|
61
+ c.queue(*op)
62
+ end
63
+
64
+ c.queue("EXEC")
65
+
66
+ # Return the result of SMEMBERS
67
+ c.commit[-1][-2]
68
+ end
69
+ end
data/makefile ADDED
@@ -0,0 +1,4 @@
1
+ .PHONY: test
2
+
3
+ test:
4
+ cutest -r ./test/helper.rb ./test/*.rb
data/stal.gemspec ADDED
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "stal"
3
+ s.version = "0.0.1"
4
+ s.summary = %{Set algebra solver for Redis}
5
+ s.description = %Q{Stal receives s-expressions and resolves the set operations in Redis}
6
+ s.authors = ["Michel Martens"]
7
+ s.email = ["michel@soveran.com"]
8
+ s.homepage = "https://github.com/soveran/stal"
9
+ s.license = "MIT"
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+
13
+ s.add_dependency "redic"
14
+ s.add_development_dependency "cutest"
15
+ end
data/test/all.rb ADDED
@@ -0,0 +1,37 @@
1
+ require_relative "helper"
2
+
3
+ setup do
4
+ Redic.new.tap do |c|
5
+ c.call("FLUSHDB")
6
+ c.call("SADD", "foo", "a", "b", "c")
7
+ c.call("SADD", "bar", "b", "c", "d")
8
+ c.call("SADD", "baz", "c", "d", "e")
9
+ c.call("SADD", "qux", "x", "y", "z")
10
+ end
11
+ end
12
+
13
+ test do |c|
14
+
15
+ # Shortcut syntax
16
+ expr = [:union, "qux", [:diff, [:inter, "foo", "bar"], "baz"]]
17
+
18
+ # Explicit syntax
19
+ expr = [:SUNIONSTORE, "qux", [:SDIFFSTORE, [:SINTERSTORE, "foo", "bar"], "baz"]]
20
+
21
+ assert_equal ["b", "x", "y", "z"], Stal.solve(c, expr).sort
22
+
23
+ # Explicit syntax with strings
24
+ expr = ["SUNIONSTORE", "qux", ["SDIFFSTORE", ["SINTERSTORE", "foo", "bar"], "baz"]]
25
+
26
+ assert_equal ["b", "x", "y", "z"], Stal.solve(c, expr).sort
27
+
28
+ # Explicit syntax with lowercase strings
29
+ expr = ["sunionstore", "qux", ["sdiffstore", ["sinterstore", "foo", "bar"], "baz"]]
30
+
31
+ assert_equal ["b", "x", "y", "z"], Stal.solve(c, expr).sort
32
+
33
+ assert_equal ["b", "x", "y", "z"], Stal.solve(c, expr).sort
34
+
35
+ # Verify there's no pollution
36
+ assert_equal ["bar", "baz", "foo", "qux"], c.call("KEYS", "*").sort
37
+ end
data/test/helper.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative "../lib/stal"
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michel Martens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redic
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cutest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Stal receives s-expressions and resolves the set operations in Redis
42
+ email:
43
+ - michel@soveran.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gems
49
+ - LICENSE
50
+ - README.md
51
+ - lib/stal.rb
52
+ - makefile
53
+ - stal.gemspec
54
+ - test/all.rb
55
+ - test/helper.rb
56
+ homepage: https://github.com/soveran/stal
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.0.14
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Set algebra solver for Redis
80
+ test_files: []