Class: Batchwatch::BatchResult
- Inherits:
-
Object
- Object
- Batchwatch::BatchResult
- Defined in:
- lib/batchwatch/job.rb
Overview
The split of a batch into landed / failed / expired (#180).
A real batch is three sets, not one: requests that landed, requests that failed per-request, and requests still outstanding when the 24h expiry hit. Reporting only "completed" loses the last two, which is exactly where silent data loss lives. This object carries the three sets, their counts, and the per-request ids, and - because provider ordering is not guaranteed - is built by mapping on custom_id, never by index.
The measurement rule for a partial job (#180): an expiry is reported with status="expired" (NOT completed, which would pollute p90; NOT failed, which would lose the "queue was slow" signal), a per-request-failed job as completed with the landed count, and a clean job as completed. The client does not invent a fourth reading.
Instance Attribute Summary collapse
-
#expired_ids ⇒ Object
readonly
Returns the value of attribute expired_ids.
-
#failed_ids ⇒ Object
readonly
Returns the value of attribute failed_ids.
-
#job ⇒ Object
readonly
Returns the value of attribute job.
-
#landed_ids ⇒ Object
readonly
Returns the value of attribute landed_ids.
-
#results_by_id ⇒ Object
readonly
Returns the value of attribute results_by_id.
Class Method Summary collapse
-
.from_handle(job) ⇒ Object
Coarse split from the whole-batch terminal status.
-
.from_results(job, results = nil, custom_ids = nil) ⇒ Object
Build the split from per-request outcomes, or from the handle status.
Instance Method Summary collapse
-
#complete? ⇒ Boolean
true only when every submitted request landed.
- #expired ⇒ Object
- #failed ⇒ Object
-
#initialize(job, landed_ids:, failed_ids:, expired_ids:, results_by_id: nil) ⇒ BatchResult
constructor
A new instance of BatchResult.
-
#landed ⇒ Object
---- counts, so a caller can branch without .length on three arrays -------.
-
#result_for(custom_id) ⇒ Object
The caller's own landed result for one custom_id, or nil.
- #total ⇒ Object
Constructor Details
#initialize(job, landed_ids:, failed_ids:, expired_ids:, results_by_id: nil) ⇒ BatchResult
Returns a new instance of BatchResult.
639 640 641 642 643 644 645 646 647 648 |
# File 'lib/batchwatch/job.rb', line 639 def initialize(job, landed_ids:, failed_ids:, expired_ids:, results_by_id: nil) @job = job @landed_ids = landed_ids.dup @failed_ids = failed_ids.dup @expired_ids = expired_ids.dup # The caller's own result objects, keyed by custom_id, for the landed ones # - so map-back is a hash lookup, never a positional zip. @results_by_id = (results_by_id || {}).dup end |
Instance Attribute Details
#expired_ids ⇒ Object (readonly)
Returns the value of attribute expired_ids.
637 638 639 |
# File 'lib/batchwatch/job.rb', line 637 def expired_ids @expired_ids end |
#failed_ids ⇒ Object (readonly)
Returns the value of attribute failed_ids.
637 638 639 |
# File 'lib/batchwatch/job.rb', line 637 def failed_ids @failed_ids end |
#job ⇒ Object (readonly)
Returns the value of attribute job.
637 638 639 |
# File 'lib/batchwatch/job.rb', line 637 def job @job end |
#landed_ids ⇒ Object (readonly)
Returns the value of attribute landed_ids.
637 638 639 |
# File 'lib/batchwatch/job.rb', line 637 def landed_ids @landed_ids end |
#results_by_id ⇒ Object (readonly)
Returns the value of attribute results_by_id.
637 638 639 |
# File 'lib/batchwatch/job.rb', line 637 def results_by_id @results_by_id end |
Class Method Details
.from_handle(job) ⇒ Object
Coarse split from the whole-batch terminal status. For a provider that gives us no per-request lines: an expired handle is all-expired, a non-success terminal handle all-failed, a success all-landed. There are no ids to list at this granularity, so the sets carry a single whole-batch marker each and the counts read 1/0/0-style.
729 730 731 732 733 734 735 736 737 738 739 |
# File 'lib/batchwatch/job.rb', line 729 def self.from_handle(job) handle = job.handle if Batchwatch.default_expired(handle) || job.expired return new(job, landed_ids: [], failed_ids: [], expired_ids: [WHOLE_MARKER]) end if Batchwatch.default_succeeded(handle) return new(job, landed_ids: [WHOLE_MARKER], failed_ids: [], expired_ids: []) end new(job, landed_ids: [], failed_ids: [WHOLE_MARKER], expired_ids: []) end |
.from_results(job, results = nil, custom_ids = nil) ⇒ Object
Build the split from per-request outcomes, or from the handle status.
See BatchJob#split for the argument contract. The per-request path classifies each result line by whether it carries an error, treats any submitted id with no line as expired, and keys the landed results by custom_id. The handle-status fallback reads the whole-batch terminal state for a provider that reports no lines.
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 |
# File 'lib/batchwatch/job.rb', line 689 def self.from_results(job, results = nil, custom_ids = nil) return from_handle(job) if results.nil? && custom_ids.nil? results = Array(results) seen = {} landed = [] failed = [] results.each do |item| cid = Batchwatch.custom_id_of(item) if cid.nil? # A line we cannot map is not silently dropped into "landed" - that # would be the zip-by-index mistake in another guise. It counts as # failed so the caller sees the reconciliation gap. failed << UNMAPPED_MARKER next end seen[cid] = item if Batchwatch.result_error?(item) failed << cid else landed << cid end end # Anything submitted but never returned is outstanding at expiry. submitted = custom_ids.nil? ? seen.keys : Array(custom_ids) expired = submitted.reject { |cid| seen.key?(cid) } results_by_id = {} landed.each { |cid| results_by_id[cid] = seen[cid] unless cid == UNMAPPED_MARKER } new(job, landed_ids: landed.reject { |c| c == UNMAPPED_MARKER }, failed_ids: failed, expired_ids: expired, results_by_id: results_by_id) end |
Instance Method Details
#complete? ⇒ Boolean
true only when every submitted request landed. No silent success: a job with anything failed or outstanding at expiry is NOT complete. This is the method a caller checks before treating the batch as done.
671 672 673 |
# File 'lib/batchwatch/job.rb', line 671 def complete? total > 0 && failed.zero? && expired.zero? end |
#expired ⇒ Object
660 661 662 |
# File 'lib/batchwatch/job.rb', line 660 def expired @expired_ids.length end |
#failed ⇒ Object
656 657 658 |
# File 'lib/batchwatch/job.rb', line 656 def failed @failed_ids.length end |
#landed ⇒ Object
---- counts, so a caller can branch without .length on three arrays -------
652 653 654 |
# File 'lib/batchwatch/job.rb', line 652 def landed @landed_ids.length end |
#result_for(custom_id) ⇒ Object
The caller's own landed result for one custom_id, or nil. The map-back the naive zip gets wrong: a lookup by id, so out-of-order provider results still reach the right caller object.
678 679 680 |
# File 'lib/batchwatch/job.rb', line 678 def result_for(custom_id) @results_by_id[custom_id] end |
#total ⇒ Object
664 665 666 |
# File 'lib/batchwatch/job.rb', line 664 def total landed + failed + expired end |