Class: BazaRb
- Inherits:
-
Object
- Object
- BazaRb
- Defined in:
- lib/baza-rb.rb,
lib/baza-rb/version.rb
Overview
Just a version.
We keep this file separate from the “baza-rb.rb” in order to have an ability to include it from the “.gemspec” script, without including all other packages (thus failing the build).
- Author
-
Yegor Bugayenko ([email protected])
- Copyright
-
Copyright © 2024-2026 Yegor Bugayenko
- License
-
MIT
Defined Under Namespace
Classes: BadCompression, BadResponse, Fake, ServerFailure, TimedOut
Constant Summary collapse
- DEFAULT_CHUNK_SIZE =
How big are the chunks we send, by default, in bytes. Numbers larger than 1Mb may lead to problems with the server, since sending time will be too long and the server may drop connections. Better keep it as is: 1Mb.
1_000_000- VERSION =
'0.0.0'
Instance Method Summary collapse
-
#balance ⇒ Float
Get current balance of the authenticated user.
-
#csrf ⇒ String
Get CSRF token from the server for authenticated requests.
-
#durable_find(pname, file) ⇒ Integer?
Find a durable by job name and file name.
-
#durable_load(id, file) ⇒ Object
Load a single durable from server to local file.
-
#durable_lock(id, owner) ⇒ Object
Lock a single durable.
-
#durable_place(pname, file) ⇒ Integer
Place a single durable file on the server.
-
#durable_save(id, file, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
Save a single durable from local file to server.
-
#durable_unlock(id, owner) ⇒ Object
Unlock a single durable.
-
#enter(pname, badge, why, job) { ... } ⇒ String
Enter a valve to cache or retrieve a computation result.
-
#exit_code(id) ⇒ Integer
Read and return the exit code of the job.
-
#fee(tab, amount, summary, job) ⇒ Integer
Pay a fee associated with a job.
-
#finish(id, zip) ⇒ Object
Submit a ZIP archive to finish a previously popped job.
-
#finished?(id) ⇒ Boolean
Check if the job with this ID is finished already.
-
#initialize(host, port, token, ssl: true, timeout: 30, retries: 5, pause: 1, loog: Loog::NULL, compress: true) ⇒ BazaRb
constructor
Initialize a new Zerocracy API client.
-
#lock(pname, owner) ⇒ Object
Lock the name.
-
#name_exists?(pname) ⇒ Boolean
Check whether the name of the job exists on the server.
-
#pop(owner, zip) ⇒ Boolean
Pop the next available job from the server’s queue.
-
#pull(id) ⇒ String
Pull factbase from the server for a specific job.
-
#push(pname, data, meta, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
Push factbase to the server to create a new job.
-
#recent(name) ⇒ Integer
Get the ID of the job by the name.
-
#stdout(id) ⇒ String
Read and return the stdout of the job.
-
#transfer(recipient, amount, summary, job: nil) ⇒ Integer
Transfer funds to another user.
-
#unlock(pname, owner) ⇒ Object
Unlock the name.
-
#verified(id) ⇒ String
Read and return the verification verdict of the job.
-
#whoami ⇒ String
Get GitHub login name of the logged in user.
Constructor Details
#initialize(host, port, token, ssl: true, timeout: 30, retries: 5, pause: 1, loog: Loog::NULL, compress: true) ⇒ BazaRb
Initialize a new Zerocracy API client.
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/baza-rb.rb', line 64 def initialize(host, port, token, ssl: true, timeout: 30, retries: 5, pause: 1, loog: Loog::NULL, compress: true) @host = host @port = port @ssl = ssl @token = token @timeout = timeout @loog = loog @retries = retries @pause = pause @compress = compress end |
Instance Method Details
#balance ⇒ Float
Get current balance of the authenticated user.
94 95 96 97 98 99 100 101 102 |
# File 'lib/baza-rb.rb', line 94 def balance z = nil elapsed(@loog, level: Logger::INFO) do ret = get(home.append('account').append('balance')) z = ret.body.to_f throw :"The balance is Ƶ#{z}, at #{@host}" end z end |
#csrf ⇒ String
Get CSRF token from the server for authenticated requests.
The CSRF token is required for POST requests to prevent cross-site request forgery attacks.
572 573 574 575 576 577 578 579 |
# File 'lib/baza-rb.rb', line 572 def csrf token = nil elapsed(@loog, level: Logger::INFO) do token = get(home.append('csrf')).body throw :"CSRF token retrieved (#{token.length} chars)" end token end |
#durable_find(pname, file) ⇒ Integer?
Find a durable by job name and file name.
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/baza-rb.rb', line 407 def durable_find(pname, file) raise 'The "pname" is nil' if pname.nil? raise 'The "pname" may not be empty' if pname.empty? raise 'The "file" is nil' if file.nil? raise 'The "file" may not be empty' if file.empty? id = nil elapsed(@loog, level: Logger::INFO) do ret = get(home.append('durable-find').add(jname: pname, pname:, file:), [200, 404]) if ret.code == 200 id = ret.body.to_i throw :"Found durable ##{id} for job \"#{pname}\" file \"#{file}\" at #{@host}" else throw :"Durable not found for job \"#{pname}\" file \"#{file}\" at #{@host}" end end id end |
#durable_load(id, file) ⇒ Object
Load a single durable from server to local file.
351 352 353 354 355 356 357 358 359 360 |
# File 'lib/baza-rb.rb', line 351 def durable_load(id, file) raise 'The ID of the durable is nil' if id.nil? raise 'The ID of the durable must be an Integer' unless id.is_a?(Integer) raise 'The ID of the durable must be a positive integer' unless id.positive? raise 'The "file" of the durable is nil' if file.nil? elapsed(@loog, level: Logger::INFO) do download(home.append('durables').append(id), file) throw :"Durable ##{id} loaded #{File.size(file)} bytes from #{@host}" end end |
#durable_lock(id, owner) ⇒ Object
Lock a single durable.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/baza-rb.rb', line 367 def durable_lock(id, owner) raise 'The ID of the durable is nil' if id.nil? raise 'The ID of the durable must be an Integer' unless id.is_a?(Integer) raise 'The ID of the durable must be a positive integer' unless id.positive? raise 'The "owner" of the lock is nil' if owner.nil? raise 'The "owner" of the lock may not be empty' if owner.empty? elapsed(@loog, level: Logger::INFO) do post( home.append('durables').append(id).append('lock'), { 'owner' => owner } ) throw :"Durable ##{id} locked at #{@host}" end end |
#durable_place(pname, file) ⇒ Integer
Place a single durable file on the server.
The file provided will only be uploaded to the server if the durable is currently absent. If the durable is present, the file will be ignored. It is expected to use only small placeholder files, not real data.
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/baza-rb.rb', line 303 def durable_place(pname, file) raise 'The "pname" of the durable is nil' if pname.nil? raise 'The "pname" of the durable may not be empty' if pname.empty? raise 'The "file" of the durable is nil' if file.nil? raise "The file '#{file}' is absent" unless File.exist?(file) if File.size(file) > 1024 raise "The file '#{file}' is too big (#{File.size(file)} bytes) for durable_place(), use durable_save() instead" end id = nil elapsed(@loog, level: Logger::INFO) do ret = post( home.append('durable-place'), { 'pname' => pname, 'jname' => pname, 'file' => File.basename(file), 'zip' => File.open(file, 'rb') } ) id = ret.headers['X-Zerocracy-DurableId'].to_i throw :"Durable ##{id} (#{file}, #{File.size(file)} bytes) placed for job \"#{pname}\" at #{@host}" end id end |
#durable_save(id, file, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
Save a single durable from local file to server.
334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/baza-rb.rb', line 334 def durable_save(id, file, chunk_size: DEFAULT_CHUNK_SIZE) raise 'The ID of the durable is nil' if id.nil? raise 'The ID of the durable must be an Integer' unless id.is_a?(Integer) raise 'The ID of the durable must be a positive integer' unless id.positive? raise 'The "file" of the durable is nil' if file.nil? raise "The file '#{file}' is absent" unless File.exist?(file) elapsed(@loog, level: Logger::INFO) do upload(home.append('durables').append(id), file, chunk_size:) throw :"Durable ##{id} saved #{File.size(file)} bytes to #{@host}" end end |
#durable_unlock(id, owner) ⇒ Object
Unlock a single durable.
387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/baza-rb.rb', line 387 def durable_unlock(id, owner) raise 'The ID of the durable is nil' if id.nil? raise 'The ID of the durable must be an Integer' unless id.is_a?(Integer) raise 'The ID of the durable must be a positive integer' unless id.positive? raise 'The "owner" of the lock is nil' if owner.nil? raise 'The "owner" of the lock may not be empty' if owner.empty? elapsed(@loog, level: Logger::INFO) do post( home.append('durables').append(id).append('unlock'), { 'owner' => owner } ) throw :"Durable ##{id} unlocked at #{@host}" end end |
#enter(pname, badge, why, job) { ... } ⇒ String
Enter a valve to cache or retrieve a computation result.
Valves prevent duplicate computations by caching results. If a result for the given badge already exists, it’s returned. Otherwise, the block is executed and its result is cached.
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/baza-rb.rb', line 542 def enter(pname, badge, why, job) elapsed(@loog, good: "Entered valve #{badge} to #{pname}") do retry_it do ret = get(home.append('result').add(badge:), [200, 204]) return ret.body if ret.code == 200 r = yield uri = home.append('valves') uri = uri.add(job:) unless job.nil? post( uri, { 'name' => pname, 'pname' => pname, 'badge' => badge, 'why' => why, 'result' => r.to_s } ) r end end end |
#exit_code(id) ⇒ Integer
Read and return the exit code of the job.
190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/baza-rb.rb', line 190 def exit_code(id) raise 'The ID of the job is nil' if id.nil? raise 'The ID of the job must be a positive integer' unless id.positive? code = 0 elapsed(@loog, level: Logger::INFO) do ret = get(home.append('exit').append("#{id}.txt")) code = ret.body.to_i throw :"The exit code of the job ##{id} is #{code}" end code end |
#fee(tab, amount, summary, job) ⇒ Integer
Pay a fee associated with a job.
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
# File 'lib/baza-rb.rb', line 464 def fee(tab, amount, summary, job) raise 'The "tab" is nil' if tab.nil? raise 'The "amount" is nil' if amount.nil? raise 'The "amount" must be Float' unless amount.is_a?(Float) raise 'The "job" is nil' if job.nil? raise 'The "job" must be Integer' unless job.is_a?(Integer) raise 'The "summary" is nil' if summary.nil? id = nil elapsed(@loog, level: Logger::INFO) do ret = post( home.append('account').append('fee'), { 'tab' => tab, 'amount' => format('%0.6f', amount), 'summary' => summary, 'job' => job.to_s } ) id = ret.headers['X-Zerocracy-ReceiptId'].to_i throw :"Fee Ƶ#{format('%0.6f', amount)} paid at #{@host}" end id end |
#finish(id, zip) ⇒ Object
Submit a ZIP archive to finish a previously popped job.
518 519 520 521 522 523 524 525 526 527 |
# File 'lib/baza-rb.rb', line 518 def finish(id, zip) raise 'The ID of the job is nil' if id.nil? raise 'The ID of the job must be a positive integer' unless id.positive? raise 'The "zip" of the job is nil' if zip.nil? raise "The 'zip' file is absent: #{zip}" unless File.exist?(zip) elapsed(@loog, level: Logger::INFO) do upload(home.append('finish').add(id:), zip) throw :"Pushed #{File.size(zip)} bytes to #{@host}, finished job ##{id}" end end |
#finished?(id) ⇒ Boolean
Check if the job with this ID is finished already.
156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/baza-rb.rb', line 156 def finished?(id) raise 'The ID of the job is nil' if id.nil? raise 'The ID of the job must be a positive integer' unless id.positive? fin = false elapsed(@loog, level: Logger::INFO) do ret = get(home.append('finished').append(id)) fin = ret.body == 'yes' throw :"The job ##{id} is #{'not yet ' unless fin}finished at #{@host}#{" (#{ret.body.inspect})" unless fin}" end fin end |
#lock(pname, owner) ⇒ Object
Lock the name.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/baza-rb.rb', line 225 def lock(pname, owner) raise 'The "pname" of the product is nil' if pname.nil? raise 'The "pname" of the product may not be empty' if pname.empty? raise 'The "owner" of the lock is nil' if owner.nil? elapsed(@loog, level: Logger::INFO) do ret = post( home.append('lock').append(pname), { 'owner' => owner }, [302, 409] ) throw :"Product name #{pname.inspect} locked at #{@host}" if ret.code == 302 raise "Failed to lock #{pname.inspect} product at #{@host}, it's already locked" end end |
#name_exists?(pname) ⇒ Boolean
Check whether the name of the job exists on the server.
280 281 282 283 284 285 286 287 288 289 290 |
# File 'lib/baza-rb.rb', line 280 def name_exists?(pname) raise 'The "pname" of the product is nil' if pname.nil? raise 'The "pname" of the product may not be empty' if pname.empty? exists = false elapsed(@loog, level: Logger::INFO) do ret = get(home.append('exists').append(pname)) exists = ret.body == 'yes' throw :"The name #{pname.inspect} #{exists ? 'exists' : "doesn't exist"} at #{@host}" end exists end |
#pop(owner, zip) ⇒ Boolean
Pop the next available job from the server’s queue.
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 |
# File 'lib/baza-rb.rb', line 494 def pop(owner, zip) success = false elapsed(@loog, level: Logger::INFO) do uri = home.append('pop').add(owner:) ret = get(uri, [204, 302]) if ret.code == 204 FileUtils.rm_f(zip) throw :"Nothing to pop at #{uri}" end job = ret.headers['X-Zerocracy-JobId'] raise 'Job ID is not returned in X-Zerocracy-JobId' if job.nil? raise "Job ID returned in X-Zerocracy-JobId is not valid (#{job.inspect})" unless job.match?(/^[0-9]+$/) download(uri.add(job:), zip) success = true throw :"Popped #{File.size(zip)} bytes in ZIP archive at #{@host}" end success end |
#pull(id) ⇒ String
Pull factbase from the server for a specific job.
137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/baza-rb.rb', line 137 def pull(id) raise 'The ID of the job is nil' if id.nil? raise 'The ID of the job must be a positive integer' unless id.positive? data = '' elapsed(@loog, level: Logger::INFO) do Tempfile.open do |file| download(home.append('pull').append("#{id}.fb"), file.path) data = File.binread(file) throw :"Pulled #{data.bytesize} bytes of job ##{id} factbase at #{@host}" end end data end |
#push(pname, data, meta, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
Push factbase to the server to create a new job.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/baza-rb.rb', line 111 def push(pname, data, , chunk_size: DEFAULT_CHUNK_SIZE) raise 'The "name" of the job is nil' if pname.nil? raise 'The "name" of the job may not be empty' if pname.empty? raise 'The "data" of the job is nil' if data.nil? raise 'The "meta" of the job is nil' if .nil? elapsed(@loog, level: Logger::INFO) do Tempfile.open do |file| File.binwrite(file.path, data) upload( home.append('push').append(pname), file.path, headers.merge( 'X-Zerocracy-Meta' => .map { |v| Base64.encode64(v).delete("\n") }.join(' ') ), chunk_size: ) end throw :"Pushed #{data.bytesize} bytes to #{@host}" end end |
#recent(name) ⇒ Integer
Get the ID of the job by the name.
264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/baza-rb.rb', line 264 def recent(name) raise 'The "name" of the job is nil' if name.nil? raise 'The "name" of the job may not be empty' if name.empty? job = nil elapsed(@loog, level: Logger::INFO) do ret = get(home.append('recent').append("#{name}.txt")) job = ret.body.to_i throw :"The recent \"#{name}\" job's ID is ##{job} at #{@host}" end job end |
#stdout(id) ⇒ String
Read and return the stdout of the job.
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/baza-rb.rb', line 173 def stdout(id) raise 'The ID of the job is nil' if id.nil? raise 'The ID of the job must be a positive integer' unless id.positive? stdout = '' elapsed(@loog, level: Logger::INFO) do ret = get(home.append('stdout').append("#{id}.txt")) stdout = ret.body throw :"The stdout of the job ##{id} has #{stdout.split("\n").count} lines" end stdout end |
#transfer(recipient, amount, summary, job: nil) ⇒ Integer
Transfer funds to another user.
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
# File 'lib/baza-rb.rb', line 433 def transfer(recipient, amount, summary, job: nil) raise 'The "recipient" is nil' if recipient.nil? raise 'The "amount" is nil' if amount.nil? raise 'The "amount" must be Float' unless amount.is_a?(Float) raise 'The "summary" is nil' if summary.nil? id = nil body = { 'human' => recipient, 'amount' => format('%0.6f', amount), 'summary' => summary } body['job'] = job unless job.nil? elapsed(@loog, level: Logger::INFO) do ret = post( home.append('account').append('transfer'), body ) id = ret.headers['X-Zerocracy-ReceiptId'].to_i throw :"Transferred Ƶ#{format('%0.6f', amount)} to @#{recipient} at #{@host}" end id end |
#unlock(pname, owner) ⇒ Object
Unlock the name.
245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/baza-rb.rb', line 245 def unlock(pname, owner) raise 'The "pname" of the job is nil' if pname.nil? raise 'The "pname" of the job may not be empty' if pname.empty? raise 'The "owner" of the lock is nil' if owner.nil? raise 'The "owner" of the lock may not be empty' if owner.empty? elapsed(@loog, level: Logger::INFO) do post( home.append('unlock').append(pname), { 'owner' => owner } ) throw :"Job name #{pname.inspect} unlocked at #{@host}" end end |
#verified(id) ⇒ String
Read and return the verification verdict of the job.
207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/baza-rb.rb', line 207 def verified(id) raise 'The ID of the job is nil' if id.nil? raise 'The ID of the job must be a positive integer' unless id.positive? verdict = '' elapsed(@loog, level: Logger::INFO) do ret = get(home.append('jobs').append(id).append('verified.txt')) verdict = ret.body throw :"The verdict of the job ##{id} is #{verdict.inspect}" end verdict end |
#whoami ⇒ String
Get GitHub login name of the logged in user.
80 81 82 83 84 85 86 87 88 |
# File 'lib/baza-rb.rb', line 80 def whoami nick = nil elapsed(@loog, level: Logger::INFO) do ret = get(home.append('whoami')) nick = ret.body throw :"I know that I am @#{nick}, at #{@host}" end nick end |