baza.rb 0.8.0 → 0.9.1

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