sweatpants 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +6 -0
- data/lib/sweatpants.rb +23 -0
- data/lib/sweatpants/client.rb +45 -0
- data/lib/sweatpants/configuration.rb +29 -0
- data/lib/sweatpants/queue.rb +60 -0
- data/lib/sweatpants/queued_request.rb +23 -0
- data/lib/sweatpants/timer.rb +28 -0
- data/spec/client_spec.rb +81 -0
- data/spec/configuration_spec.rb +52 -0
- data/spec/queue_spec.rb +54 -0
- data/spec/request_spec.rb +24 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/sweatpants_spec.rb +9 -0
- data/spec/timer_spec.rb +59 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f74b60bb640fe707d0cae47be97c6b5dd611b3bb
|
4
|
+
data.tar.gz: 982cbf2bf2c4ab79fe6337885eed4a913f53ebb6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 96454502b61b4807f32e9cb0b2b7d8acefb0a434d536418df30f5721376addb889c1cbb49fd4c93fe439e21349655c7d84c705a8c161938982a50e44582855df
|
7
|
+
data.tar.gz: a95a70d1305b3eb079c4c84336b0269b863888c118c60ab3f702b37a73f1ffa662ac99177efd091748110ce7da3c9fccf4b525d62bf4ed5500c4e8aec3dfff49
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 bentona
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Sweatpants
|
2
|
+
[![Build Status](https://secure.travis-ci.org/bentona/sweatpants.png?branch=master)](http://travis-ci.org/bentona/sweatpants) [![Code Climate](https://codeclimate.com/github/bentona/sweatpants.png)](https://codeclimate.com/github/bentona/sweatpants) [![Coverage Status](https://coveralls.io/repos/bentona/sweatpants/badge.png)](https://coveralls.io/r/bentona/sweatpants)
|
3
|
+
|
4
|
+
Redis-backed elasticsearch-ruby wrapper that aggregates requests & dispatches them as bulk requests.
|
5
|
+
|
6
|
+
Inspired, in part, by https://github.com/nz/elasticmill
|
7
|
+
|
8
|
+
|
9
|
+
Create a sweatpants client.
|
10
|
+
```
|
11
|
+
elasticsearch_options = {
|
12
|
+
host: 'localhost'
|
13
|
+
}
|
14
|
+
|
15
|
+
sweatpants_options = {
|
16
|
+
queue: SweatpantsQueue.new,
|
17
|
+
flush_frequency: 1,
|
18
|
+
actions_to_trap: [:index]
|
19
|
+
}
|
20
|
+
|
21
|
+
sweatpants = Sweatpants.new elasticsearch_options, sweatpants_options
|
22
|
+
```
|
23
|
+
|
24
|
+
Send sweatpants a request that will be queued.
|
25
|
+
```
|
26
|
+
sweatpants.index({
|
27
|
+
index: "matches",
|
28
|
+
type: "ExpertMatch",
|
29
|
+
id: "1234",
|
30
|
+
body: {some: 'stuff'}
|
31
|
+
})
|
32
|
+
```
|
33
|
+
|
34
|
+
Send sweatpants a request that will be immediately executed.
|
35
|
+
```
|
36
|
+
sweatpants.index(
|
37
|
+
{
|
38
|
+
index: "matches",
|
39
|
+
type: "ExpertMatch",
|
40
|
+
id: "5678",
|
41
|
+
body: {some: "really important stuff"}
|
42
|
+
},
|
43
|
+
{
|
44
|
+
immediate: true
|
45
|
+
}
|
46
|
+
)
|
47
|
+
```
|
data/Rakefile
ADDED
data/lib/sweatpants.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "sweatpants/client"
|
2
|
+
require "sweatpants/queue"
|
3
|
+
require "sweatpants/timer"
|
4
|
+
require "sweatpants/queued_request"
|
5
|
+
require "sweatpants/configuration"
|
6
|
+
|
7
|
+
module Sweatpants
|
8
|
+
class << self
|
9
|
+
attr_writer :configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configuration
|
13
|
+
@configuration ||= Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure
|
17
|
+
yield(configuration)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.reset
|
21
|
+
@configuration = Configuration.new
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'elasticsearch'
|
2
|
+
|
3
|
+
module Sweatpants
|
4
|
+
class Client
|
5
|
+
|
6
|
+
attr_reader :queue, :client, :actions_to_trap, :flush_frequency
|
7
|
+
|
8
|
+
def initialize es_params=nil
|
9
|
+
@client = es_params.nil? ? Sweatpants.configuration.client : Elasticsearch::Client.new(es_params)
|
10
|
+
@queue = Sweatpants.configuration.queue
|
11
|
+
@flush_frequency = Sweatpants.configuration.flush_frequency
|
12
|
+
@actions_to_trap = Sweatpants.configuration.actions_to_trap
|
13
|
+
@timer = Sweatpants::Timer.new(@flush_frequency)
|
14
|
+
@timer.on_tick { flush }
|
15
|
+
end
|
16
|
+
|
17
|
+
def flush
|
18
|
+
begin
|
19
|
+
@client.bulk @queue.dequeue
|
20
|
+
rescue Exception => e
|
21
|
+
$stderr.puts e # use a Logger, maybe @client's?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method_name, *args, &block)
|
26
|
+
if trap_request?(method_name, *args)
|
27
|
+
delay(method_name, *args)
|
28
|
+
else
|
29
|
+
@client.send(method_name, args[0])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def delay method_name, *args
|
36
|
+
request = Sweatpants::QueuedRequest.new method_name, args.first
|
37
|
+
@queue.enqueue request.to_bulk
|
38
|
+
end
|
39
|
+
|
40
|
+
def trap_request? action, *args
|
41
|
+
sweatpants_arguments = args[1] || {}
|
42
|
+
!sweatpants_arguments[:immediate] && @actions_to_trap.include?(action)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# mostly taken from http://brandonhilkert.com/blog/ruby-gem-configuration-patterns
|
2
|
+
module Sweatpants
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :flush_frequency, :queue, :actions_to_trap, :client
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@flush_frequency = 1
|
8
|
+
@queue_type = :redis
|
9
|
+
@actions_to_trap = [:index]
|
10
|
+
@client = Elasticsearch::Client.new
|
11
|
+
@redis_config = {
|
12
|
+
host: 'localhost',
|
13
|
+
port: 6379,
|
14
|
+
list: 'sweatpants_queue',
|
15
|
+
database: 3
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def queue
|
20
|
+
case @queue_type
|
21
|
+
when :redis
|
22
|
+
Sweatpants::RedisQueue.new(@redis_config)
|
23
|
+
else
|
24
|
+
Sweatpants::SimpleQueue.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module Sweatpants
|
4
|
+
class SimpleQueue < Array
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def enqueue request
|
10
|
+
true if self << request
|
11
|
+
end
|
12
|
+
|
13
|
+
def dequeue count=nil
|
14
|
+
count.nil? ? pop(self.size) : pop(count)
|
15
|
+
end
|
16
|
+
|
17
|
+
def peek
|
18
|
+
self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Sweatpants
|
24
|
+
class RedisQueue
|
25
|
+
attr_reader :redis
|
26
|
+
|
27
|
+
def initialize params = {}
|
28
|
+
@list_name = params[:list]
|
29
|
+
@redis = Redis.new(host: params[:host], port: params[:port])
|
30
|
+
@redis.select params[:database]
|
31
|
+
end
|
32
|
+
|
33
|
+
def enqueue request
|
34
|
+
@redis.rpush @list_name, request.to_json
|
35
|
+
end
|
36
|
+
|
37
|
+
def dequeue count=nil
|
38
|
+
count = @redis.llen(@list_name) unless count
|
39
|
+
multi_pop count
|
40
|
+
end
|
41
|
+
|
42
|
+
def multi_pop count
|
43
|
+
items = @redis.multi {
|
44
|
+
peek count
|
45
|
+
@redis.ltrim(@list_name, count, -1)
|
46
|
+
}[0]
|
47
|
+
items
|
48
|
+
end
|
49
|
+
|
50
|
+
def flushall
|
51
|
+
@redis.flushall
|
52
|
+
end
|
53
|
+
|
54
|
+
def peek count = nil
|
55
|
+
count = @redis.llen(@list_name) unless count
|
56
|
+
@redis.lrange(@list_name, 0, count - 1)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Sweatpants
|
3
|
+
class QueuedRequest
|
4
|
+
|
5
|
+
def initialize method, params
|
6
|
+
@method = method
|
7
|
+
@type = params[:type] || nil
|
8
|
+
@index = params[:index] || nil
|
9
|
+
@id = params[:id] || nil
|
10
|
+
@body = params[:body] || nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_bulk
|
14
|
+
[bulk_header, @body].map(&:to_json).join("\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def bulk_header
|
18
|
+
header = { @method.to_sym => { _index: @index, _type: @type } }
|
19
|
+
header[:id] = @id if @id
|
20
|
+
header
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sweatpants
|
2
|
+
class Timer
|
3
|
+
attr_reader :blocks
|
4
|
+
def initialize frequency
|
5
|
+
@blocks = []
|
6
|
+
@frequency = frequency
|
7
|
+
spawn_tick_thread
|
8
|
+
end
|
9
|
+
|
10
|
+
def spawn_tick_thread
|
11
|
+
Thread.new do
|
12
|
+
while true do
|
13
|
+
sleep @frequency
|
14
|
+
call_blocks
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def call_blocks
|
20
|
+
@blocks.each &:call
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_tick &block
|
24
|
+
raise 'Timer#register requires a block' unless block
|
25
|
+
@blocks << block
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'redis'
|
3
|
+
|
4
|
+
module Sweatpants
|
5
|
+
describe Client do
|
6
|
+
let(:request_1){ {index: "matches", type: 'MyIndex', body: {stuff: 'some stuff'} } }
|
7
|
+
|
8
|
+
describe '#new' do
|
9
|
+
it "instantiates with a client and queue" do
|
10
|
+
sweatpants = Sweatpants::Client.new
|
11
|
+
sweatpants.instance_variable_get(:@client).should_not be_nil
|
12
|
+
sweatpants.instance_variable_get(:@queue).should be_a Sweatpants::RedisQueue
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#configure' do
|
17
|
+
before do
|
18
|
+
Sweatpants.configure do |config|
|
19
|
+
config.flush_frequency = 5
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has a flush frequency of 5 seconds" do
|
24
|
+
client = Sweatpants::Client.new
|
25
|
+
expect(client.flush_frequency).to eq(5)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#flush' do
|
30
|
+
before :each do
|
31
|
+
Sweatpants.reset
|
32
|
+
@es_client = double('es_client')
|
33
|
+
allow(@es_client).to receive(:bulk)
|
34
|
+
Sweatpants.configure do |config|
|
35
|
+
config.client = @es_client
|
36
|
+
config.flush_frequency = 10000
|
37
|
+
end
|
38
|
+
@client = Sweatpants::Client.new
|
39
|
+
@jobs = [{here: 'are'}, {some: 'jobs'}]
|
40
|
+
@jobs.map{|job| @client.queue.enqueue job}
|
41
|
+
@client.flush
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sends the requests with client.bulk' do
|
45
|
+
expect(@es_client).to have_received(:bulk).with(@jobs.map(&:to_json))
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'traps requests' do
|
51
|
+
|
52
|
+
before :each do
|
53
|
+
Sweatpants.reset
|
54
|
+
fake_client = double(search: nil, index: nil)
|
55
|
+
Sweatpants.configure do |config|
|
56
|
+
config.client = fake_client
|
57
|
+
config.flush_frequency = 10000
|
58
|
+
end
|
59
|
+
@sweatpants = Sweatpants::Client.new
|
60
|
+
@sweatpants.queue.flushall
|
61
|
+
end
|
62
|
+
|
63
|
+
it "traps an index request" do
|
64
|
+
@sweatpants.index(request_1)
|
65
|
+
expect(@sweatpants.queue.peek).to have(1).item
|
66
|
+
end
|
67
|
+
|
68
|
+
it "doesn't trap a search request" do
|
69
|
+
@sweatpants.search(request_1)
|
70
|
+
expect(@sweatpants.client).to have_received(:search).with(request_1)
|
71
|
+
expect(@sweatpants.queue.peek).to have(0).items
|
72
|
+
end
|
73
|
+
|
74
|
+
it "doesn't trap a request marked as immediate" do
|
75
|
+
@sweatpants.index(request_1, {immediate: true})
|
76
|
+
expect(@sweatpants.queue.peek).to have(0).items
|
77
|
+
expect(@sweatpants.client).to have_received(:index).with(request_1)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# spec/mega_lotto/configuration_spec.rb
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
# client, queue, flush_frequency, actions_to_trap, timer
|
6
|
+
|
7
|
+
module Sweatpants
|
8
|
+
describe Configuration do
|
9
|
+
describe "#flush_frequency" do
|
10
|
+
it "default value is 1 second" do
|
11
|
+
Configuration.new.flush_frequency = 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#actions_to_trap" do
|
16
|
+
it "default value is [:index]" do
|
17
|
+
Configuration.new.actions_to_trap = [:index]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#flush_frequency=" do
|
22
|
+
it "can set value" do
|
23
|
+
config = Configuration.new
|
24
|
+
config.flush_frequency = 7
|
25
|
+
expect(config.flush_frequency).to eq(7)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#actions_to_trap=" do
|
30
|
+
it "can set value" do
|
31
|
+
config = Configuration.new
|
32
|
+
config.actions_to_trap = [:index, :test_action]
|
33
|
+
expect(config.actions_to_trap).to eq([:index, :test_action])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".reset" do
|
38
|
+
before :each do
|
39
|
+
Sweatpants.configure do |config|
|
40
|
+
config.flush_frequency = 5
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "resets the configuration" do
|
45
|
+
Sweatpants.reset
|
46
|
+
config = Sweatpants.configuration
|
47
|
+
expect(config.flush_frequency).to eq(1)
|
48
|
+
expect(config.actions_to_trap).to eq([:index])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/queue_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fakeredis'
|
3
|
+
|
4
|
+
describe Sweatpants::RedisQueue do
|
5
|
+
|
6
|
+
let(:request_1) { ({foo: "bar", baz: "buzz"})}
|
7
|
+
let(:request_2) { ({some: "stuff"})}
|
8
|
+
let(:request_3) { ({other: "things"})}
|
9
|
+
let(:request_4) { ({fizz: 'bang'})}
|
10
|
+
|
11
|
+
describe '#initialize' do
|
12
|
+
it "works" do
|
13
|
+
Sweatpants::RedisQueue.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#enqueue' do
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
Redis.new.flushall
|
21
|
+
@queue = Sweatpants::RedisQueue.new
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can enqueue requests (json strings)" do
|
25
|
+
@queue.enqueue(request_1)
|
26
|
+
@queue.enqueue(request_2)
|
27
|
+
expect(@queue.peek(2)).to eq([request_1.to_json, request_2.to_json])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#dequeue' do
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
Redis.new.flushall
|
35
|
+
@queue = Sweatpants::RedisQueue.new
|
36
|
+
end
|
37
|
+
|
38
|
+
it "dequeues all requests by default" do
|
39
|
+
@queue.enqueue(request_1)
|
40
|
+
@queue.enqueue(request_2)
|
41
|
+
expect(@queue.dequeue).to eq([request_1.to_json, request_2.to_json])
|
42
|
+
end
|
43
|
+
|
44
|
+
it "dequeues the specified number of requests" do
|
45
|
+
@queue.enqueue(request_1)
|
46
|
+
@queue.enqueue(request_2)
|
47
|
+
@queue.enqueue(request_3)
|
48
|
+
@queue.enqueue(request_4)
|
49
|
+
expect(@queue.dequeue(1)).to eq([request_1.to_json])
|
50
|
+
expect(@queue.dequeue(2)).to eq([request_2.to_json, request_3.to_json])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sweatpants::QueuedRequest do
|
4
|
+
|
5
|
+
let(:params_1) { { type: "MyType", index: "users", id: 123, body: {some: 'stuff'} } }
|
6
|
+
let(:request_1) { Sweatpants::QueuedRequest.new :index, params_1 }
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
it 'initializes with proper params' do
|
10
|
+
Sweatpants::QueuedRequest.new :index, params_1
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'raises when initialized without proper params' do
|
14
|
+
expect{Sweatpants::QueuedRequest.new}.to raise_error
|
15
|
+
expect{Sweatpants::QueuedRequest.new :index }.to raise_error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#to_bulk' do
|
20
|
+
it 'properly formats a bulk request' do
|
21
|
+
expect(request_1.to_bulk).to eq("{\"index\":{\"_index\":\"users\",\"_type\":\"MyType\"},\"id\":123}\n{\"some\":\"stuff\"}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/timer_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sweatpants::Timer do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@timer = Sweatpants::Timer.new 1
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#on_tick' do
|
10
|
+
|
11
|
+
context 'block given' do
|
12
|
+
|
13
|
+
before :each do
|
14
|
+
3.times{ @timer.on_tick {} }
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'stores the given blocks' do
|
18
|
+
expect(@timer).to have(3).blocks
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'block not given' do
|
23
|
+
it 'throws an exception when no block is given' do
|
24
|
+
expect{ @timer.on_tick }.to raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#call_blocks' do
|
30
|
+
|
31
|
+
context 'with blocks present' do
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
@block_1_called = false
|
35
|
+
@block_2_called = false
|
36
|
+
|
37
|
+
@timer.on_tick do
|
38
|
+
@block_1_called = true
|
39
|
+
end
|
40
|
+
|
41
|
+
@timer.on_tick do
|
42
|
+
@block_2_called = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'calls all blocks present' do
|
47
|
+
@timer.call_blocks
|
48
|
+
expect(@block_1_called).to be_true
|
49
|
+
expect(@block_2_called).to be_true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with no blocks present' do
|
54
|
+
it 'should not raise when no blocks are present' do
|
55
|
+
@timer.call_blocks
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sweatpants
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Benton Anderson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Sponsored by Originate(http://originate.com)
|
14
|
+
email: benton.anderson@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- LICENSE.txt
|
20
|
+
- README.md
|
21
|
+
- Rakefile
|
22
|
+
- lib/sweatpants.rb
|
23
|
+
- lib/sweatpants/client.rb
|
24
|
+
- lib/sweatpants/configuration.rb
|
25
|
+
- lib/sweatpants/queue.rb
|
26
|
+
- lib/sweatpants/queued_request.rb
|
27
|
+
- lib/sweatpants/timer.rb
|
28
|
+
- spec/client_spec.rb
|
29
|
+
- spec/configuration_spec.rb
|
30
|
+
- spec/queue_spec.rb
|
31
|
+
- spec/request_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- spec/sweatpants_spec.rb
|
34
|
+
- spec/timer_spec.rb
|
35
|
+
homepage: http://github.com/bentona/sweatpants
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 2.2.2
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: Wrapper for elasticsearch-ruby that bulks-up requests
|
59
|
+
test_files:
|
60
|
+
- spec/client_spec.rb
|
61
|
+
- spec/configuration_spec.rb
|
62
|
+
- spec/queue_spec.rb
|
63
|
+
- spec/request_spec.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
- spec/sweatpants_spec.rb
|
66
|
+
- spec/timer_spec.rb
|