swagger 1.4.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +62 -0
- data/README.rdoc +9 -7
- data/Rakefile +7 -43
- data/lib/resque_extension.rb +3 -3
- data/lib/resque_value.rb +0 -1
- data/lib/swagger.rb +5 -2
- data/lib/swagger/commands/helpers.rb +16 -0
- data/lib/swagger/commands/keys.rb +21 -0
- data/lib/swagger/commands/lists.rb +53 -0
- data/lib/swagger/commands/sets.rb +25 -0
- data/lib/swagger/commands/sorted_sets.rb +56 -0
- data/lib/swagger/commands/strings.rb +60 -0
- data/lib/swagger/redis.rb +26 -0
- data/lib/swagger/swallow.rb +14 -0
- data/lib/swagger/version.rb +7 -0
- data/spec/resque_extension_spec.rb +6 -7
- data/spec/spec_helper.rb +17 -14
- data/spec/support/helpers.rb +7 -0
- data/spec/swagger/commands/sorted_sets_spec.rb +175 -0
- data/spec/swagger/commands/strings_spec.rb +58 -0
- data/spec/swagger/redis_spec.rb +171 -0
- data/swagger.gemspec +12 -52
- metadata +74 -35
- data/VERSION +0 -1
- data/lib/redis_impersonator.rb +0 -129
- data/spec/redis_impersonator_spec.rb +0 -171
- data/spec/spec.opts +0 -1
data/.gitignore
CHANGED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
swagger (1.4.1)
|
5
|
+
activerecord
|
6
|
+
resque (>= 1.10.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (3.0.3)
|
12
|
+
activesupport (= 3.0.3)
|
13
|
+
builder (~> 2.1.2)
|
14
|
+
i18n (~> 0.4)
|
15
|
+
activerecord (3.0.3)
|
16
|
+
activemodel (= 3.0.3)
|
17
|
+
activesupport (= 3.0.3)
|
18
|
+
arel (~> 2.0.2)
|
19
|
+
tzinfo (~> 0.3.23)
|
20
|
+
activesupport (3.0.3)
|
21
|
+
arel (2.0.7)
|
22
|
+
builder (2.1.2)
|
23
|
+
diff-lcs (1.1.2)
|
24
|
+
i18n (0.5.0)
|
25
|
+
json (1.4.6)
|
26
|
+
rack (1.2.1)
|
27
|
+
rake (0.8.7)
|
28
|
+
redis (2.1.1)
|
29
|
+
redis-namespace (0.8.0)
|
30
|
+
redis (< 3.0.0)
|
31
|
+
resque (1.10.0)
|
32
|
+
json (~> 1.4.6)
|
33
|
+
redis-namespace (~> 0.8.0)
|
34
|
+
sinatra (>= 0.9.2)
|
35
|
+
vegas (~> 0.1.2)
|
36
|
+
rspec (2.4.0)
|
37
|
+
rspec-core (~> 2.4.0)
|
38
|
+
rspec-expectations (~> 2.4.0)
|
39
|
+
rspec-mocks (~> 2.4.0)
|
40
|
+
rspec-core (2.4.0)
|
41
|
+
rspec-expectations (2.4.0)
|
42
|
+
diff-lcs (~> 1.1.2)
|
43
|
+
rspec-mocks (2.4.0)
|
44
|
+
sinatra (1.1.2)
|
45
|
+
rack (~> 1.1)
|
46
|
+
tilt (~> 1.2)
|
47
|
+
sqlite3 (1.3.3)
|
48
|
+
tilt (1.2.2)
|
49
|
+
tzinfo (0.3.24)
|
50
|
+
vegas (0.1.8)
|
51
|
+
rack (>= 1.0.0)
|
52
|
+
|
53
|
+
PLATFORMS
|
54
|
+
ruby
|
55
|
+
|
56
|
+
DEPENDENCIES
|
57
|
+
activerecord
|
58
|
+
rake (~> 0.8.7)
|
59
|
+
resque (>= 1.10.0)
|
60
|
+
rspec (>= 2.4.0)
|
61
|
+
sqlite3 (>= 1.3.3)
|
62
|
+
swagger!
|
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Swagger = Resque + ActiveRecord - Redis
|
2
|
-
|
2
|
+
|
3
3
|
Swagger marries the power and robustness of Resque with the trivial setup of delayed_job. Swagger allows you to use all the features of Resque (http://github.com/defunkt/resque) without any of the "Redis" by adding one table to your existing database.
|
4
|
-
|
4
|
+
|
5
5
|
== Getting Started
|
6
6
|
|
7
7
|
=== 1. Add resque and swagger to your gem dependencies (order is important)
|
@@ -19,20 +19,22 @@ Swagger marries the power and robustness of Resque with the trivial setup of del
|
|
19
19
|
Resque.connect_to_database(database)
|
20
20
|
|
21
21
|
==== NOTE: This allows rails and the resque admin app to use the same initializer by executing at the console: resque-web config/initializers/resque.rb
|
22
|
-
|
22
|
+
|
23
23
|
=== 3. Create an active record migration
|
24
|
-
|
24
|
+
|
25
25
|
create_table :resque_values do |table|
|
26
26
|
table.column :key, :string
|
27
27
|
table.column :key_type, :string
|
28
|
-
table.column :
|
28
|
+
table.column :score, :integer
|
29
|
+
table.column :value, :text
|
30
|
+
table.timestamps
|
29
31
|
end
|
30
|
-
|
32
|
+
|
31
33
|
add_index :resque_values, :key
|
32
34
|
add_index :resque_values, [:key, :key_type]
|
33
35
|
|
34
36
|
== Note on Patches/Pull Requests
|
35
|
-
|
37
|
+
|
36
38
|
* Fork the project.
|
37
39
|
* Make your feature addition or bug fix.
|
38
40
|
* Add tests for it. This is important so I don't break it in a
|
data/Rakefile
CHANGED
@@ -1,46 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "swagger"
|
8
|
-
gem.summary = %Q{Everything Resque provides minus Redis}
|
9
|
-
gem.description = %Q{Duck punch Resque to use active record for backround jobs instead of redis}
|
10
|
-
gem.email = "mdeiters@gmail.com"
|
11
|
-
gem.homepage = "http://github.com/mdeiters/swagger"
|
12
|
-
gem.authors = ["mdeiters"]
|
13
|
-
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
-
gem.add_dependency "activerecord" #, "2.3.8"
|
15
|
-
gem.add_dependency "resque", ">= 1.10.0"
|
16
|
-
end
|
17
|
-
Jeweler::GemcutterTasks.new
|
18
|
-
rescue LoadError
|
19
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
-
end
|
21
|
-
|
22
|
-
require 'spec/rake/spectask'
|
23
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
-
spec.libs << 'lib' << 'spec'
|
25
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
-
end
|
1
|
+
require 'bundler'
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler::GemHelper.install_tasks
|
27
4
|
|
28
|
-
|
29
|
-
|
30
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
-
spec.rcov = true
|
32
|
-
end
|
33
|
-
|
34
|
-
task :spec => :check_dependencies
|
35
|
-
|
36
|
-
task :default => :spec
|
5
|
+
require 'rake'
|
6
|
+
require 'rspec/core/rake_task'
|
37
7
|
|
38
|
-
|
39
|
-
Rake::RDocTask.new do |rdoc|
|
40
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
8
|
+
RSpec::Core::RakeTask.new
|
41
9
|
|
42
|
-
|
43
|
-
rdoc.title = "swagger #{version}"
|
44
|
-
rdoc.rdoc_files.include('README*')
|
45
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
-
end
|
10
|
+
task :default => :spec
|
data/lib/resque_extension.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
Resque.module_eval do
|
2
2
|
def swagger!
|
3
3
|
define_method(:redis=) do |*args|
|
4
|
-
@redis =
|
4
|
+
@redis = Swagger::Redis.new
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
define_method(:connect_to_database) do |database|
|
8
8
|
ResqueValue.establish_connection database
|
9
9
|
end
|
10
|
-
end
|
10
|
+
end
|
11
11
|
end
|
data/lib/resque_value.rb
CHANGED
data/lib/swagger.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Swagger
|
2
|
+
module Commands
|
3
|
+
module Keys
|
4
|
+
|
5
|
+
def del(key)
|
6
|
+
ResqueValue.delete_all(:key => key.to_s)
|
7
|
+
nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def exists(key)
|
11
|
+
ResqueValue.exists?(:key => key.to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
def keys(pattern = '*')
|
15
|
+
raise "Pattern '#{pattern}' not supported" if pattern != '*'
|
16
|
+
ResqueValue.all(:select => 'DISTINCT resque_values.key').map(&:key)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Swagger
|
2
|
+
module Commands
|
3
|
+
module Lists
|
4
|
+
KEY_TYPE = 'list'
|
5
|
+
|
6
|
+
def llen(list_name)
|
7
|
+
ResqueValue.all(:conditions => {:key => list_name.to_s, :key_type=> KEY_TYPE }).size
|
8
|
+
end
|
9
|
+
|
10
|
+
def lset(list_name, index, value)
|
11
|
+
rpush(list_name, value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def lrange(list_name, start_range, end_range)
|
15
|
+
options = { :conditions => {
|
16
|
+
:key => list_name.to_s,
|
17
|
+
:key_type=> KEY_TYPE}}
|
18
|
+
unless end_range < 0
|
19
|
+
limit = end_range - start_range + 1
|
20
|
+
options.merge!(:limit => limit, :offset => start_range)
|
21
|
+
end
|
22
|
+
values = ResqueValue.all(options)
|
23
|
+
values.map(&:value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def lrem(list_name, count, value)
|
27
|
+
raise "Only supports count of 0 which means to remove all elements in list" if count != 0
|
28
|
+
ResqueValue.delete_all(:key => list_name.to_s, :key_type=> KEY_TYPE, :value => value )
|
29
|
+
end
|
30
|
+
|
31
|
+
def lpop(list_name)
|
32
|
+
ResqueValue.transaction do
|
33
|
+
last = ResqueValue.last(:conditions => {:key => list_name.to_s, :key_type => KEY_TYPE}, :lock => true)
|
34
|
+
if last
|
35
|
+
last.destroy
|
36
|
+
return last.value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def rpush(list_name, value)
|
42
|
+
ResqueValue.create!(:key => list_name.to_s, :key_type => KEY_TYPE, :value => value.to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
def ltrim(list_name, start_range, end_range)
|
46
|
+
limit = end_range - start_range + 1
|
47
|
+
ids = ResqueValue.all(:select => "id", :conditions => {:key => list_name}, :offset => start_range, :limit => limit)
|
48
|
+
ResqueValue.delete_all(["`key` = ? AND id NOT IN (?)", list_name, ids.collect{|i| i.id}])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Swagger
|
2
|
+
module Commands
|
3
|
+
module Sets
|
4
|
+
KEY_TYPE = 'set'
|
5
|
+
|
6
|
+
def sadd(set_name, value)
|
7
|
+
sismember(set_name, value) || ResqueValue.create!(:key => set_name.to_s, :key_type => KEY_TYPE, :value => value.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def srem(set_name, value)
|
11
|
+
ResqueValue.delete_all(:key => set_name.to_s, :key_type => KEY_TYPE, :value => value.to_s)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def smembers(set_name)
|
16
|
+
ResqueValue.all(:conditions => {:key => set_name.to_s, :key_type => KEY_TYPE}).map(&:value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def sismember(set_name, value)
|
20
|
+
ResqueValue.exists?(:key => set_name.to_s, :key_type => KEY_TYPE, :value => value.to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Swagger
|
2
|
+
module Commands
|
3
|
+
module SortedSets
|
4
|
+
|
5
|
+
KEY_TYPE = 'sorted_set'
|
6
|
+
|
7
|
+
def zadd(key, score, value)
|
8
|
+
record = ResqueValue.find_or_initialize_by_key_and_key_type_and_value(
|
9
|
+
key.to_s, KEY_TYPE, value)
|
10
|
+
record.score = score
|
11
|
+
record.save!
|
12
|
+
record
|
13
|
+
end
|
14
|
+
|
15
|
+
def zrem(key, value)
|
16
|
+
ResqueValue.delete_all conditions(key).merge(:value => value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def zcard(key)
|
20
|
+
ResqueValue.count :conditions => conditions(key)
|
21
|
+
end
|
22
|
+
|
23
|
+
def zrange(key, start, stop)
|
24
|
+
Helpers.select_values(
|
25
|
+
'SELECT value FROM resque_values ' \
|
26
|
+
"WHERE key = #{key} " \
|
27
|
+
'ORDER BY score'
|
28
|
+
)[start..stop]
|
29
|
+
end
|
30
|
+
|
31
|
+
def zrangebyscore(key, min, max, options = {})
|
32
|
+
min = ResqueValue.minimum(:score, :conditions => conditions(key)) || 0 if min == '-inf'
|
33
|
+
max = ResqueValue.maximum(:score, :conditions => conditions(key)) || 0 if max == '+inf'
|
34
|
+
|
35
|
+
Helpers.select_values(
|
36
|
+
[].tap do |sql|
|
37
|
+
sql << 'SELECT value FROM resque_values'
|
38
|
+
sql << "WHERE `key` = '#{key}'"
|
39
|
+
sql << "AND score BETWEEN #{min} AND #{max}"
|
40
|
+
sql << 'ORDER BY score'
|
41
|
+
if limit = options[:limit]
|
42
|
+
sql << "LIMIT #{limit.join(', ')}"
|
43
|
+
end
|
44
|
+
end.join(' ')
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def conditions(key)
|
51
|
+
{ :key => key.to_s, :key_type => KEY_TYPE }
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Swagger
|
2
|
+
module Commands
|
3
|
+
module Strings
|
4
|
+
|
5
|
+
def get(key)
|
6
|
+
resque_value = ResqueValue.first(:conditions => {:key => key})
|
7
|
+
resque_value.value if resque_value
|
8
|
+
end
|
9
|
+
|
10
|
+
def set(key, value)
|
11
|
+
resque_value = ResqueValue.find_or_initialize_by_key(key.to_s)
|
12
|
+
resque_value.value = value
|
13
|
+
resque_value.save!
|
14
|
+
value
|
15
|
+
end
|
16
|
+
|
17
|
+
def setnx(key, value)
|
18
|
+
resque_value = ResqueValue.find_or_initialize_by_key(key.to_s)
|
19
|
+
if resque_value.new_record?
|
20
|
+
resque_value.value = value
|
21
|
+
resque_value.save!
|
22
|
+
end
|
23
|
+
resque_value.value
|
24
|
+
end
|
25
|
+
|
26
|
+
def incr(key)
|
27
|
+
incrby(key, '1')
|
28
|
+
end
|
29
|
+
|
30
|
+
def decr(key)
|
31
|
+
decrby(key, '1')
|
32
|
+
end
|
33
|
+
|
34
|
+
def incrby(key, value)
|
35
|
+
object = ResqueValue.find_or_initialize_by_key(key.to_s)
|
36
|
+
object.value = (object.value.to_i + value.to_i).to_s
|
37
|
+
object.save!
|
38
|
+
object.value
|
39
|
+
end
|
40
|
+
|
41
|
+
def decrby(key, value)
|
42
|
+
object = ResqueValue.find_or_initialize_by_key(key.to_s)
|
43
|
+
object.value = (object.value.to_i - value.to_i).to_s
|
44
|
+
object.save!
|
45
|
+
object.value
|
46
|
+
end
|
47
|
+
|
48
|
+
def mapped_mget(*keys)
|
49
|
+
Hash[*keys.zip(mget(*keys)).flatten]
|
50
|
+
end
|
51
|
+
|
52
|
+
def mget(*keys)
|
53
|
+
keys.collect!{|key| key.to_s }
|
54
|
+
resque_values = ResqueValue.all(:conditions => {:key => keys})
|
55
|
+
resque_values.map(&:value)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'swagger/swallow'
|
2
|
+
require 'swagger/commands/helpers'
|
3
|
+
require 'swagger/commands/keys'
|
4
|
+
require 'swagger/commands/lists'
|
5
|
+
require 'swagger/commands/sets'
|
6
|
+
require 'swagger/commands/sorted_sets'
|
7
|
+
require 'swagger/commands/strings'
|
8
|
+
|
9
|
+
module Swagger
|
10
|
+
class Redis
|
11
|
+
|
12
|
+
extend Swallow
|
13
|
+
|
14
|
+
swallow :namespace=
|
15
|
+
swallow :namespace, 'not applicable'
|
16
|
+
swallow :server, 'ActiveRecord'
|
17
|
+
swallow :info, self.inspect
|
18
|
+
|
19
|
+
include Commands::Keys
|
20
|
+
include Commands::Lists
|
21
|
+
include Commands::Sets
|
22
|
+
include Commands::SortedSets
|
23
|
+
include Commands::Strings
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|