dbox 0.6.7 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ == 0.6.8 / 2012-04-02
2
+ * Minor Enhancements
3
+ * Added retries after receiving HTTPServiceUnavailable from Dropbox API.
4
+ * Turned number of threads down to 3 (more than that triggers Dropbox rate limiting after a while).
5
+
1
6
  == 0.6.7 / 2012-03-29
2
7
  * Minor Enhancements
3
8
  * Added timeout to SQLite operations to help with threads competing for db operations.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.7
1
+ 0.6.8
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "dbox"
8
- s.version = "0.6.7"
8
+ s.version = "0.6.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ken Pratt"]
12
- s.date = "2012-03-29"
12
+ s.date = "2012-04-03"
13
13
  s.description = "An easy-to-use Dropbox client with fine-grained control over syncs."
14
14
  s.email = "ken@kenpratt.net"
15
15
  s.executables = ["dbox"]
@@ -1,4 +1,7 @@
1
1
  module Dbox
2
+ NUM_TRIES = 3
3
+ TIME_BETWEEN_TRIES = 3 # in seconds
4
+
2
5
  class ConfigurationError < RuntimeError; end
3
6
  class ServerError < RuntimeError; end
4
7
  class RemoteMissing < RuntimeError; end
@@ -62,16 +65,24 @@ module Dbox
62
65
  @client = DropboxClient.new(@session, 'dropbox')
63
66
  end
64
67
 
65
- def run(path)
68
+ def run(path, tries = NUM_TRIES, &proc)
66
69
  begin
67
- res = yield
70
+ res = proc.call
68
71
  handle_response(path, res) { raise RuntimeError, "Unexpected result: #{res.inspect}" }
69
72
  rescue DropboxNotModified => e
70
73
  :not_modified
71
74
  rescue DropboxAuthError => e
72
75
  raise e
73
76
  rescue DropboxError => e
74
- handle_response(path, e.http_response) { raise ServerError, "Server error -- might be a hiccup, please try your request again (#{e.message})" }
77
+ if e.http_response.kind_of?(Net::HTTPServiceUnavailable) && tries > 0
78
+ log.info "Encountered 503 on #{path} (likely rate limiting). Sleeping #{TIME_BETWEEN_TRIES}s and trying again."
79
+ # TODO check for "Retry-After" header and use that for sleep instead of TIME_BETWEEN_TRIES
80
+ log.debug "Headers: #{e.http_response.to_hash.inspect}"
81
+ sleep TIME_BETWEEN_TRIES
82
+ run(path, tries - 1, &proc)
83
+ else
84
+ handle_response(path, e.http_response) { raise ServerError, "Server error -- might be a hiccup, please try your request again (#{e.message})" }
85
+ end
75
86
  end
76
87
  end
77
88
 
@@ -95,8 +106,8 @@ module Dbox
95
106
  end
96
107
 
97
108
  def metadata(path = "/", hash = nil, list=true)
98
- log.debug "Fetching metadata for #{path}"
99
109
  run(path) do
110
+ log.debug "Fetching metadata for #{path}"
100
111
  res = @client.metadata(path, 10000, list, hash)
101
112
  log.debug res.inspect
102
113
  res
@@ -104,8 +115,8 @@ module Dbox
104
115
  end
105
116
 
106
117
  def create_dir(path)
107
- log.info "Creating #{path}"
108
118
  run(path) do
119
+ log.info "Creating #{path}"
109
120
  begin
110
121
  @client.file_create_folder(path)
111
122
  rescue DropboxError => e
@@ -119,17 +130,19 @@ module Dbox
119
130
  end
120
131
 
121
132
  def delete_dir(path)
122
- log.info "Deleting #{path}"
123
133
  run(path) do
134
+ log.info "Deleting #{path}"
124
135
  @client.file_delete(path)
125
136
  end
126
137
  end
127
138
 
128
139
  def get_file(path, file_obj, stream=false)
129
- log.info "Downloading #{path}"
130
140
  unless stream
131
141
  # just download directly using the get_file API
132
- res = run(path) { @client.get_file(path) }
142
+ res = run(path) do
143
+ log.info "Downloading #{path}"
144
+ @client.get_file(path)
145
+ end
133
146
  if res.kind_of?(String)
134
147
  file_obj << res
135
148
  true
@@ -142,6 +155,7 @@ module Dbox
142
155
  res = run(path) { @client.media(path) }
143
156
  url = res[:url] if res && res.kind_of?(Hash)
144
157
  if url
158
+ log.info "Downloading #{path}"
145
159
  streaming_download(url, file_obj)
146
160
  else
147
161
  get_file(path, file_obj, false)
@@ -149,23 +163,23 @@ module Dbox
149
163
  end
150
164
  end
151
165
 
152
- def put_file(path, file_obj, previous_revision=nil)
153
- log.info "Uploading #{path}"
166
+ def put_file(path, local_path, previous_revision=nil)
154
167
  run(path) do
155
- @client.put_file(path, file_obj, false, previous_revision)
168
+ log.info "Uploading #{path}"
169
+ File.open(local_path, "r") {|f| @client.put_file(path, f, false, previous_revision) }
156
170
  end
157
171
  end
158
172
 
159
173
  def delete_file(path)
160
- log.info "Deleting #{path}"
161
174
  run(path) do
175
+ log.info "Deleting #{path}"
162
176
  @client.file_delete(path)
163
177
  end
164
178
  end
165
179
 
166
180
  def move(old_path, new_path)
167
- log.info "Moving #{old_path} to #{new_path}"
168
181
  run(old_path) do
182
+ log.info "Moving #{old_path} to #{new_path}"
169
183
  begin
170
184
  @client.file_move(old_path, new_path)
171
185
  rescue DropboxError => e
@@ -517,9 +517,7 @@ module Dbox
517
517
  end
518
518
 
519
519
  def upload
520
- File.open(local_path) do |f|
521
- api.put_file(remote_path, f)
522
- end
520
+ api.put_file(remote_path, local_path)
523
521
  force_metadata_update_from_server
524
522
  end
525
523
  end
@@ -1,6 +1,6 @@
1
1
  module Dbox
2
2
  class Syncer
3
- MAX_PARALLEL_DBOX_OPS = 5
3
+ MAX_PARALLEL_DBOX_OPS = 3
4
4
  MIN_BYTES_TO_STREAM_DOWNLOAD = 1024 * 100 # 100kB
5
5
 
6
6
  include Loggable
@@ -620,12 +620,10 @@ module Dbox
620
620
  def upload_file(file)
621
621
  local_path = relative_to_local_path(file[:path])
622
622
  remote_path = relative_to_remote_path(file[:path])
623
- File.open(local_path) do |f|
624
- db_entry = database.find_by_path(file[:path])
625
- last_revision = db_entry ? db_entry[:revision] : nil
626
- res = api.put_file(remote_path, f, last_revision)
627
- process_basic_remote_props(res)
628
- end
623
+ db_entry = database.find_by_path(file[:path])
624
+ last_revision = db_entry ? db_entry[:revision] : nil
625
+ res = api.put_file(remote_path, local_path, last_revision)
626
+ process_basic_remote_props(res)
629
627
  end
630
628
 
631
629
  def force_metadata_update_from_server(entry)
@@ -377,7 +377,14 @@ describe Dbox do
377
377
  Dbox.push(@local).should eql(:created => [], :deleted => [], :updated => ["hello.txt"], :failed => [])
378
378
 
379
379
  make_file "#{@alternate}/hello.txt"
380
- Dbox.push(@alternate).should eql(:created => [], :deleted => [], :updated => [], :conflicts => [{:original => "hello.txt", :renamed => "hello (1).txt"}], :failed => [])
380
+ res = Dbox.push(@alternate)
381
+ res[:created].should eql([])
382
+ res[:updated].should eql([])
383
+ res[:deleted].should eql([])
384
+ res[:failed].should eql([])
385
+ res[:conflicts].size.should eql(1)
386
+ res[:conflicts][0][:original].should eql("hello.txt")
387
+ res[:conflicts][0][:renamed].should match(/hello \(.* conflicted copy\).txt/)
381
388
  end
382
389
  end
383
390
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbox
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 7
10
- version: 0.6.7
9
+ - 8
10
+ version: 0.6.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ken Pratt
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-29 00:00:00 Z
18
+ date: 2012-04-03 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: multipart-post