Skip to content

Commit

Permalink
Retry if a request fails
Browse files Browse the repository at this point in the history
  • Loading branch information
eschnett committed Mar 15, 2019
1 parent aeba462 commit f5e9073
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 31 deletions.
118 changes: 87 additions & 31 deletions src/DropboxSDK.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ function post_rpc(auth::Authorization,
else
body = HTTP.nobody
end
@label retry
try
resp = HTTP.request(
"POST", "https://api.dropboxapi.com/2/$fun", headers, body;
Expand All @@ -116,6 +117,15 @@ function post_rpc(auth::Authorization,
ex::HTTP.StatusError
resp = ex.response
res = JSON.parse(String(resp.body); dicttype=Dict, inttype=Int64)
retry_after = get(res, "retry_after", nothing)
if retry_after !== nothing
# We are rate limited; wait and try again
println("Warning $(ex.status): $(res["error_summary"])")
println("Waiting $retry_after seconds...")
sleep(retry_after)
println("Retrying...")
@goto retry
end
println("Error $(ex.status): $(res["error_summary"])")
return Error(res)
end
Expand All @@ -142,16 +152,27 @@ function post_content_upload(auth::Authorization,
push!(headers, "Dropbox-API-Arg" => JSON.json(args))
push!(headers, "Content-Type" => "application/octet-stream")
body = content
@label retry
try
resp = HTTP.request(
"POST", "https://content.dropboxapi.com/2/$fun", headers, body;
verbose=0)
res = JSON.parse(String(resp.body); dicttype=Dict, inttype=Int64)
return res
catch ex
@show ex
ex::HTTP.StatusError
resp = ex.response
res = JSON.parse(String(resp.body); dicttype=Dict, inttype=Int64)
retry_after = get(res, "retry_after", nothing)
if retry_after !== nothing
# We are rate limited; wait and try again
println("Warning $(ex.status): $(res["error_summary"])")
println("Waiting $retry_after seconds...")
sleep(retry_after)
println("Retrying...")
@goto retry
end
println("Error $(ex.status): $(res["error_summary"])")
return Error(res)
end
Expand All @@ -175,6 +196,7 @@ function post_content_download(auth::Authorization,
]
push!(headers, "Dropbox-API-Arg" => JSON.json(args))
push!(headers, "Content-Type" => "application/octet-stream")
@label retry
try
resp = HTTP.request(
"POST", "https://content.dropboxapi.com/2/$fun", headers;
Expand All @@ -184,9 +206,19 @@ function post_content_download(auth::Authorization,
dicttype=Dict, inttype=Int64)
return res, resp.body
catch ex
@show ex
ex::HTTP.StatusError
resp = ex.response
res = JSON.parse(String(resp.body); dicttype=Dict, inttype=Int64)
retry_after = get(res, "retry_after", nothing)
if retry_after !== nothing
# We are rate limited; wait and try again
println("Warning $(ex.status): $(res["error_summary"])")
println("Waiting $retry_after seconds...")
sleep(retry_after)
println("Retrying...")
@goto retry
end
println("Error $(ex.status): $(res["error_summary"])")
return Error(res)
end
Expand Down Expand Up @@ -298,6 +330,61 @@ end



export files_download
"""
files_download(auth::Authorization,
path::String
)::Union{Error, Tuple{FileMetadata, Vector{UInt8}}}
Download file `path`, return both its metadata and content.
"""
function files_download(auth::Authorization,
path::String)::
Union{Error, Tuple{FileMetadata, Vector{UInt8}}}

args = Dict(
"path" => path,
)
res = post_content_download(auth, "files/download", args)
if res isa Error return res end
res, content = res
metadata = FileMetadata(res)

# Check content hash
content_hash = calc_content_hash(content)
if metadata.content_hash != content_hash
return Error(Dict("error_summary" => "content hash does not match"))
end

return metadata, content
end



export files_get_metadata
"""
files_get_metadata(auth::Authorization,
path::String
)::Union{Error, Metadata}
Get metadata for file or folder `path`.
"""
function files_get_metadata(auth::Authorization,
path::String)::Union{Error, Metadata}
args = Dict(
"path" => path,
"include_media_info" => false,
"include_deleted" => false,
"include_has_explicit_shared_members" => false,
# "include_property_groups"
)
res = post_rpc(auth, "files/get_metadata", args)
if res isa Error return res end
return Metadata(res)
end



export Metadata
abstract type Metadata end
Metadata(d::Dict) = Dict(
Expand Down Expand Up @@ -409,37 +496,6 @@ end



export files_download
"""
files_download(auth::Authorization,
path::String
)::Union{Error, Tuple{FileMetadata, Vector{UInt8}}}
Download file `path`, return both its metadata and content.
"""
function files_download(auth::Authorization,
path::String)::
Union{Error, Tuple{FileMetadata, Vector{UInt8}}}

args = Dict(
"path" => path,
)
res = post_content_download(auth, "files/download", args)
if res isa Error return res end
res, content = res
metadata = FileMetadata(res)

# Check content hash
content_hash = calc_content_hash(content)
if metadata.content_hash != content_hash
return Error(Dict("error_summary" => "content hash does not match"))
end

return metadata, content
end



export WriteMode
@enum WriteMode add overwrite # update

Expand Down
7 changes: 7 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ end
@test String(content) == "Hello, World!\n"
end

@testset "Get file metadata" begin
metadata = files_get_metadata(auth, "/$folder/file")
@test metadata.path_display == "/$folder/file"
@test (metadata.content_hash ==
calc_content_hash(Vector{UInt8}("Hello, World!\n")))
end

@testset "Upload empty file" begin
metadata = files_upload(auth, "/$folder/file0", Vector{UInt8}(""))
@test metadata isa FileMetadata
Expand Down

0 comments on commit f5e9073

Please sign in to comment.