timberline 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +3 -0
- data/README.markdown +38 -3
- data/lib/timberline/config.rb +70 -19
- data/lib/timberline/version.rb +1 -1
- data/spec/config/test_config.yaml +4 -0
- data/spec/lib/timberline/config_spec.rb +46 -0
- metadata +13 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dcba7d76edc4b00c7060cfa2c01e7df38700912
|
4
|
+
data.tar.gz: f3dad3c3080a4c35db3f91f2b8b599f008039bf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03b760d6e84c72d91884ee18f87fa797577839f16e495148c144144780adfeab120e8bb2ffb4661eec4d51d1e4dbc06e14a0faab6cef95400712a3c3a6fbb2d0
|
7
|
+
data.tar.gz: 3cbb508700948108bbabd33e1e24e0f98189ae06545047dec89479cb9e3266aeb7b9116bae2fd6c931434722b77cd5e81b91c21df54c869412174ca1f3f20d7f
|
data/CHANGELOG
CHANGED
data/README.markdown
CHANGED
@@ -83,7 +83,7 @@ queue (more on that later). There are 3 ways to configure Timberline:
|
|
83
83
|
c.port = 12345
|
84
84
|
c.password = "foobar"
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
...As long as you run this block before you attempt to access your queues,
|
88
88
|
your settings will all take effect. Redis defaults will be used if you omit
|
89
89
|
anything.
|
@@ -99,6 +99,10 @@ queue (more on that later). There are 3 ways to configure Timberline:
|
|
99
99
|
|
100
100
|
TIMBERLINE_YAML = 'path/to/your/yaml/file.yaml'
|
101
101
|
|
102
|
+
3. Running on Heroku? Define an environment variable for the URL:
|
103
|
+
|
104
|
+
export TIMBERLINE_URL="redis://:foobar@192.168.1.105:12345/1?timeout=99&namespace=my_namespace"
|
105
|
+
|
102
106
|
### Pushing jobs onto a queue
|
103
107
|
|
104
108
|
To push a job onto the queue you'll want to make use of the `Timberline#push`
|
@@ -151,7 +155,7 @@ you could write a queue processor that reads off of that queue.
|
|
151
155
|
### Using the binary
|
152
156
|
|
153
157
|
In order to make reading off of the queue easier, there's a binary named
|
154
|
-
`
|
158
|
+
`timberline` included with this gem.
|
155
159
|
|
156
160
|
Example:
|
157
161
|
|
@@ -168,13 +172,44 @@ block until either the process is killed, or until something is added to the
|
|
168
172
|
queue.
|
169
173
|
|
170
174
|
There are some options to the Timberline binary that you may find helpful -
|
171
|
-
`timberline --help` for more.
|
175
|
+
`timberline --help` for more.
|
172
176
|
|
173
177
|
### Rails
|
174
178
|
|
175
179
|
If you're using Timberline in conjunction with a Rails environment, check out
|
176
180
|
the [timberline-rails](https://github.com/treehouse/timberline-rails) gem.
|
177
181
|
|
182
|
+
### Redis Failover
|
183
|
+
|
184
|
+
The Redis client (>= v3.2) is able to [perform automatic Redis
|
185
|
+
connection](https://github.com/redis/redis-rb#sentinel-support) failovers by
|
186
|
+
using [Redis Sentinel](http://redis.io/topics/sentinel). In cases where this is
|
187
|
+
enabled, pass sentinel configuration on to the Redis client using the
|
188
|
+
"sentinels" key a configuration:
|
189
|
+
|
190
|
+
Via timberline.yml:
|
191
|
+
|
192
|
+
```yaml
|
193
|
+
host: 127.0.0.1
|
194
|
+
sentinels:
|
195
|
+
- host: 127.0.0.1
|
196
|
+
port: 26379
|
197
|
+
```
|
198
|
+
|
199
|
+
Via the Timberline.configure:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
Timberline.configure do |c|
|
203
|
+
# ...
|
204
|
+
c.sentinels = [{ host: 127.0.0.1, port: 26379 }]
|
205
|
+
end
|
206
|
+
```
|
207
|
+
|
208
|
+
Via the ENV VAR
|
209
|
+
```bash
|
210
|
+
export TIMBERLINE_URL="redis://:foobar@192.168.1.105:12345/1?sentinel=host1:1111&sentinel=host2:2222"
|
211
|
+
```
|
212
|
+
|
178
213
|
## TODO
|
179
214
|
|
180
215
|
Still to be done:
|
data/lib/timberline/config.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
1
3
|
class Timberline
|
2
4
|
# Object that manages Timberline configuration. Responsible for Redis configs
|
3
5
|
# as well as Timberline-specific configuration values, like how many times an
|
4
6
|
# item should be retried in a queue.
|
5
7
|
#
|
6
|
-
# @attr [Integer] database part of the redis configuration - index of the
|
8
|
+
# @attr [Integer] database part of the redis configuration - index of the
|
7
9
|
# redis database to use
|
8
|
-
# @attr [String] host part of the redis configuration - the hostname of the
|
10
|
+
# @attr [String] host part of the redis configuration - the hostname of the
|
9
11
|
# redis server
|
10
12
|
# @attr [Integer] port part of the redis configuration - the port of the
|
11
13
|
# redis server
|
@@ -21,22 +23,18 @@ class Timberline
|
|
21
23
|
# should be allowed to retry itself before it is placed on the error queue
|
22
24
|
# @attr [Integer] stat_timeout the number of minutes that stats will stay live
|
23
25
|
# in redis before they are expired
|
26
|
+
# @attr [Array] sentinels a list of sentinel hosts that can be connected to
|
27
|
+
# for failover protection.
|
24
28
|
#
|
25
29
|
class Config
|
26
|
-
attr_accessor :database, :host, :port, :timeout, :password,
|
27
|
-
:logger, :namespace, :max_retries, :stat_timeout
|
30
|
+
attr_accessor :database, :host, :port, :timeout, :password,
|
31
|
+
:logger, :namespace, :max_retries, :stat_timeout, :sentinels
|
28
32
|
|
29
33
|
# Attemps to load configuration from TIMBERLINE_YAML, if it exists.
|
30
34
|
# Otherwise creates a default Config object.
|
31
|
-
def initialize
|
32
|
-
|
33
|
-
|
34
|
-
yaml = YAML.load_file(TIMBERLINE_YAML)
|
35
|
-
load_from_yaml(yaml)
|
36
|
-
else
|
37
|
-
raise "Specified Timberline config file #{TIMBERLINE_YAML} is not present."
|
38
|
-
end
|
39
|
-
end
|
35
|
+
def initialize
|
36
|
+
configure_via_yaml
|
37
|
+
configure_via_env
|
40
38
|
end
|
41
39
|
|
42
40
|
# @return [String] the configured redis namespace, with a default of 'timberline'
|
@@ -49,27 +47,80 @@ class Timberline
|
|
49
47
|
@max_retries ||= 5
|
50
48
|
end
|
51
49
|
|
52
|
-
# @return [Integer] the configured lifetime of stats (in minutes), with a default of 60
|
50
|
+
# @return [Integer] the configured lifetime of stats (in minutes), with a default of 60
|
53
51
|
def stat_timeout
|
54
52
|
@stat_timeout ||= 60
|
55
53
|
end
|
56
54
|
|
55
|
+
# @return [{host: "x", port: 1}] list of sentinel server
|
56
|
+
def sentinels
|
57
|
+
@sentinels ||= []
|
58
|
+
end
|
59
|
+
|
57
60
|
# @return [Hash] a Redis-ready hash for use in instantiating a new redis object.
|
58
61
|
def redis_config
|
59
62
|
config = {}
|
60
63
|
|
61
|
-
{
|
64
|
+
{
|
65
|
+
db: database,
|
66
|
+
host: host,
|
67
|
+
port: port,
|
68
|
+
timeout: timeout,
|
69
|
+
password: password,
|
70
|
+
logger: logger,
|
71
|
+
sentinels: sentinels.empty? ? nil : sentinels
|
72
|
+
}.each do |name, value|
|
62
73
|
config[name] = value unless value.nil?
|
63
74
|
end
|
64
75
|
|
65
76
|
config
|
66
77
|
end
|
67
78
|
|
68
|
-
|
79
|
+
private
|
80
|
+
|
81
|
+
def configure_via_yaml
|
82
|
+
return unless defined? TIMBERLINE_YAML
|
83
|
+
if File.exist?(TIMBERLINE_YAML)
|
84
|
+
yaml = YAML.load_file(TIMBERLINE_YAML)
|
85
|
+
load_from_yaml(yaml)
|
86
|
+
else
|
87
|
+
fail "Specified Timberline config file #{TIMBERLINE_YAML} is not present."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def convert_if_int(val)
|
92
|
+
# convert strings that only have integers in them to ints
|
93
|
+
val.match(/\A[+-]?\d+\Z/) ? val.to_i : val
|
94
|
+
end
|
95
|
+
|
96
|
+
def configure_via_env
|
97
|
+
return unless ENV.key?("TIMBERLINE_URL")
|
98
|
+
|
99
|
+
uri = URI::Parser.new.parse(ENV["TIMBERLINE_URL"])
|
100
|
+
fail "Must be a redis url, not #{uri.scheme.inspect}" unless uri.scheme == "redis"
|
101
|
+
|
102
|
+
@host = uri.host
|
103
|
+
@port = uri.port
|
104
|
+
@database = convert_if_int(uri.path[1..-1])
|
105
|
+
@password = uri.password
|
106
|
+
|
107
|
+
params = uri.query.nil? ? {} : CGI.parse(uri.query)
|
108
|
+
%w(timeout namespace).each do |setting|
|
109
|
+
next unless params.key?(setting)
|
110
|
+
instance_variable_set("@#{setting}", convert_if_int(params[setting][0]))
|
111
|
+
end
|
112
|
+
if params.key?("sentinel")
|
113
|
+
params["sentinel"].each do |val|
|
114
|
+
host, port = val.split(":")
|
115
|
+
self.sentinels += [{ "host" => host, "port" => convert_if_int(port) }]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
69
120
|
def load_from_yaml(yaml_config)
|
70
|
-
|
71
|
-
|
72
|
-
|
121
|
+
fail "Missing yaml configs!" if yaml_config.nil?
|
122
|
+
%w(database host port timeout password namespace sentinels).each do |setting|
|
123
|
+
instance_variable_set("@#{setting}", yaml_config[setting])
|
73
124
|
end
|
74
125
|
end
|
75
126
|
end
|
data/lib/timberline/version.rb
CHANGED
@@ -2,6 +2,47 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Timberline::Config do
|
4
4
|
describe "newly created" do
|
5
|
+
context "when the TIMBERLINE_URL env var is defined" do
|
6
|
+
before do
|
7
|
+
ENV["TIMBERLINE_URL"] = "redis://:apassword@ahostname:9000/3?timeout=666&namespace=foobar&sentinel=sentinel1:1&sentinel=sentinel2:2"
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
ENV.delete("TIMBERLINE_URL")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "loads the host variable from the env var" do
|
15
|
+
expect(subject.host).to eq("ahostname")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "loads the port variable from the env var" do
|
19
|
+
expect(subject.port).to eq(9000)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "loads the timeout variable from the env var" do
|
23
|
+
expect(subject.timeout).to eq(666)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "loads the password from the env var" do
|
27
|
+
expect(subject.password).to eq("apassword")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "loads the database from the env var" do
|
31
|
+
expect(subject.database).to eq(3)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "loads the namespace from the env var" do
|
35
|
+
expect(subject.namespace).to eq("foobar")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "loads the sentinel servers" do
|
39
|
+
expect(subject.sentinels).to eq([
|
40
|
+
{ "host" => "sentinel1", "port" => 1 },
|
41
|
+
{ "host" => "sentinel2", "port" => 2 }
|
42
|
+
])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
5
46
|
context "when the TIMBERLINE_YAML constant is defined" do
|
6
47
|
context "and the specified file exists" do
|
7
48
|
before do
|
@@ -35,6 +76,11 @@ describe Timberline::Config do
|
|
35
76
|
it "loads the namespace from the config file" do
|
36
77
|
expect(subject.namespace).to eq("treecurve")
|
37
78
|
end
|
79
|
+
|
80
|
+
it "loads the sentinels from the config file" do
|
81
|
+
sentinels = [{"host" => "localhost", "port" => 111111}]
|
82
|
+
expect(subject.sentinels).to eq sentinels
|
83
|
+
end
|
38
84
|
end
|
39
85
|
|
40
86
|
context "and the specified file doesn't exist" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timberline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tommy Morgan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -202,4 +202,14 @@ signing_key:
|
|
202
202
|
specification_version: 4
|
203
203
|
summary: Timberline is a simple and extensible queuing system built in Ruby and backed
|
204
204
|
by Redis.
|
205
|
-
test_files:
|
205
|
+
test_files:
|
206
|
+
- spec/config/test_config.yaml
|
207
|
+
- spec/lib/timberline/anonymous_worker_spec.rb
|
208
|
+
- spec/lib/timberline/config_spec.rb
|
209
|
+
- spec/lib/timberline/envelope_spec.rb
|
210
|
+
- spec/lib/timberline/queue_spec.rb
|
211
|
+
- spec/lib/timberline_spec.rb
|
212
|
+
- spec/spec_helper.rb
|
213
|
+
- spec/support/timberline_reset.rb
|
214
|
+
- spec/support/timberline_yaml.rb
|
215
|
+
has_rdoc:
|