wordnik 4.08 → 4.09

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- wordnik (4.08)
4
+ wordnik (4.09)
5
5
  activemodel (>= 3.0.3)
6
6
  addressable (>= 2.2.4)
7
7
  htmlentities (>= 4.2.4)
data/README.md CHANGED
@@ -92,8 +92,8 @@ Releasing
92
92
  ---------
93
93
 
94
94
  ```bash
95
- rake swagger
96
- open lib/version.rb # bump the version number
95
+ rake swagger # um, don't do this unless the API has changed
96
+ edit lib/wordnik/version.rb # bump the version number
97
97
  rake spec # test
98
98
  git commit -am "newness" # commit
99
99
  git push origin master # push
@@ -19,8 +19,8 @@ module Wordnik
19
19
  attr_accessor :current_host
20
20
 
21
21
  def initialize(hosts)
22
- @all_hosts = hosts
23
- @hosts = @all_hosts
22
+ @all_hosts = hosts.clone
23
+ @hosts = @all_hosts.clone
24
24
  @failed_hosts_table = {}
25
25
  @current_host = nil
26
26
  end
@@ -36,7 +36,7 @@ module Wordnik
36
36
  #Wordnik.logger.debug "Informing failure about #{@current_host}. table: #{@failed_hosts_table.inspect}"
37
37
  if @failed_hosts_table.include?(@current_host)
38
38
  failures, failed_time = @failed_hosts_table[@current_host]
39
- @failed_hosts_table[@current_host] = [failures+1, failed_time]
39
+ @failed_hosts_table[@current_host] = [failures+1, Time.now.to_f]
40
40
  else
41
41
  @failed_hosts_table[@current_host] = [1, Time.now.to_f] # failure count, first failure time
42
42
  end
@@ -57,15 +57,25 @@ module Wordnik
57
57
  return if @failed_hosts_table.size == 0
58
58
  @failed_hosts_table.each do |host, pair|
59
59
  failures, failed_time = pair
60
- seconds_since_first_failure = (Time.now.to_f - failed_time)
61
- #Wordnik.logger.debug "Seconds since #{host}'s first failure: #{seconds_since_first_failure} compared to #{2**(failures-1)}"
60
+ n = Time.now.to_f
61
+ seconds_since_last_failure = (n - failed_time)
62
62
  # exponential backoff, but try every hour...
63
- if (seconds_since_first_failure > [3600, 2**(failures-1)].min)
63
+ if (seconds_since_last_failure > [3600, 2**(failures-1)].min)
64
64
  @hosts << host # give it a chance to succeed ...
65
- #Wordnik.logger.debug "Added #{host} to @hosts; now: #{@hosts}"
65
+ update_failed_time(host, n)
66
66
  end
67
67
  end
68
68
  end
69
+
70
+ # mostly useful in mock testing...
71
+ def update_failed_time(host, time=Time.now)
72
+ if @failed_hosts_table.include? host
73
+ failures, _ = @failed_hosts_table[host]
74
+ @failed_hosts_table[host] = [failures, time.to_f]
75
+ else
76
+ @failed_hosts_table[host] = [1,time.to_f]
77
+ end
78
+ end
69
79
  end
70
80
 
71
81
  end
@@ -1,3 +1,3 @@
1
1
  module Wordnik
2
- VERSION = "4.08"
2
+ VERSION = "4.09"
3
3
  end
@@ -1,28 +1,109 @@
1
1
  require 'spec_helper'
2
+ require 'objspace' # ruby 1.9, I think
2
3
 
3
4
  describe Wordnik::LoadBalancer do
4
- before(:each) do
5
- @hosts = ["alpha","beta","gamma","delta"].map{|x| "#{x}.wordnik.com"}
6
- end
5
+ before(:each) do
6
+ @hosts = ["alpha","beta","gamma","delta"].map{|x| "#{x}.wordnik.com"}
7
+ end
7
8
 
8
- describe "Load Balancer" do
9
+ describe "Load Balancer" do
9
10
  it "allows creation with a list of hosts" do
10
- lb = Wordnik::LoadBalancer.new(@hosts)
11
- h = lb.host
12
- @hosts.should include(h)
11
+ lb = Wordnik::LoadBalancer.new(@hosts)
12
+ h = lb.host
13
+ @hosts.should include(h)
13
14
  end
14
15
 
15
16
  it "returns different (random) hosts" do
16
- lb = Wordnik::LoadBalancer.new(@hosts)
17
- counts = Hash.new(0)
18
- 1.upto(1000) do
19
- h = lb.host
20
- counts[h] += 1
21
- end
22
- @hosts.each {|host| counts[host].should > 10}
17
+ lb = Wordnik::LoadBalancer.new(@hosts)
18
+ counts = Hash.new(0)
19
+ 1.upto(1000) do
20
+ h = lb.host
21
+ counts[h] += 1
22
+ end
23
+ @hosts.each {|host| counts[host].should > 10}
24
+ end
25
+
26
+ it "should not leak memory" do
27
+ lb = Wordnik::LoadBalancer.new(@hosts)
28
+ free = ObjectSpace.count_objects[:TOTAL]
29
+ 1000.times {h = lb.host}
30
+ free.should == ObjectSpace.count_objects[:TOTAL]
23
31
  end
24
32
 
25
- it "should not leak memory"
33
+ describe "Success and failure modes" do
34
+ it "allows for a failure" do
35
+ lb = Wordnik::LoadBalancer.new(@hosts)
36
+ h = lb.host
37
+ lb.inform_failure
38
+ lb.failed_hosts_table.size.should == 1
39
+ lb.hosts.should_not include(h)
40
+ lb.hosts.size.should == lb.all_hosts.size - 1
41
+ end
42
+
43
+ it "allows for two failures" do
44
+ lb = Wordnik::LoadBalancer.new(@hosts)
45
+ h1 = lb.host
46
+ lb.inform_failure
47
+ h2 = lb.host
48
+ lb.inform_failure
49
+ lb.failed_hosts_table.size.should == 2
50
+ lb.hosts.should_not include(h1)
51
+ lb.hosts.should_not include(h2)
52
+ lb.hosts.size.should == lb.all_hosts.size - 2
53
+ end
54
+
55
+ it "should never leave hosts empty" do
56
+ lb = Wordnik::LoadBalancer.new(@hosts)
57
+ @hosts.size.times{h = lb.host; lb.inform_failure}
58
+ lb.hosts.size.should == 1
59
+ end
26
60
 
61
+ it "allows for a subsequent success" do
62
+ lb = Wordnik::LoadBalancer.new(@hosts)
63
+ h = lb.host
64
+ lb.inform_failure
65
+ lb.inform_success
66
+ lb.failed_hosts_table.size.should == 0
67
+ lb.hosts.should include(h)
68
+ lb.hosts.size.should == lb.all_hosts.size
69
+ end
70
+
71
+ it "does exponential back-off" do
72
+ lb = Wordnik::LoadBalancer.new(@hosts)
73
+ t = Time.now
74
+ h = lb.host
75
+ lb.inform_failure
76
+ lb.update_failed_time(h, t)
77
+ lb.update_failed_time(h, t-2) # pretend it happened two seconds ago
78
+ lb.restore_failed_hosts_maybe
79
+ lb.hosts.should include(h)
80
+ lb.hosts.size.should == lb.all_hosts.size
81
+ lb.inform_failure
82
+ lb.inform_failure
83
+ lb.update_failed_time(h, t-2) # pretend it happened two seconds ago
84
+ lb.restore_failed_hosts_maybe
85
+ lb.hosts.should_not include(h)
86
+ lb.hosts.size.should == lb.all_hosts.size - 1
87
+ lb.update_failed_time(h, t-4) # pretend it happened 4 seconds ago
88
+ lb.restore_failed_hosts_maybe
89
+ lb.hosts.should include(h)
90
+ lb.hosts.size.should == lb.all_hosts.size
91
+ # create a lot of failures
92
+ 1000.times {lb.inform_failure}
93
+ lb.update_failed_time(h, t-((59*60)+59)) # pretend it happened 59:59 minutes ago
94
+ lb.restore_failed_hosts_maybe
95
+ lb.hosts.should_not include(h)
96
+ lb.hosts.size.should == lb.all_hosts.size - 1
97
+ lb.update_failed_time(h, t-(60*60)) # pretend it happened 1 hour ago
98
+ lb.restore_failed_hosts_maybe
99
+ lb.hosts.should include(h)
100
+ lb.hosts.size.should == lb.all_hosts.size
101
+ lb.inform_success
102
+ lb.failed_hosts_table.size.should == 0
103
+ end
104
+ end
27
105
  end
106
+
107
+
108
+
28
109
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wordnik
3
3
  version: !ruby/object:Gem::Version
4
- version: '4.08'
4
+ version: '4.09'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-10-29 00:00:00.000000000 Z
13
+ date: 2012-10-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: typhoeus
@@ -310,7 +310,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
310
310
  version: '0'
311
311
  segments:
312
312
  - 0
313
- hash: -796298365332589124
313
+ hash: 1161348886692951169
314
314
  required_rubygems_version: !ruby/object:Gem::Requirement
315
315
  none: false
316
316
  requirements:
@@ -319,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
319
  version: '0'
320
320
  segments:
321
321
  - 0
322
- hash: -796298365332589124
322
+ hash: 1161348886692951169
323
323
  requirements: []
324
324
  rubyforge_project: wordnik
325
325
  rubygems_version: 1.8.24