copycopter_client 1.0.0.beta1 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
@@ -35,10 +35,13 @@ module CopycopterClient
35
35
  if spawner?
36
36
  register_spawn_hooks
37
37
  else
38
+ register_job_hooks
38
39
  logger.info("Starting poller")
39
40
  @pending = true
40
41
  at_exit { sync }
41
- Thread.new { poll }
42
+ unless Thread.new { poll }
43
+ logger.error("Couldn't start poller thread")
44
+ end
42
45
  end
43
46
  end
44
47
 
@@ -78,6 +81,12 @@ module CopycopterClient
78
81
  end
79
82
  end
80
83
 
84
+ def flush
85
+ with_queued_changes do |queued|
86
+ client.upload(queued)
87
+ end
88
+ end
89
+
81
90
  private
82
91
 
83
92
  attr_reader :client, :polling_delay, :logger
@@ -95,9 +104,7 @@ module CopycopterClient
95
104
  begin
96
105
  downloaded_blurbs = client.download
97
106
  lock { @blurbs = downloaded_blurbs }
98
- with_queued_changes do |queued|
99
- client.upload(queued)
100
- end
107
+ flush
101
108
  rescue ConnectionError => error
102
109
  logger.error(error.message)
103
110
  end
@@ -124,6 +131,20 @@ module CopycopterClient
124
131
  $0.include?("ApplicationSpawner") || $0 =~ /unicorn.*master/
125
132
  end
126
133
 
134
+ def register_job_hooks
135
+ if defined?(Resque)
136
+ logger.info("Registered Resque after_perform hook")
137
+ Resque::Job.class_eval do
138
+ alias_method :perform_without_copycopter, :perform
139
+ def perform
140
+ job_was_performed = perform_without_copycopter
141
+ CopycopterClient.flush
142
+ job_was_performed
143
+ end
144
+ end
145
+ end
146
+ end
147
+
127
148
  def register_spawn_hooks
128
149
  if defined?(PhusionPassenger)
129
150
  logger.info("Registered Phusion Passenger fork hook")
@@ -1,6 +1,6 @@
1
1
  module CopycopterClient
2
2
  # Client version
3
- VERSION = "1.0.0.beta1"
3
+ VERSION = "1.0.0.beta2"
4
4
 
5
5
  # API version being used to communicate with the server
6
6
  API_VERSION = "2.0"
@@ -34,6 +34,12 @@ module CopycopterClient
34
34
  sync.start
35
35
  end
36
36
 
37
+ # Flush queued changed synchronously
38
+ # This is called from the Resque after perform "hook"
39
+ def self.flush
40
+ sync.flush
41
+ end
42
+
37
43
  # Call this method to modify defaults in your initializers.
38
44
  #
39
45
  # @example
@@ -95,6 +95,17 @@ describe CopycopterClient::Sync do
95
95
  client.uploaded.should == { 'test.key' => 'test value' }
96
96
  end
97
97
 
98
+ it "uploads changes when flushed" do
99
+ sync = build_sync(:polling_delay => 86400)
100
+ sync.start
101
+ sleep 2
102
+ sync['test.key'] = 'test value'
103
+ sync.flush
104
+ sleep(2)
105
+
106
+ client.uploaded.should == { 'test.key' => 'test value' }
107
+ end
108
+
98
109
  it "handles connection errors when polling" do
99
110
  failure = "server is napping"
100
111
  logger = FakeLogger.new
@@ -153,6 +164,39 @@ describe CopycopterClient::Sync do
153
164
  "Got entries: #{logger.entries.inspect}"
154
165
  end
155
166
 
167
+ it "flushes after running a resque job" do
168
+ define_constant('Resque', Module.new)
169
+ job = define_constant('Resque::Job', FakeResqueJob).new(:key => 'test.key', :value => 'all your base')
170
+
171
+ api_key = "12345"
172
+ FakeCopycopterApp.add_project api_key
173
+ logger = FakeLogger.new
174
+
175
+ config = { :logger => logger, :polling_delay => 86400, :api_key => api_key }
176
+ default_config = CopycopterClient::Configuration.new.to_hash.update(config)
177
+ real_client = CopycopterClient::Client.new(default_config)
178
+ sync = CopycopterClient::Sync.new(real_client, default_config)
179
+ CopycopterClient.sync = sync
180
+ job.sync = sync
181
+
182
+ sync.start
183
+ sleep(2)
184
+
185
+ logger.should have_entry(:info, "Registered Resque after_perform hook")
186
+
187
+ if fork
188
+ Process.wait
189
+ else
190
+ job.perform
191
+ exit!
192
+ end
193
+ sleep(2)
194
+
195
+ project = FakeCopycopterApp.project(api_key)
196
+ project.draft['test.key'].should == 'all your base'
197
+
198
+ end
199
+
156
200
  it "starts after spawning when using unicorn" do
157
201
  logger = FakeLogger.new
158
202
  define_constant('Unicorn', Module.new)
@@ -232,6 +276,15 @@ describe CopycopterClient::Sync do
232
276
  logger.should_not have_entry(:info, "Waiting for first sync")
233
277
  end
234
278
 
279
+ it "logs an error if the background thread can't start" do
280
+ Thread.stubs(:new => nil)
281
+ logger = FakeLogger.new
282
+
283
+ build_sync(:logger => logger).start
284
+
285
+ logger.should have_entry(:error, "Couldn't start poller thread")
286
+ end
287
+
235
288
  describe "given locked mutex" do
236
289
  Spec::Matchers.define :finish_after_unlocking do |mutex|
237
290
  match do |thread|
@@ -291,5 +344,15 @@ describe CopycopterClient::Sync do
291
344
 
292
345
  sync.should have_received(:start)
293
346
  end
347
+
348
+ it "flushes from the top level" do
349
+ sync = build_sync
350
+ CopycopterClient.sync = sync
351
+ sync.stubs(:flush)
352
+
353
+ CopycopterClient.flush
354
+
355
+ sync.should have_received(:flush)
356
+ end
294
357
  end
295
358
 
@@ -0,0 +1,11 @@
1
+ class FakeResqueJob
2
+ attr_accessor :sync
3
+ def initialize(hash)
4
+ @key = hash[:key]
5
+ @value = hash[:value]
6
+ end
7
+ def perform
8
+ sync[@key] = @value
9
+ true
10
+ end
11
+ end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: copycopter_client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196353
5
- prerelease: 6
4
+ hash: 299253594
5
+ prerelease: true
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
- - beta
11
- - 1
12
- version: 1.0.0.beta1
10
+ - beta2
11
+ version: 1.0.0.beta2
13
12
  platform: ruby
14
13
  authors:
15
14
  - thoughtbot
@@ -21,9 +20,10 @@ date: 2010-06-04 00:00:00 -04:00
21
20
  default_executable:
22
21
  dependencies:
23
22
  - !ruby/object:Gem::Dependency
24
- name: i18n
23
+ type: :runtime
25
24
  prerelease: false
26
- requirement: &id001 !ruby/object:Gem::Requirement
25
+ name: i18n
26
+ version_requirements: &id001 !ruby/object:Gem::Requirement
27
27
  none: false
28
28
  requirements:
29
29
  - - ">="
@@ -32,8 +32,7 @@ dependencies:
32
32
  segments:
33
33
  - 0
34
34
  version: "0"
35
- type: :runtime
36
- version_requirements: *id001
35
+ requirement: *id001
37
36
  description:
38
37
  email: support@thoughtbot.com
39
38
  executables: []
@@ -73,6 +72,7 @@ files:
73
72
  - spec/support/fake_html_safe_string.rb
74
73
  - spec/support/fake_logger.rb
75
74
  - spec/support/fake_passenger.rb
75
+ - spec/support/fake_resque_job.rb
76
76
  - spec/support/fake_unicorn.rb
77
77
  - features/rails.feature
78
78
  - features/step_definitions/copycopter_server_steps.rb
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  requirements: []
114
114
 
115
115
  rubyforge_project: copycopter_client
116
- rubygems_version: 1.4.1
116
+ rubygems_version: 1.3.7
117
117
  signing_key:
118
118
  specification_version: 3
119
119
  summary: Client for the Copycopter content management service