dbox 0.6.7 → 0.6.8

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,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