wordnik 4.08 → 4.09

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.
@@ -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