Class: Clickwrap::Integrity::AttestationReconciler
- Inherits:
-
Object
- Object
- Clickwrap::Integrity::AttestationReconciler
- Defined in:
- lib/clickwrap/integrity/attestation_reconciler.rb
Overview
Finds committed events for which a configured external integrity adapter never left an attestation row, then asks only for those missing records. This closes the recoverable part of the after-commit crash window: the required evidence remains committed, and an operator can safely discover and retry the optional external work later.
No local database can prove whether a process died immediately before or immediately after a provider accepted a request. Adapters should therefore use the event digest (timestamps) or exact chain snapshot (anchors) as their idempotency key. A retry may otherwise create a second valid provider record; Clickwrap preserves both and never calls that exactly-once delivery.
Defined Under Namespace
Instance Attribute Summary collapse
-
#retry_failed_attestations ⇒ Object
readonly
Returns the value of attribute retry_failed_attestations.
-
#scope ⇒ Object
readonly
Returns the value of attribute scope.
Class Method Summary collapse
- .configured_kinds ⇒ Object
- .eligible_scope(scope, kind) ⇒ Object
- .missing_counts(scope: Event.all) ⇒ Object
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(scope: Event.all, retry_failed_attestations: false) ⇒ AttestationReconciler
constructor
A new instance of AttestationReconciler.
Constructor Details
#initialize(scope: Event.all, retry_failed_attestations: false) ⇒ AttestationReconciler
Returns a new instance of AttestationReconciler.
64 65 66 67 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 64 def initialize(scope: Event.all, retry_failed_attestations: false) @scope = scope @retry_failed_attestations = retry_failed_attestations end |
Instance Attribute Details
#retry_failed_attestations ⇒ Object (readonly)
Returns the value of attribute retry_failed_attestations.
69 70 71 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 69 def retry_failed_attestations @retry_failed_attestations end |
#scope ⇒ Object (readonly)
Returns the value of attribute scope.
69 70 71 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 69 def scope @scope end |
Class Method Details
.configured_kinds ⇒ Object
52 53 54 55 56 57 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 52 def configured_kinds kinds = [] kinds << "third_party_timestamp" if Clickwrap.config. kinds << "event_anchor" if Clickwrap.config.anchor_event_history_with kinds end |
.eligible_scope(scope, kind) ⇒ Object
59 60 61 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 59 def eligible_scope(scope, kind) kind == "event_anchor" ? scope.where.not(chain_scope: nil) : scope end |
.missing_counts(scope: Event.all) ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 44 def missing_counts(scope: Event.all) configured_kinds.to_h do |kind| eligible = eligible_scope(scope, kind) recorded = IntegrityAttestation.where(kind: kind).select(:event_id) [kind, eligible.where.not(id: recorded).count] end end |
Instance Method Details
#call ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/clickwrap/integrity/attestation_reconciler.rb', line 71 def call outcomes = [] each_event do |event| configured_kinds_for(event).each do |kind| next unless attempt_needed?(event, kind) attestation = attest(event, kind) outcomes << Outcome.new( event_id: event.id, kind: kind, state: attestation&.state || "not_recorded", attestation_id: attestation&.id ) end end Result.new(outcomes: outcomes.freeze) end |