backup-backblaze 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/Rakefile +25 -1
- data/lib/backup/backblaze.rb +3 -0
- data/lib/backup/backblaze/account.rb +41 -85
- data/lib/backup/backblaze/api_importer.rb +93 -0
- data/lib/backup/backblaze/back_blaze.rb +6 -18
- data/lib/backup/backblaze/hash_wrap.rb +2 -0
- data/lib/backup/backblaze/http.rb +132 -0
- data/lib/backup/backblaze/retry.rb +56 -52
- data/lib/backup/backblaze/retry_lookup.rb +112 -0
- data/lib/backup/backblaze/upload_file.rb +38 -49
- data/lib/backup/backblaze/upload_large_file.rb +61 -83
- data/lib/backup/backblaze/url_token.rb +11 -0
- data/lib/backup/backblaze/version.rb +1 -1
- data/src/retry.pl +157 -0
- data/src/retry_lookup.erb +42 -0
- metadata +8 -2
data/src/retry.pl
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
% execute with SWI-Prolog:
|
2
|
+
%
|
3
|
+
% generate the when clauses for matching
|
4
|
+
% swipl -q -l retry.pl -t to_whens
|
5
|
+
%
|
6
|
+
% generate the map for dependency checking
|
7
|
+
% swipl -q -l retry.pl -t to_map
|
8
|
+
|
9
|
+
:- use_module(library(bounds)).
|
10
|
+
|
11
|
+
% The complete list as of 04-Sep-2018
|
12
|
+
all_b2api(b2_authorize_account).
|
13
|
+
all_b2api(b2_cancel_large_file).
|
14
|
+
all_b2api(b2_create_bucket).
|
15
|
+
all_b2api(b2_create_key).
|
16
|
+
all_b2api(b2_delete_bucket).
|
17
|
+
all_b2api(b2_delete_file_version).
|
18
|
+
all_b2api(b2_delete_key).
|
19
|
+
all_b2api(b2_download_file_by_id).
|
20
|
+
all_b2api(b2_download_file_by_name).
|
21
|
+
all_b2api(b2_finish_large_file).
|
22
|
+
all_b2api(b2_get_download_authorization).
|
23
|
+
all_b2api(b2_get_file_info).
|
24
|
+
all_b2api(b2_get_upload_part_url).
|
25
|
+
all_b2api(b2_get_upload_url).
|
26
|
+
all_b2api(b2_hide_file).
|
27
|
+
all_b2api(b2_list_buckets).
|
28
|
+
all_b2api(b2_list_file_names).
|
29
|
+
all_b2api(b2_list_file_versions).
|
30
|
+
all_b2api(b2_list_keys).
|
31
|
+
all_b2api(b2_list_parts).
|
32
|
+
all_b2api(b2_list_unfinished_large_files).
|
33
|
+
all_b2api(b2_start_large_file).
|
34
|
+
all_b2api(b2_update_bucket).
|
35
|
+
all_b2api(b2_upload_file).
|
36
|
+
all_b2api(b2_upload_part ).
|
37
|
+
|
38
|
+
% All api calls we're interested in.
|
39
|
+
% In approximate frequency of usage order.
|
40
|
+
some_b2api(b2_upload_part).
|
41
|
+
some_b2api(b2_get_upload_part_url).
|
42
|
+
some_b2api(b2_get_upload_url).
|
43
|
+
some_b2api(b2_upload_file).
|
44
|
+
some_b2api(b2_authorize_account).
|
45
|
+
some_b2api(b2_list_buckets).
|
46
|
+
some_b2api(b2_list_file_names).
|
47
|
+
some_b2api(b2_delete_file_version).
|
48
|
+
some_b2api(b2_finish_large_file).
|
49
|
+
some_b2api(b2_start_large_file).
|
50
|
+
|
51
|
+
b2api(A) :- some_b2api(A).
|
52
|
+
|
53
|
+
% Needs library(bounds). Leaves the bounds as a predicate, which is nicer to
|
54
|
+
% read, can be output as a ruby range, and still matches correctly.
|
55
|
+
five_hundreds(V) :- V in 500..599.
|
56
|
+
|
57
|
+
% these two have special retries
|
58
|
+
upload_retry(b2_upload_part, b2_get_upload_part_url).
|
59
|
+
upload_retry(b2_upload_file, b2_get_upload_url).
|
60
|
+
|
61
|
+
% These two codes from 401 are allowed to retry
|
62
|
+
not_authorised_retryable_code(expired_auth_token).
|
63
|
+
not_authorised_retryable_code(bad_auth_token).
|
64
|
+
|
65
|
+
% Sources:
|
66
|
+
% https://www.backblaze.com/b2/docs/calling.html
|
67
|
+
% https://www.backblaze.com/b2/docs/uploading.html
|
68
|
+
% https://www.backblaze.com/b2/docs/integration_checklist.html
|
69
|
+
|
70
|
+
%%%%%%%%%%%%%%
|
71
|
+
% HttpStatus is one of the Http status codes, as an integer
|
72
|
+
% Code is a backblaze-specific string, read from the response body
|
73
|
+
% RetryCalls is the set of calls to use to retry the OriginalCall
|
74
|
+
% retry(OriginalCall, HttpStatus, Code, RetryCalls)
|
75
|
+
|
76
|
+
% No retry, cos it succeeded :-D
|
77
|
+
retry(_, HttpStatus, _, []) :- HttpStatus in 200..399, false.
|
78
|
+
|
79
|
+
% upload-specific 401 :- re-fetch upload url.
|
80
|
+
%
|
81
|
+
% Some docs say only for expired_auth_token? Other docs say just retry
|
82
|
+
% regardless of code.
|
83
|
+
retry( Call, 401, Code, [Retry,Call] ) :-
|
84
|
+
not_authorised_retryable_code(Code),
|
85
|
+
upload_retry(Call,Retry).
|
86
|
+
|
87
|
+
% upload-specific 408,5xx - re-fetch upload url
|
88
|
+
retry( Call, HttpStatus, _Code, [Retry,Call] ) :-
|
89
|
+
(HttpStatus = 408; five_hundreds(HttpStatus)),
|
90
|
+
upload_retry(Call,Retry).
|
91
|
+
|
92
|
+
% upload-specific 429 - just retry the call
|
93
|
+
retry( Call, 429, _Code, [Call] ) :- upload_retry(Call,_).
|
94
|
+
|
95
|
+
% non-upload 401 failures - re-auth account
|
96
|
+
retry( Call, 401, Code, [b2_authorize_account,Call] ) :-
|
97
|
+
Call \= b2_authorize_account, % b2_authorize_account can't retry with b2_authorize_account
|
98
|
+
not(upload_retry(Call,_)),
|
99
|
+
not_authorised_retryable_code(Code),
|
100
|
+
not(upload_retry(Call,_)).
|
101
|
+
|
102
|
+
% non-upload with 408, 429, and 5xx - retry call (after a backoff)
|
103
|
+
retry( Call,HttpStatus,_Code,[Call] ) :-
|
104
|
+
not(upload_retry(Call,_)),
|
105
|
+
(member(HttpStatus, [408,429]); five_hundreds(HttpStatus)),
|
106
|
+
not(upload_retry(Call,_)).
|
107
|
+
|
108
|
+
%%%%%%%%%%%%%%%%%%%
|
109
|
+
% generate all posibilities
|
110
|
+
allballs( Call,HttpStatus,Code,Retry ) :-
|
111
|
+
b2api(Call),
|
112
|
+
retry(Call,HttpStatus,Code,Retry).
|
113
|
+
|
114
|
+
%%%%%%%%%%%%%%%%%%%
|
115
|
+
% Various conversions to ruby
|
116
|
+
|
117
|
+
% use with with_output_to, can't figure out another way :-\
|
118
|
+
to_ruby_commas([]).
|
119
|
+
to_ruby_commas([Last]) :- !, to_ruby(Last).
|
120
|
+
to_ruby_commas([Fst|Rst]) :- to_ruby(Fst), format(','), to_ruby_commas(Rst).
|
121
|
+
|
122
|
+
% This has to be before ruby_lit(A). Dunno why.
|
123
|
+
to_ruby(Range) :- attvar(Range), get_attr(Range, bounds, bounds(N,X,_)), format('~d..~d', [N,X]).
|
124
|
+
to_ruby(A) :- atom(A), format(':~a', A).
|
125
|
+
to_ruby(S) :- string(S), format('"~s"', S).
|
126
|
+
to_ruby(N) :- integer(N), format('~d', N).
|
127
|
+
to_ruby(F) :- float(F), format( '~f', F).
|
128
|
+
to_ruby(L) :- is_list(L), format('[~@]', to_ruby_commas(L)).
|
129
|
+
to_ruby(ruby_lit(A)) :- format('~w', A).
|
130
|
+
|
131
|
+
default_to_any(Code,DefCode) :- ground(Code) -> format(atom(DefCode), ':~a', Code); DefCode = 'Any'.
|
132
|
+
|
133
|
+
all_whens :-
|
134
|
+
allballs( Call, HttpStatus, Code, Retries ),
|
135
|
+
to_when( Call, HttpStatus, Code, Retries ).
|
136
|
+
|
137
|
+
to_when( Call, HttpStatus, Code, Retries ) :-
|
138
|
+
default_to_any(Code,DefaultedAnyCode),
|
139
|
+
format('when [~@, ~@, ~a] then ~@~n', [to_ruby(Call),to_ruby(HttpStatus),DefaultedAnyCode,to_ruby(Retries)] ).
|
140
|
+
|
141
|
+
to_whens :- findall(_,all_whens,_).
|
142
|
+
to_whens(Term) :- findall(_,(apply(Term,C,Hs,Co,Re),retry(C,Hs,Co,Re)),_).
|
143
|
+
|
144
|
+
some_whens :-
|
145
|
+
findall(
|
146
|
+
_,
|
147
|
+
(member(C,[b2_upload_part,b2_upload_file,b2_authorize_account,any_call]),retry(C,Hs,Co,Re),to_when(C,Hs,Co,Re))
|
148
|
+
,_).
|
149
|
+
|
150
|
+
map_all :-
|
151
|
+
format('retries = Hash.new{|h,k| h[k] = Set.new}~n'),
|
152
|
+
allballs( Call, _HttpStatus, _Code, Retries ),
|
153
|
+
selectchk(Call,Retries,Uniqs),
|
154
|
+
Uniqs \= [],
|
155
|
+
format('retries[~@].merge(~@)~n', [to_ruby(Call),to_ruby(Uniqs)] ).
|
156
|
+
|
157
|
+
to_map :- findall(_,map_all,_), format('retries~n').
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Backblaze
|
5
|
+
module RetryLookup
|
6
|
+
def (Any = Object.new).=== _other; true end
|
7
|
+
|
8
|
+
module Matcher
|
9
|
+
refine Array do
|
10
|
+
def === other
|
11
|
+
return false unless size == other.size
|
12
|
+
size.times.all? do |idx|
|
13
|
+
self[idx] === other[idx]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
using Matcher
|
20
|
+
|
21
|
+
# Generated from retry.pl
|
22
|
+
#
|
23
|
+
# Cross-product of all the retry scenarios we know about. This probably
|
24
|
+
# isn't the fastest way to calculate retries. But they're rare, so the
|
25
|
+
# slowdown doesn't matter. There is a more general pattern, but I don't
|
26
|
+
# want to get sucked into implementing unification.
|
27
|
+
module_function def retry_sequence api_call, http_status, code
|
28
|
+
case [api_call.to_sym, http_status, code.to_sym]
|
29
|
+
<%= `swipl -q -l #{__dir__}/retry.pl -t to_whens`.gsub(/^(\s*)/, ' ') -%>
|
30
|
+
else [] # No retry. eg 400 and most 401 should just fail immediately
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module_function def retry_dependencies
|
35
|
+
@retry_dependencies ||= begin
|
36
|
+
# didn't want to fight with prolog to generate uniq values here, so just let ruby do it.
|
37
|
+
<%= `swipl -q -l #{__dir__}/retry.pl -t to_map`.gsub(/^(\s*)/, ' ') -%>
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backup-backblaze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Anderson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -115,12 +115,18 @@ files:
|
|
115
115
|
- bin/setup
|
116
116
|
- lib/backup/backblaze.rb
|
117
117
|
- lib/backup/backblaze/account.rb
|
118
|
+
- lib/backup/backblaze/api_importer.rb
|
118
119
|
- lib/backup/backblaze/back_blaze.rb
|
119
120
|
- lib/backup/backblaze/hash_wrap.rb
|
121
|
+
- lib/backup/backblaze/http.rb
|
120
122
|
- lib/backup/backblaze/retry.rb
|
123
|
+
- lib/backup/backblaze/retry_lookup.rb
|
121
124
|
- lib/backup/backblaze/upload_file.rb
|
122
125
|
- lib/backup/backblaze/upload_large_file.rb
|
126
|
+
- lib/backup/backblaze/url_token.rb
|
123
127
|
- lib/backup/backblaze/version.rb
|
128
|
+
- src/retry.pl
|
129
|
+
- src/retry_lookup.erb
|
124
130
|
homepage: http://github.com/djellemah/backup-backblaze
|
125
131
|
licenses:
|
126
132
|
- MIT
|