timberline 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f2df22b2ea8867378c5b0256c18d5014b75d218
4
- data.tar.gz: cebaa4450c46540581d082b0aa137b9c478272a2
3
+ metadata.gz: 5dcba7d76edc4b00c7060cfa2c01e7df38700912
4
+ data.tar.gz: f3dad3c3080a4c35db3f91f2b8b599f008039bf7
5
5
  SHA512:
6
- metadata.gz: c0fed6eec0f3f8c4240e8227331b896180d33b47f02e3a28d48f1dd78abfdca51f93ffa3272edb444e113d2b6b856b72d6764a1638e5788689c16fa5ec713d4b
7
- data.tar.gz: 626722046cd800dcf5683c775523a3e41ce0e39a77b161374e1a2d4b80196bde4cc8873fbb5d66050e0636e0ffb82b79939ce041437b97612a8410697edc85df
6
+ metadata.gz: 03b760d6e84c72d91884ee18f87fa797577839f16e495148c144144780adfeab120e8bb2ffb4661eec4d51d1e4dbc06e14a0faab6cef95400712a3c3a6fbb2d0
7
+ data.tar.gz: 3cbb508700948108bbabd33e1e24e0f98189ae06545047dec89479cb9e3266aeb7b9116bae2fd6c931434722b77cd5e81b91c21df54c869412174ca1f3f20d7f
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ 0.8.3
2
+ - Add support for configuring via env var
3
+ - Add support for Redis sentinels
1
4
  0.7.0
2
5
  - Add Worker objects
3
6
  - Add YARD documentation, publish docs to rubydoc.info
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
- `Timberline` included with this gem.
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:
@@ -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
- if defined? TIMBERLINE_YAML
33
- if File.exists?(TIMBERLINE_YAML)
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
- { db: database, host: host, port: port, timeout: timeout, password: password, logger: logger }.each do |name, value|
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
- private
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
- raise "Missing yaml configs!" if yaml_config.nil?
71
- ["database","host","port","timeout","password","logger","namespace"].each do |setting|
72
- self.instance_variable_set("@#{setting}", yaml_config[setting])
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
@@ -1,4 +1,4 @@
1
1
  class Timberline
2
2
  # The current canonical version for Timberline.
3
- VERSION = "0.8.2"
3
+ VERSION = "0.8.3"
4
4
  end
@@ -4,3 +4,7 @@ timeout: 10
4
4
  password: foo
5
5
  database: 3
6
6
  namespace: treecurve
7
+ sentinels:
8
+ -
9
+ host: localhost
10
+ port: 111111
@@ -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.2
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-07-02 00:00:00.000000000 Z
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: