baza.rb 0.7.0 → 0.9.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/lib/baza-rb/version.rb +1 -1
- data/lib/baza-rb.rb +293 -317
- data/test/test_baza-rb.rb +58 -31
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82a8cd1767f0f915a8345f5aa9ad79699b8a5a1d5f102cae9c77dd822d2a4e77
|
4
|
+
data.tar.gz: 15c9601e95620ccc4904c94e6e813cac13ea3b46aa398797433d03d9c5ccf219
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92e9caded9b39f0194c79920b12a5d81ee3dbc0e21bace3ce8b7368ecea63ab9c7af739e02114f1cdff72337d09926ec3a7b8bbf5b2c60ebc65e88e7a17dd6da
|
7
|
+
data.tar.gz: e492fc6856487d474b58d869844e51b240f629572d5d4118df20926ba2cbab5ec116e3af4ddfa7b7586a3ba82d03667d240adcc66f319c3b0106d7698ea81c7c
|
data/lib/baza-rb/version.rb
CHANGED
data/lib/baza-rb.rb
CHANGED
@@ -68,15 +68,7 @@ class BazaRb
|
|
68
68
|
def whoami
|
69
69
|
nick = nil
|
70
70
|
elapsed(@loog) do
|
71
|
-
ret =
|
72
|
-
retry_it do
|
73
|
-
checked(
|
74
|
-
Typhoeus::Request.get(
|
75
|
-
home.append('whoami').to_s,
|
76
|
-
headers:
|
77
|
-
)
|
78
|
-
)
|
79
|
-
end
|
71
|
+
ret = get(home.append('whoami'))
|
80
72
|
nick = ret.body
|
81
73
|
throw :"I know that I am @#{nick}, at #{@host}"
|
82
74
|
end
|
@@ -90,15 +82,7 @@ class BazaRb
|
|
90
82
|
def balance
|
91
83
|
z = nil
|
92
84
|
elapsed(@loog) do
|
93
|
-
ret =
|
94
|
-
retry_it do
|
95
|
-
checked(
|
96
|
-
Typhoeus::Request.get(
|
97
|
-
home.append('account').append('balance').to_s,
|
98
|
-
headers:
|
99
|
-
)
|
100
|
-
)
|
101
|
-
end
|
85
|
+
ret = get(home.append('account').append('balance'))
|
102
86
|
z = ret.body.to_f
|
103
87
|
throw :"The balance is Ƶ#{z}, at #{@host}"
|
104
88
|
end
|
@@ -110,41 +94,27 @@ class BazaRb
|
|
110
94
|
# @param [String] name The unique name of the job on the server
|
111
95
|
# @param [String] data The binary data to push to the server (factbase content)
|
112
96
|
# @param [Array<String>] meta List of metadata strings to attach to the job
|
113
|
-
# @
|
97
|
+
# @param [Integer] chunk_size Maximum size of one chunk
|
114
98
|
# @raise [ServerFailure] If the push operation fails
|
115
|
-
def push(name, data, meta)
|
99
|
+
def push(name, data, meta, chunk_size: 1_000_000)
|
116
100
|
raise 'The "name" of the job is nil' if name.nil?
|
117
101
|
raise 'The "name" of the job may not be empty' if name.empty?
|
118
102
|
raise 'The "data" of the job is nil' if data.nil?
|
119
103
|
raise 'The "meta" of the job is nil' if meta.nil?
|
120
|
-
id = 0
|
121
|
-
hdrs = headers.merge(
|
122
|
-
'Content-Type' => 'application/octet-stream',
|
123
|
-
'Content-Length' => data.bytesize
|
124
|
-
)
|
125
|
-
unless meta.empty?
|
126
|
-
hdrs = hdrs.merge('X-Zerocracy-Meta' => meta.map { |v| Base64.encode64(v).delete("\n") }.join(' '))
|
127
|
-
end
|
128
|
-
params = {
|
129
|
-
connecttimeout: @timeout,
|
130
|
-
timeout: @timeout,
|
131
|
-
body: data,
|
132
|
-
headers: hdrs
|
133
|
-
}
|
134
104
|
elapsed(@loog) do
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
)
|
142
|
-
)
|
143
|
-
|
144
|
-
|
145
|
-
|
105
|
+
Tempfile.open do |file|
|
106
|
+
File.binwrite(file.path, data)
|
107
|
+
upload(
|
108
|
+
home.append('push').append(name),
|
109
|
+
file.path,
|
110
|
+
headers.merge(
|
111
|
+
'X-Zerocracy-Meta' => meta.map { |v| Base64.encode64(v).delete("\n") }.join(' ')
|
112
|
+
),
|
113
|
+
chunk_size:
|
114
|
+
)
|
115
|
+
end
|
116
|
+
throw :"Pushed #{data.bytesize} bytes to #{@host}"
|
146
117
|
end
|
147
|
-
id
|
148
118
|
end
|
149
119
|
|
150
120
|
# Pull factbase from the server for a specific job.
|
@@ -158,7 +128,7 @@ class BazaRb
|
|
158
128
|
data = ''
|
159
129
|
elapsed(@loog) do
|
160
130
|
Tempfile.open do |file|
|
161
|
-
download(home.append('pull').append("#{id}.fb")
|
131
|
+
download(home.append('pull').append("#{id}.fb"), file.path)
|
162
132
|
data = File.binread(file)
|
163
133
|
throw :"Pulled #{data.bytesize} bytes of job ##{id} factbase at #{@host}"
|
164
134
|
end
|
@@ -176,15 +146,7 @@ class BazaRb
|
|
176
146
|
raise 'The ID of the job must be a positive integer' unless id.positive?
|
177
147
|
fin = false
|
178
148
|
elapsed(@loog) do
|
179
|
-
ret =
|
180
|
-
retry_it do
|
181
|
-
checked(
|
182
|
-
Typhoeus::Request.get(
|
183
|
-
home.append('finished').append(id).to_s,
|
184
|
-
headers:
|
185
|
-
)
|
186
|
-
)
|
187
|
-
end
|
149
|
+
ret = get(home.append('finished').append(id))
|
188
150
|
fin = ret.body == 'yes'
|
189
151
|
throw :"The job ##{id} is #{'not yet ' unless fin}finished at #{@host}#{" (#{ret.body.inspect})" unless fin}"
|
190
152
|
end
|
@@ -195,20 +157,13 @@ class BazaRb
|
|
195
157
|
#
|
196
158
|
# @param [Integer] id The ID of the job on the server
|
197
159
|
# @return [String] The stdout, as a text
|
160
|
+
# @raise [ServerFailure] If the job doesn't exist or retrieval fails
|
198
161
|
def stdout(id)
|
199
162
|
raise 'The ID of the job is nil' if id.nil?
|
200
163
|
raise 'The ID of the job must be a positive integer' unless id.positive?
|
201
164
|
stdout = ''
|
202
165
|
elapsed(@loog) do
|
203
|
-
ret =
|
204
|
-
retry_it do
|
205
|
-
checked(
|
206
|
-
Typhoeus::Request.get(
|
207
|
-
home.append('stdout').append("#{id}.txt").to_s,
|
208
|
-
headers:
|
209
|
-
)
|
210
|
-
)
|
211
|
-
end
|
166
|
+
ret = get(home.append('stdout').append("#{id}.txt"))
|
212
167
|
stdout = ret.body
|
213
168
|
throw :"The stdout of the job ##{id} has #{stdout.split("\n").count} lines"
|
214
169
|
end
|
@@ -219,20 +174,13 @@ class BazaRb
|
|
219
174
|
#
|
220
175
|
# @param [Integer] id The ID of the job on the server
|
221
176
|
# @return [Integer] The exit code
|
177
|
+
# @raise [ServerFailure] If the job doesn't exist or retrieval fails
|
222
178
|
def exit_code(id)
|
223
179
|
raise 'The ID of the job is nil' if id.nil?
|
224
180
|
raise 'The ID of the job must be a positive integer' unless id.positive?
|
225
181
|
code = 0
|
226
182
|
elapsed(@loog) do
|
227
|
-
ret =
|
228
|
-
retry_it do
|
229
|
-
checked(
|
230
|
-
Typhoeus::Request.get(
|
231
|
-
home.append('exit').append("#{id}.txt").to_s,
|
232
|
-
headers:
|
233
|
-
)
|
234
|
-
)
|
235
|
-
end
|
183
|
+
ret = get(home.append('exit').append("#{id}.txt"))
|
236
184
|
code = ret.body.to_i
|
237
185
|
throw :"The exit code of the job ##{id} is #{code}"
|
238
186
|
end
|
@@ -243,20 +191,13 @@ class BazaRb
|
|
243
191
|
#
|
244
192
|
# @param [Integer] id The ID of the job on the server
|
245
193
|
# @return [String] The verdict
|
194
|
+
# @raise [ServerFailure] If the job doesn't exist or retrieval fails
|
246
195
|
def verified(id)
|
247
196
|
raise 'The ID of the job is nil' if id.nil?
|
248
197
|
raise 'The ID of the job must be a positive integer' unless id.positive?
|
249
198
|
verdict = ''
|
250
199
|
elapsed(@loog) do
|
251
|
-
ret =
|
252
|
-
retry_it do
|
253
|
-
checked(
|
254
|
-
Typhoeus::Request.get(
|
255
|
-
home.append('jobs').append(id).append('verified.txt').to_s,
|
256
|
-
headers:
|
257
|
-
)
|
258
|
-
)
|
259
|
-
end
|
200
|
+
ret = get(home.append('jobs').append(id).append('verified.txt'))
|
260
201
|
verdict = ret.body
|
261
202
|
throw :"The verdict of the job ##{id} is #{verdict.inspect}"
|
262
203
|
end
|
@@ -267,21 +208,18 @@ class BazaRb
|
|
267
208
|
#
|
268
209
|
# @param [String] name The name of the job on the server
|
269
210
|
# @param [String] owner The owner of the lock (any string)
|
211
|
+
# @raise [RuntimeError] If the name is already locked
|
212
|
+
# @raise [ServerFailure] If the lock operation fails
|
270
213
|
def lock(name, owner)
|
271
214
|
raise 'The "name" of the job is nil' if name.nil?
|
272
215
|
raise 'The "name" of the job may not be empty' if name.empty?
|
273
216
|
raise 'The "owner" of the lock is nil' if owner.nil?
|
274
217
|
elapsed(@loog) do
|
275
|
-
ret =
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
headers:
|
281
|
-
),
|
282
|
-
[302, 409]
|
283
|
-
)
|
284
|
-
end
|
218
|
+
ret = post(
|
219
|
+
home.append('lock').append(name),
|
220
|
+
{ 'owner' => owner },
|
221
|
+
[302, 409]
|
222
|
+
)
|
285
223
|
throw :"Job name '#{name}' locked at #{@host}" if ret.code == 302
|
286
224
|
raise "Failed to lock '#{name}' job at #{@host}, it's already locked"
|
287
225
|
end
|
@@ -291,21 +229,17 @@ class BazaRb
|
|
291
229
|
#
|
292
230
|
# @param [String] name The name of the job on the server
|
293
231
|
# @param [String] owner The owner of the lock (any string)
|
232
|
+
# @raise [ServerFailure] If the unlock operation fails
|
294
233
|
def unlock(name, owner)
|
295
234
|
raise 'The "name" of the job is nil' if name.nil?
|
296
235
|
raise 'The "name" of the job may not be empty' if name.empty?
|
297
236
|
raise 'The "owner" of the lock is nil' if owner.nil?
|
298
237
|
raise 'The "owner" of the lock may not be empty' if owner.empty?
|
299
238
|
elapsed(@loog) do
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
headers:
|
305
|
-
),
|
306
|
-
302
|
307
|
-
)
|
308
|
-
end
|
239
|
+
post(
|
240
|
+
home.append('unlock').append(name),
|
241
|
+
{ 'owner' => owner }
|
242
|
+
)
|
309
243
|
throw :"Job name '#{name}' unlocked at #{@host}"
|
310
244
|
end
|
311
245
|
end
|
@@ -314,20 +248,13 @@ class BazaRb
|
|
314
248
|
#
|
315
249
|
# @param [String] name The name of the job on the server
|
316
250
|
# @return [Integer] The ID of the job on the server
|
251
|
+
# @raise [ServerFailure] If the job doesn't exist or retrieval fails
|
317
252
|
def recent(name)
|
318
253
|
raise 'The "name" of the job is nil' if name.nil?
|
319
254
|
raise 'The "name" of the job may not be empty' if name.empty?
|
320
255
|
job = nil
|
321
256
|
elapsed(@loog) do
|
322
|
-
ret =
|
323
|
-
retry_it do
|
324
|
-
checked(
|
325
|
-
Typhoeus::Request.get(
|
326
|
-
home.append('recent').append("#{name}.txt").to_s,
|
327
|
-
headers:
|
328
|
-
)
|
329
|
-
)
|
330
|
-
end
|
257
|
+
ret = get(home.append('recent').append("#{name}.txt"))
|
331
258
|
job = ret.body.to_i
|
332
259
|
throw :"The recent \"#{name}\" job's ID is ##{job} at #{@host}"
|
333
260
|
end
|
@@ -343,15 +270,7 @@ class BazaRb
|
|
343
270
|
raise 'The "name" of the job may not be empty' if name.empty?
|
344
271
|
exists = false
|
345
272
|
elapsed(@loog) do
|
346
|
-
ret =
|
347
|
-
retry_it do
|
348
|
-
checked(
|
349
|
-
Typhoeus::Request.get(
|
350
|
-
home.append('exists').append(name).to_s,
|
351
|
-
headers:
|
352
|
-
)
|
353
|
-
)
|
354
|
-
end
|
273
|
+
ret = get(home.append('exists').append(name))
|
355
274
|
exists = ret.body == 'yes'
|
356
275
|
throw :"The name \"#{name}\" #{exists ? 'exists' : "doesn't exist"} at #{@host}"
|
357
276
|
end
|
@@ -362,36 +281,33 @@ class BazaRb
|
|
362
281
|
#
|
363
282
|
# @param [String] jname The name of the job on the server
|
364
283
|
# @param [String] file The path to the file to upload
|
284
|
+
# @param [Integer] chunk_size Maximum size of one chunk
|
365
285
|
# @return [Integer] The ID of the created durable
|
366
286
|
# @raise [ServerFailure] If the upload fails
|
367
|
-
def durable_place(jname, file)
|
287
|
+
def durable_place(jname, file, chunk_size: 1_000_000)
|
368
288
|
raise 'The "jname" of the durable is nil' if jname.nil?
|
369
289
|
raise 'The "jname" of the durable may not be empty' if jname.empty?
|
370
290
|
raise 'The "file" of the durable is nil' if file.nil?
|
371
291
|
raise "The file '#{file}' is absent" unless File.exist?(file)
|
372
292
|
id = nil
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
timeout: @timeout
|
388
|
-
),
|
389
|
-
302
|
390
|
-
)
|
391
|
-
end
|
392
|
-
id = ret.headers['X-Zerocracy-DurableId'].to_i
|
393
|
-
throw :"Durable ##{id} (#{file}) placed for job \"#{jname}\" at #{@host}"
|
293
|
+
Tempfile.open do |f|
|
294
|
+
File.write(f.path, 'placeholder')
|
295
|
+
elapsed(@loog) do
|
296
|
+
ret = post(
|
297
|
+
home.append('durables').append('place'),
|
298
|
+
{
|
299
|
+
'jname' => jname,
|
300
|
+
'file' => File.basename(file),
|
301
|
+
'zip' => File.open(f, 'rb')
|
302
|
+
}
|
303
|
+
)
|
304
|
+
id = ret.headers['X-Zerocracy-DurableId'].to_i
|
305
|
+
throw :"Durable ##{id} (#{file}, #{File.size(file)} bytes) placed for job \"#{jname}\" at #{@host}"
|
306
|
+
end
|
394
307
|
end
|
308
|
+
durable_lock(id, user_agent)
|
309
|
+
durable_save(id, file, chunk_size:)
|
310
|
+
durable_unlock(id, user_agent)
|
395
311
|
id
|
396
312
|
end
|
397
313
|
|
@@ -399,23 +315,15 @@ class BazaRb
|
|
399
315
|
#
|
400
316
|
# @param [Integer] id The ID of the durable
|
401
317
|
# @param [String] file The file to upload
|
402
|
-
|
318
|
+
# @param [Integer] chunk_size Maximum size of one chunk
|
319
|
+
# @raise [ServerFailure] If the save operation fails
|
320
|
+
def durable_save(id, file, chunk_size: 1_000_000)
|
403
321
|
raise 'The ID of the durable is nil' if id.nil?
|
404
322
|
raise 'The ID of the durable must be a positive integer' unless id.positive?
|
405
323
|
raise 'The "file" of the durable is nil' if file.nil?
|
406
324
|
raise "The file '#{file}' is absent" unless File.exist?(file)
|
407
325
|
elapsed(@loog) do
|
408
|
-
|
409
|
-
checked(
|
410
|
-
Typhoeus::Request.put(
|
411
|
-
home.append('durables').append(id).to_s,
|
412
|
-
body: File.binread(file),
|
413
|
-
headers:,
|
414
|
-
connecttimeout: @timeout,
|
415
|
-
timeout: @timeout
|
416
|
-
)
|
417
|
-
)
|
418
|
-
end
|
326
|
+
upload(home.append('durables').append(id), file, chunk_size:)
|
419
327
|
throw :"Durable ##{id} saved #{File.size(file)} bytes to #{@host}"
|
420
328
|
end
|
421
329
|
end
|
@@ -423,13 +331,14 @@ class BazaRb
|
|
423
331
|
# Load a single durable from server to local file.
|
424
332
|
#
|
425
333
|
# @param [Integer] id The ID of the durable
|
426
|
-
# @param [String] file The file to
|
334
|
+
# @param [String] file The local file path to save the downloaded durable
|
335
|
+
# @raise [ServerFailure] If the load operation fails
|
427
336
|
def durable_load(id, file)
|
428
337
|
raise 'The ID of the durable is nil' if id.nil?
|
429
338
|
raise 'The ID of the durable must be a positive integer' unless id.positive?
|
430
339
|
raise 'The "file" of the durable is nil' if file.nil?
|
431
340
|
elapsed(@loog) do
|
432
|
-
download(home.append('durables').append(id)
|
341
|
+
download(home.append('durables').append(id), file)
|
433
342
|
throw :"Durable ##{id} loaded #{File.size(file)} bytes from #{@host}"
|
434
343
|
end
|
435
344
|
end
|
@@ -438,21 +347,17 @@ class BazaRb
|
|
438
347
|
#
|
439
348
|
# @param [Integer] id The ID of the durable
|
440
349
|
# @param [String] owner The owner of the lock
|
350
|
+
# @raise [ServerFailure] If the lock operation fails
|
441
351
|
def durable_lock(id, owner)
|
442
352
|
raise 'The ID of the durable is nil' if id.nil?
|
443
353
|
raise 'The ID of the durable must be a positive integer' unless id.positive?
|
444
354
|
raise 'The "owner" of the lock is nil' if owner.nil?
|
445
355
|
raise 'The "owner" of the lock may not be empty' if owner.empty?
|
446
356
|
elapsed(@loog) do
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
headers:
|
452
|
-
),
|
453
|
-
302
|
454
|
-
)
|
455
|
-
end
|
357
|
+
post(
|
358
|
+
home.append('durables').append(id).append('lock'),
|
359
|
+
{ 'owner' => owner }
|
360
|
+
)
|
456
361
|
throw :"Durable ##{id} locked at #{@host}"
|
457
362
|
end
|
458
363
|
end
|
@@ -461,21 +366,17 @@ class BazaRb
|
|
461
366
|
#
|
462
367
|
# @param [Integer] id The ID of the durable
|
463
368
|
# @param [String] owner The owner of the lock
|
369
|
+
# @raise [ServerFailure] If the unlock operation fails
|
464
370
|
def durable_unlock(id, owner)
|
465
371
|
raise 'The ID of the durable is nil' if id.nil?
|
466
372
|
raise 'The ID of the durable must be a positive integer' unless id.positive?
|
467
373
|
raise 'The "owner" of the lock is nil' if owner.nil?
|
468
374
|
raise 'The "owner" of the lock may not be empty' if owner.empty?
|
469
375
|
elapsed(@loog) do
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
headers:
|
475
|
-
),
|
476
|
-
302
|
477
|
-
)
|
478
|
-
end
|
376
|
+
post(
|
377
|
+
home.append('durables').append(id).append('unlock'),
|
378
|
+
{ 'owner' => owner }
|
379
|
+
)
|
479
380
|
throw :"Durable ##{id} unlocked at #{@host}"
|
480
381
|
end
|
481
382
|
end
|
@@ -492,16 +393,7 @@ class BazaRb
|
|
492
393
|
raise 'The "file" may not be empty' if file.empty?
|
493
394
|
id = nil
|
494
395
|
elapsed(@loog) do
|
495
|
-
ret =
|
496
|
-
retry_it do
|
497
|
-
checked(
|
498
|
-
Typhoeus::Request.get(
|
499
|
-
home.append('durables').append('find').add(jname:, file:).to_s,
|
500
|
-
headers:
|
501
|
-
),
|
502
|
-
[200, 404]
|
503
|
-
)
|
504
|
-
end
|
396
|
+
ret = get(home.append('durables').append('find').add(jname:, file:), [200, 404])
|
505
397
|
if ret.code == 200
|
506
398
|
id = ret.body.to_i
|
507
399
|
throw :"Found durable ##{id} for job \"#{jname}\" file \"#{file}\" at #{@host}"
|
@@ -527,26 +419,16 @@ class BazaRb
|
|
527
419
|
raise 'The "summary" is nil' if summary.nil?
|
528
420
|
id = nil
|
529
421
|
body = {
|
530
|
-
'_csrf' => csrf,
|
531
422
|
'human' => recipient,
|
532
423
|
'amount' => format('%0.6f', amount),
|
533
424
|
'summary' => summary
|
534
425
|
}
|
535
426
|
body['job'] = job unless job.nil?
|
536
427
|
elapsed(@loog) do
|
537
|
-
ret =
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
home.append('account').append('transfer').to_s,
|
542
|
-
body:,
|
543
|
-
headers:,
|
544
|
-
connecttimeout: @timeout,
|
545
|
-
timeout: @timeout
|
546
|
-
),
|
547
|
-
302
|
548
|
-
)
|
549
|
-
end
|
428
|
+
ret = post(
|
429
|
+
home.append('account').append('transfer'),
|
430
|
+
body
|
431
|
+
)
|
550
432
|
id = ret.headers['X-Zerocracy-ReceiptId'].to_i
|
551
433
|
throw :"Transferred Ƶ#{format('%0.6f', amount)} to @#{recipient} at #{@host}"
|
552
434
|
end
|
@@ -569,27 +451,16 @@ class BazaRb
|
|
569
451
|
raise 'The "job" must be Integer' unless job.is_a?(Integer)
|
570
452
|
raise 'The "summary" is nil' if summary.nil?
|
571
453
|
id = nil
|
572
|
-
body = {
|
573
|
-
'_csrf' => csrf,
|
574
|
-
'tab' => tab,
|
575
|
-
'amount' => format('%0.6f', amount),
|
576
|
-
'summary' => summary,
|
577
|
-
'job' => job.to_s
|
578
|
-
}
|
579
454
|
elapsed(@loog) do
|
580
|
-
ret =
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
),
|
590
|
-
302
|
591
|
-
)
|
592
|
-
end
|
455
|
+
ret = post(
|
456
|
+
home.append('account').append('fee'),
|
457
|
+
{
|
458
|
+
'tab' => tab,
|
459
|
+
'amount' => format('%0.6f', amount),
|
460
|
+
'summary' => summary,
|
461
|
+
'job' => job.to_s
|
462
|
+
}
|
463
|
+
)
|
593
464
|
id = ret.headers['X-Zerocracy-ReceiptId'].to_i
|
594
465
|
throw :"Fee Ƶ#{format('%0.6f', amount)} paid at #{@host}"
|
595
466
|
end
|
@@ -606,16 +477,7 @@ class BazaRb
|
|
606
477
|
success = false
|
607
478
|
elapsed(@loog) do
|
608
479
|
uri = home.append('pop').add(owner:)
|
609
|
-
ret =
|
610
|
-
retry_it do
|
611
|
-
checked(
|
612
|
-
Typhoeus::Request.get(
|
613
|
-
uri.to_s,
|
614
|
-
headers:
|
615
|
-
),
|
616
|
-
[200, 204, 206]
|
617
|
-
)
|
618
|
-
end
|
480
|
+
ret = get(uri, [204, 302])
|
619
481
|
if ret.code == 204
|
620
482
|
FileUtils.rm_f(zip)
|
621
483
|
throw :"Nothing to pop at #{uri}"
|
@@ -641,20 +503,7 @@ class BazaRb
|
|
641
503
|
raise 'The "zip" of the job is nil' if zip.nil?
|
642
504
|
raise "The 'zip' file is absent: #{zip}" unless File.exist?(zip)
|
643
505
|
elapsed(@loog) do
|
644
|
-
|
645
|
-
checked(
|
646
|
-
Typhoeus::Request.put(
|
647
|
-
home.append('finish').add(id:).to_s,
|
648
|
-
connecttimeout: @timeout,
|
649
|
-
timeout: @timeout,
|
650
|
-
body: File.binread(zip),
|
651
|
-
headers: headers.merge(
|
652
|
-
'Content-Type' => 'application/octet-stream',
|
653
|
-
'Content-Length' => File.size(zip)
|
654
|
-
)
|
655
|
-
)
|
656
|
-
)
|
657
|
-
end
|
506
|
+
upload(home.append('finish').add(id:), zip)
|
658
507
|
throw :"Pushed #{File.size(zip)} bytes to #{@host}, finished job ##{id}"
|
659
508
|
end
|
660
509
|
end
|
@@ -675,30 +524,19 @@ class BazaRb
|
|
675
524
|
def enter(name, badge, why, job)
|
676
525
|
elapsed(@loog, intro: "Entered valve #{badge} to #{name}") do
|
677
526
|
retry_it do
|
678
|
-
ret =
|
679
|
-
Typhoeus::Request.get(
|
680
|
-
home.append('valves').append('result').add(badge:).to_s,
|
681
|
-
headers:
|
682
|
-
),
|
683
|
-
[200, 204]
|
684
|
-
)
|
527
|
+
ret = get(home.append('valves').append('result').add(badge:), [200, 204])
|
685
528
|
return ret.body if ret.code == 200
|
686
529
|
r = yield
|
687
530
|
uri = home.append('valves').append('add')
|
688
531
|
uri = uri.add(job:) unless job.nil?
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
'result' => r.to_s
|
698
|
-
},
|
699
|
-
headers:
|
700
|
-
),
|
701
|
-
302
|
532
|
+
post(
|
533
|
+
uri,
|
534
|
+
{
|
535
|
+
'name' => name,
|
536
|
+
'badge' => badge,
|
537
|
+
'why' => why,
|
538
|
+
'result' => r.to_s
|
539
|
+
}
|
702
540
|
)
|
703
541
|
r
|
704
542
|
end
|
@@ -715,15 +553,7 @@ class BazaRb
|
|
715
553
|
def csrf
|
716
554
|
token = nil
|
717
555
|
elapsed(@loog) do
|
718
|
-
|
719
|
-
token = checked(
|
720
|
-
Typhoeus::Request.get(
|
721
|
-
home.append('csrf').to_s,
|
722
|
-
headers:
|
723
|
-
),
|
724
|
-
200
|
725
|
-
).body
|
726
|
-
end
|
556
|
+
token = get(home.append('csrf')).body
|
727
557
|
throw :"CSRF token retrieved (#{token.length} chars)"
|
728
558
|
end
|
729
559
|
token
|
@@ -731,16 +561,44 @@ class BazaRb
|
|
731
561
|
|
732
562
|
private
|
733
563
|
|
564
|
+
# Get the user agent string for HTTP requests.
|
565
|
+
#
|
566
|
+
# @return [String] The user agent string
|
567
|
+
def user_agent
|
568
|
+
"baza.rb #{BazaRb::VERSION}"
|
569
|
+
end
|
570
|
+
|
571
|
+
# Get default headers for HTTP requests.
|
572
|
+
#
|
573
|
+
# @return [Hash] The default headers including User-Agent, Connection, and authentication token
|
734
574
|
def headers
|
735
575
|
{
|
736
|
-
'User-Agent' =>
|
576
|
+
'User-Agent' => user_agent,
|
737
577
|
'Connection' => 'close',
|
738
578
|
'X-Zerocracy-Token' => @token
|
739
579
|
}
|
740
580
|
end
|
741
581
|
|
582
|
+
# Decompress gzipped data.
|
583
|
+
#
|
584
|
+
# @param [String] data The gzipped data to decompress
|
585
|
+
# @return [String] The decompressed data
|
586
|
+
def unzip(data)
|
587
|
+
io = StringIO.new(data)
|
588
|
+
gz = Zlib::GzipReader.new(io)
|
589
|
+
gz.read
|
590
|
+
end
|
591
|
+
|
592
|
+
# Compress request parameters with gzip.
|
593
|
+
#
|
594
|
+
# @param [Hash] params The request parameters with :body and :headers keys
|
595
|
+
# @return [Hash] The modified parameters with compressed body and updated headers
|
742
596
|
def zipped(params)
|
743
|
-
|
597
|
+
io = StringIO.new
|
598
|
+
gz = Zlib::GzipWriter.new(io)
|
599
|
+
gz.write(params.fetch(:body))
|
600
|
+
gz.close
|
601
|
+
body = io.string
|
744
602
|
headers = params
|
745
603
|
.fetch(:headers)
|
746
604
|
.merge(
|
@@ -753,15 +611,9 @@ class BazaRb
|
|
753
611
|
params.merge(body:, headers:)
|
754
612
|
end
|
755
613
|
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
gz = Zlib::GzipWriter.new(io)
|
760
|
-
gz.write(data)
|
761
|
-
gz.close
|
762
|
-
end
|
763
|
-
end
|
764
|
-
|
614
|
+
# Build the base URI for API requests.
|
615
|
+
#
|
616
|
+
# @return [Iri] The base URI object
|
765
617
|
def home
|
766
618
|
Iri.new('')
|
767
619
|
.host(@host)
|
@@ -769,6 +621,10 @@ class BazaRb
|
|
769
621
|
.scheme(@ssl ? 'https' : 'http')
|
770
622
|
end
|
771
623
|
|
624
|
+
# Execute a block with retries on timeout.
|
625
|
+
#
|
626
|
+
# @yield The block to execute with retries
|
627
|
+
# @return [Object] The result of the block execution
|
772
628
|
def retry_it(&)
|
773
629
|
with_retries(max_tries: @retries, rescue: TimedOut, &)
|
774
630
|
end
|
@@ -821,48 +677,168 @@ class BazaRb
|
|
821
677
|
raise ServerFailure, msg
|
822
678
|
end
|
823
679
|
|
824
|
-
#
|
825
|
-
#
|
826
|
-
# @param [
|
680
|
+
# Make a GET request.
|
681
|
+
#
|
682
|
+
# @param [Iri] uri The URI to send the request to
|
683
|
+
# @param [Array<Integer>] allowed List of allowed HTTP response codes
|
684
|
+
# @return [Typhoeus::Response] The HTTP response
|
685
|
+
# @raise [ServerFailure] If the response code is not in the allowed list
|
686
|
+
def get(uri, allowed = [200])
|
687
|
+
retry_it do
|
688
|
+
checked(
|
689
|
+
Typhoeus::Request.get(
|
690
|
+
uri.to_s,
|
691
|
+
headers:,
|
692
|
+
connecttimeout: @timeout,
|
693
|
+
timeout: @timeout
|
694
|
+
),
|
695
|
+
allowed
|
696
|
+
)
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
# Make a POST request.
|
701
|
+
#
|
702
|
+
# @param [Iri] uri The URI to send the request to
|
703
|
+
# @param [Hash] params The request parameters to send in the body
|
704
|
+
# @param [Array<Integer>] allowed List of allowed HTTP response codes
|
705
|
+
# @return [Typhoeus::Response] The HTTP response
|
706
|
+
# @raise [ServerFailure] If the response code is not in the allowed list
|
707
|
+
def post(uri, params, allowed = [302])
|
708
|
+
retry_it do
|
709
|
+
checked(
|
710
|
+
Typhoeus::Request.post(
|
711
|
+
uri.to_s,
|
712
|
+
body: params.merge('_csrf' => csrf),
|
713
|
+
headers:,
|
714
|
+
connecttimeout: @timeout,
|
715
|
+
timeout: @timeout
|
716
|
+
),
|
717
|
+
allowed
|
718
|
+
)
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
# Download file via GET, using range requests for large files.
|
723
|
+
#
|
724
|
+
# @param [Iri] uri The URI to download from
|
725
|
+
# @param [String] file The local file path to save to
|
726
|
+
# @raise [ServerFailure] If the download fails
|
827
727
|
def download(uri, file)
|
828
|
-
raise 'The "file" is nil' if file.nil?
|
829
728
|
FileUtils.mkdir_p(File.dirname(file))
|
729
|
+
FileUtils.rm_f(file)
|
730
|
+
chunk = 0
|
731
|
+
elapsed(@loog) do
|
732
|
+
pos = 0
|
733
|
+
loop do
|
734
|
+
request = Typhoeus::Request.new(
|
735
|
+
uri.to_s,
|
736
|
+
method: :get,
|
737
|
+
headers: headers.merge(
|
738
|
+
'Accept' => 'application/octet-stream',
|
739
|
+
'Accept-Encoding' => 'gzip',
|
740
|
+
'Range' => "bytes=#{pos}-"
|
741
|
+
),
|
742
|
+
connecttimeout: @timeout,
|
743
|
+
timeout: @timeout
|
744
|
+
)
|
745
|
+
slice = ''
|
746
|
+
request.on_body do |data|
|
747
|
+
slice = data
|
748
|
+
end
|
749
|
+
retry_it do
|
750
|
+
request.run
|
751
|
+
end
|
752
|
+
ret = request.response
|
753
|
+
msg = [
|
754
|
+
"GET #{uri.to_uri.path} #{ret.code}",
|
755
|
+
"#{slice.bytesize} bytes",
|
756
|
+
('in gzip' if ret.headers['Content-Encoding'] == 'gzip'),
|
757
|
+
("ranged as #{ret.headers['Content-Range'].inspect}" if ret.headers['Content-Range'])
|
758
|
+
]
|
759
|
+
checked(ret, [200, 206])
|
760
|
+
if ret.headers['Content-Encoding'] == 'gzip'
|
761
|
+
slice = unzip(slice)
|
762
|
+
msg << "unzipped to #{slice.bytesize} bytes"
|
763
|
+
end
|
764
|
+
File.open(file, 'ab') do |f|
|
765
|
+
f.write(slice)
|
766
|
+
end
|
767
|
+
@loog.debug(msg.compact.join(', '))
|
768
|
+
break if ret.code == 200
|
769
|
+
_, v = ret.headers['Content-Range'].split
|
770
|
+
range, total = v.split('/')
|
771
|
+
raise "Total size is not valid (#{total.inspect})" unless total.match?(/^\*|[0-9]+$/)
|
772
|
+
_b, e = range.split('-')
|
773
|
+
raise "Range is not valid (#{range.inspect})" unless e.match?(/^[0-9]+$/)
|
774
|
+
len = ret.headers['Content-Length'].to_i
|
775
|
+
pos = e.to_i
|
776
|
+
pos += 1 unless len.zero?
|
777
|
+
break if e.to_i == total.to_i - 1
|
778
|
+
chunk += 1
|
779
|
+
sleep(1) if len.zero?
|
780
|
+
end
|
781
|
+
throw :"Downloaded #{File.size(file)} bytes in #{chunk + 1} chunks from #{uri}"
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
# Upload file via PUT, using chunked uploads for large files.
|
786
|
+
#
|
787
|
+
# @param [Iri] uri The URI to upload to
|
788
|
+
# @param [String] file The local file path to upload from
|
789
|
+
# @param [Hash] extra Hash of extra HTTP headers to include
|
790
|
+
# @param [Integer] chunk_size Maximum size of each chunk in bytes
|
791
|
+
# @raise [ServerFailure] If the upload fails
|
792
|
+
def upload(uri, file, extra = {}, chunk_size: 1_000_000)
|
793
|
+
params = {
|
794
|
+
connecttimeout: @timeout,
|
795
|
+
timeout: @timeout,
|
796
|
+
headers: headers.merge(extra).merge(
|
797
|
+
'Content-Type' => 'application/octet-stream'
|
798
|
+
)
|
799
|
+
}
|
800
|
+
total = File.size(file)
|
801
|
+
chunk = 0
|
802
|
+
sent = 0
|
830
803
|
elapsed(@loog) do
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
timeout: @timeout
|
842
|
-
)
|
843
|
-
request.on_body do |chunk|
|
844
|
-
f.write(chunk)
|
804
|
+
loop do
|
805
|
+
slice =
|
806
|
+
if total > chunk_size
|
807
|
+
File.open(file, 'rb') do |f|
|
808
|
+
params[:headers]['X-Zerocracy-Chunk'] = chunk.to_s
|
809
|
+
f.seek(chunk_size * chunk)
|
810
|
+
f.read(chunk_size) || ''
|
811
|
+
end
|
812
|
+
else
|
813
|
+
File.binread(file)
|
845
814
|
end
|
815
|
+
params[:body] = slice
|
816
|
+
params[:headers]['Content-Length'] = slice.bytesize
|
817
|
+
params = zipped(params) if @compress
|
818
|
+
ret =
|
846
819
|
retry_it do
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
range, total = v.split('/')
|
854
|
-
raise "Total size is not valid (#{total.inspect})" unless total.match?(/^\*|[0-9]+$/)
|
855
|
-
b, e = range.split('-')
|
856
|
-
raise "Range is not valid (#{range.inspect})" unless e.match?(/^[0-9]+$/)
|
857
|
-
len = ret.headers['Content-Length'].to_i
|
858
|
-
unless len.zero?
|
859
|
-
raise "Range size (#{range.inspect}) is not equal to Content-Length" unless len - 1 == e.to_i - b.to_i
|
860
|
-
raise "Range end (#{range.inspect}) is not equal to #{f.size}" if e.to_i != f.size - 1
|
820
|
+
checked(
|
821
|
+
Typhoeus::Request.put(
|
822
|
+
uri.to_s,
|
823
|
+
params
|
824
|
+
)
|
825
|
+
)
|
861
826
|
end
|
862
|
-
|
863
|
-
|
827
|
+
sent += params[:body].bytesize
|
828
|
+
@loog.debug(
|
829
|
+
[
|
830
|
+
"PUT #{uri.to_uri.path} #{ret.code}",
|
831
|
+
("gzipped #{slice.bytesize} bytes" if params[:headers]['Content-Encoding'] == 'gzip'),
|
832
|
+
"sent #{params[:body].bytesize} bytes",
|
833
|
+
("chunk ##{chunk}" if params[:headers]['X-Zerocracy-Chunk']),
|
834
|
+
('no chunks' unless params[:headers]['X-Zerocracy-Chunk'])
|
835
|
+
].compact.join(', ')
|
836
|
+
)
|
837
|
+
break if slice.empty?
|
838
|
+
break if total <= chunk_size
|
839
|
+
chunk += 1
|
864
840
|
end
|
865
|
-
throw :"
|
841
|
+
throw :"Uploaded #{sent} bytes to #{uri}#{" in #{chunk + 1} chunks" if chunk.positive?}"
|
866
842
|
end
|
867
843
|
end
|
868
844
|
end
|
data/test/test_baza-rb.rb
CHANGED
@@ -40,7 +40,7 @@ class TestBazaRb < Minitest::Test
|
|
40
40
|
fb.insert.foo = 'test-' * 10_000
|
41
41
|
fb.insert
|
42
42
|
n = fake_name
|
43
|
-
|
43
|
+
LIVE.push(n, fb.export, [])
|
44
44
|
assert(LIVE.name_exists?(n))
|
45
45
|
assert_predicate(LIVE.recent(n), :positive?)
|
46
46
|
id = LIVE.recent(n)
|
@@ -86,15 +86,16 @@ class TestBazaRb < Minitest::Test
|
|
86
86
|
fb.insert.foo = 'test-' * 10_000
|
87
87
|
fb.insert
|
88
88
|
baza = BazaRb.new(HOST, PORT, TOKEN, compress: false)
|
89
|
-
|
89
|
+
baza.push(fake_name, fb.export, [])
|
90
90
|
end
|
91
91
|
|
92
92
|
def test_live_durable_lock_unlock
|
93
93
|
WebMock.enable_net_connect!
|
94
94
|
skip('We are offline') unless we_are_online
|
95
95
|
Dir.mktmpdir do |dir|
|
96
|
-
file = File.join(dir,
|
97
|
-
|
96
|
+
file = File.join(dir, 'before.bin')
|
97
|
+
before = 'hello, Джеф!' * 10
|
98
|
+
File.binwrite(file, before)
|
98
99
|
jname = fake_name
|
99
100
|
refute(LIVE.durable_find(jname, File.basename(file)))
|
100
101
|
id = LIVE.durable_place(jname, file)
|
@@ -102,7 +103,12 @@ class TestBazaRb < Minitest::Test
|
|
102
103
|
owner = fake_name
|
103
104
|
LIVE.durable_lock(id, owner)
|
104
105
|
LIVE.durable_load(id, file)
|
106
|
+
assert_equal(before, File.binread(file).force_encoding('UTF-8'))
|
107
|
+
after = 'привет, друг!'
|
108
|
+
File.binwrite(file, after)
|
105
109
|
LIVE.durable_save(id, file)
|
110
|
+
LIVE.durable_load(id, file)
|
111
|
+
assert_equal(after, File.binread(file).force_encoding('UTF-8'))
|
106
112
|
LIVE.durable_unlock(id, owner)
|
107
113
|
end
|
108
114
|
end
|
@@ -169,20 +175,36 @@ class TestBazaRb < Minitest::Test
|
|
169
175
|
|
170
176
|
def test_unlocks_job_by_name
|
171
177
|
WebMock.disable_net_connect!
|
172
|
-
stub_request(:get, 'https://example.org/
|
178
|
+
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
179
|
+
stub_request(:post, %r{https://example.org/unlock/foo}).to_return(status: 302)
|
173
180
|
assert(fake_baza.unlock('foo', 'x'))
|
174
181
|
end
|
175
182
|
|
176
183
|
def test_durable_place
|
177
184
|
WebMock.disable_net_connect!
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
185
|
+
[fake_baza(compress: true), fake_baza(compress: false)].each do |baza|
|
186
|
+
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
187
|
+
stub_request(:post, 'https://example.org/durables/place').to_return(
|
188
|
+
status: 302, headers: { 'X-Zerocracy-DurableId' => '42' }
|
189
|
+
)
|
190
|
+
stub_request(:post, %r{https://example\.org/durables/42/lock})
|
191
|
+
.to_return(status: 302)
|
192
|
+
stub_request(:post, %r{https://example\.org/durables/42/unlock})
|
193
|
+
.to_return(status: 302)
|
194
|
+
stub_request(:put, 'https://example.org/durables/42')
|
195
|
+
.with(headers: { 'X-Zerocracy-Chunk' => '0' })
|
196
|
+
.to_return(status: 200)
|
197
|
+
stub_request(:put, 'https://example.org/durables/42')
|
198
|
+
.with(headers: { 'X-Zerocracy-Chunk' => '1' })
|
199
|
+
.to_return(status: 200)
|
200
|
+
stub_request(:put, 'https://example.org/durables/42')
|
201
|
+
.with(headers: { 'X-Zerocracy-Chunk' => '2' })
|
202
|
+
.to_return(status: 200)
|
203
|
+
Dir.mktmpdir do |dir|
|
204
|
+
file = File.join(dir, 'test.bin')
|
205
|
+
File.binwrite(file, 'hello, world!')
|
206
|
+
assert_equal(42, baza.durable_place('simple', file, chunk_size: 8))
|
207
|
+
end
|
186
208
|
end
|
187
209
|
end
|
188
210
|
|
@@ -191,10 +213,7 @@ class TestBazaRb < Minitest::Test
|
|
191
213
|
stub_request(:put, 'https://example.org/push/simple').to_return(
|
192
214
|
status: 200, body: '42'
|
193
215
|
)
|
194
|
-
|
195
|
-
42,
|
196
|
-
fake_baza.push('simple', 'hello, world!', [])
|
197
|
-
)
|
216
|
+
fake_baza.push('simple', 'hello, world!', [])
|
198
217
|
end
|
199
218
|
|
200
219
|
def test_simple_pop_with_no_job_found
|
@@ -212,9 +231,16 @@ class TestBazaRb < Minitest::Test
|
|
212
231
|
job = 4242
|
213
232
|
stub_request(:get, 'https://example.org/pop')
|
214
233
|
.with(query: { owner: })
|
234
|
+
.to_return(
|
235
|
+
status: 302,
|
236
|
+
headers: { 'X-Zerocracy-JobId' => job },
|
237
|
+
body: ''
|
238
|
+
)
|
239
|
+
stub_request(:get, 'https://example.org/pop')
|
240
|
+
.with(query: { job: })
|
215
241
|
.to_return(
|
216
242
|
status: 206,
|
217
|
-
headers: { 'Content-Range' => 'bytes 0-0/*', '
|
243
|
+
headers: { 'Content-Range' => 'bytes 0-0/*', 'Content-Length' => 0 },
|
218
244
|
body: ''
|
219
245
|
)
|
220
246
|
bin = nil
|
@@ -228,7 +254,6 @@ class TestBazaRb < Minitest::Test
|
|
228
254
|
status: 206,
|
229
255
|
headers: {
|
230
256
|
'Content-Range' => "bytes 0-7/#{bin.size}",
|
231
|
-
'X-Zerocracy-JobId' => job,
|
232
257
|
'Content-Length' => 8
|
233
258
|
},
|
234
259
|
body: bin[0..7]
|
@@ -240,7 +265,6 @@ class TestBazaRb < Minitest::Test
|
|
240
265
|
status: 206,
|
241
266
|
headers: {
|
242
267
|
'Content-Range' => "bytes 8-#{bin.size - 1}/#{bin.size}",
|
243
|
-
'X-Zerocracy-JobId' => job,
|
244
268
|
'Content-Length' => bin.size - 8
|
245
269
|
},
|
246
270
|
body: bin[8..]
|
@@ -305,7 +329,7 @@ class TestBazaRb < Minitest::Test
|
|
305
329
|
def test_simple_pull
|
306
330
|
WebMock.disable_net_connect!
|
307
331
|
stub_request(:get, 'https://example.org/pull/333.fb').to_return(
|
308
|
-
status: 200, body: 'hello, world!'
|
332
|
+
status: 200, body: 'hello, world!', headers: {}
|
309
333
|
)
|
310
334
|
assert(
|
311
335
|
fake_baza.pull(333).start_with?('hello')
|
@@ -314,13 +338,15 @@ class TestBazaRb < Minitest::Test
|
|
314
338
|
|
315
339
|
def test_simple_lock_success
|
316
340
|
WebMock.disable_net_connect!
|
317
|
-
stub_request(:get, 'https://example.org/
|
341
|
+
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
342
|
+
stub_request(:post, %r{https://example.org/lock/name}).to_return(status: 302)
|
318
343
|
fake_baza.lock('name', 'owner')
|
319
344
|
end
|
320
345
|
|
321
346
|
def test_simple_lock_failure
|
322
347
|
WebMock.disable_net_connect!
|
323
|
-
stub_request(:get, 'https://example.org/
|
348
|
+
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
349
|
+
stub_request(:post, %r{https://example.org/lock/name}).to_return(status: 409)
|
324
350
|
assert_raises(StandardError) do
|
325
351
|
fake_baza.lock('name', 'owner')
|
326
352
|
end
|
@@ -434,7 +460,7 @@ class TestBazaRb < Minitest::Test
|
|
434
460
|
file = File.join(dir, 'test.txt')
|
435
461
|
File.write(file, 'test content')
|
436
462
|
stub_request(:put, 'https://example.org:443/durables/42')
|
437
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' }
|
463
|
+
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
438
464
|
.to_return(status: 200)
|
439
465
|
fake_baza.durable_save(42, file)
|
440
466
|
end
|
@@ -446,7 +472,7 @@ class TestBazaRb < Minitest::Test
|
|
446
472
|
file = File.join(dir, 'loaded.txt')
|
447
473
|
stub_request(:get, 'https://example.org:443/durables/42')
|
448
474
|
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
449
|
-
.to_return(status: 200, body: 'loaded content')
|
475
|
+
.to_return(status: 200, body: 'loaded content', headers: {})
|
450
476
|
fake_baza.durable_load(42, file)
|
451
477
|
assert_equal('loaded content', File.read(file))
|
452
478
|
end
|
@@ -454,7 +480,8 @@ class TestBazaRb < Minitest::Test
|
|
454
480
|
|
455
481
|
def test_durable_lock
|
456
482
|
WebMock.disable_net_connect!
|
457
|
-
stub_request(:get, 'https://example.org
|
483
|
+
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
484
|
+
stub_request(:post, %r{https://example.org:443/durables/42/lock})
|
458
485
|
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
459
486
|
.to_return(status: 302)
|
460
487
|
fake_baza.durable_lock(42, 'test-owner')
|
@@ -462,7 +489,8 @@ class TestBazaRb < Minitest::Test
|
|
462
489
|
|
463
490
|
def test_durable_unlock
|
464
491
|
WebMock.disable_net_connect!
|
465
|
-
stub_request(:get, 'https://example.org
|
492
|
+
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
493
|
+
stub_request(:post, %r{https://example.org:443/durables/42/unlock})
|
466
494
|
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
467
495
|
.to_return(status: 302)
|
468
496
|
fake_baza.durable_unlock(42, 'test-owner')
|
@@ -618,8 +646,7 @@ class TestBazaRb < Minitest::Test
|
|
618
646
|
body: 'data'
|
619
647
|
)
|
620
648
|
.to_return(status: 200, body: '123')
|
621
|
-
|
622
|
-
assert_equal(123, id)
|
649
|
+
baza.push('test', 'data', [])
|
623
650
|
end
|
624
651
|
|
625
652
|
private
|
@@ -651,8 +678,8 @@ class TestBazaRb < Minitest::Test
|
|
651
678
|
req
|
652
679
|
end
|
653
680
|
|
654
|
-
def fake_baza
|
655
|
-
BazaRb.new('example.org', 443, '000', loog: Loog::NULL)
|
681
|
+
def fake_baza(compress: true)
|
682
|
+
BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress:)
|
656
683
|
end
|
657
684
|
|
658
685
|
def fake_name
|