Class: Insika::Commands::RollbackHarvest
- Inherits:
-
Object
- Object
- Insika::Commands::RollbackHarvest
- Defined in:
- lib/insika/commands/rollback_harvest.rb
Overview
— the snapshot restored. RollbackHarvest(snapshot_ref:)
restores the pre-promotion state deterministically: WriteSkill with the
snapshot's pre-promotion content (or DeleteSkill when the skill did not
exist before — the snapshot's existed flag), SetSkillAgents to the
snapshot's pre-promotion enabled_for, and the rolled_back_at stamp on
the SAME log (the log stays the single ledger: a skill promoted, rolled
back, re-promoted is three readable rows). The "rehearsed once
end-to-end" acceptance is this command's full promote -> rollback cycle.
Instance Method Summary collapse
-
#call(command) ⇒ Object
payload: { snapshot_ref:, operator?, reason? } -> Promotion (the row with rolled_back_at stamped).
-
#initialize(harvest_store:, skill_store:, skill_catalog:, profile_source:, event_stream:, write_skill: nil, delete_skill: nil, set_skill_agents: nil) ⇒ RollbackHarvest
constructor
A new instance of RollbackHarvest.
Constructor Details
#initialize(harvest_store:, skill_store:, skill_catalog:, profile_source:, event_stream:, write_skill: nil, delete_skill: nil, set_skill_agents: nil) ⇒ RollbackHarvest
Returns a new instance of RollbackHarvest.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/insika/commands/rollback_harvest.rb', line 17 def initialize(harvest_store:, skill_store:, skill_catalog:, profile_source:, event_stream:, write_skill: nil, delete_skill: nil, set_skill_agents: nil) @harvest_store = harvest_store @profiles = ProfileSource.coerce(profile_source) @event_stream = event_stream @write_skill = write_skill || Insika::Commands::WriteSkill.new(skill_store: skill_store, skill_catalog: skill_catalog, event_stream: event_stream) @delete_skill = delete_skill || Insika::Commands::DeleteSkill.new(skill_store: skill_store, skill_catalog: skill_catalog, event_stream: event_stream) @set_skill_agents = set_skill_agents || Insika::Commands::SetSkillAgents.new(profile_source: @profiles, event_stream: event_stream) end |
Instance Method Details
#call(command) ⇒ Object
payload: { snapshot_ref:, operator?, reason? } -> Promotion (the row with rolled_back_at stamped)
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/insika/commands/rollback_harvest.rb', line 37 def call(command) p = AgentPayload.symbolize(command.payload) snapshot_ref = AgentPayload.presence(p[:snapshot_ref]) raise Insika::ValidationError, "snapshot_ref is required" if snapshot_ref.nil? snap = @harvest_store.find_snapshot(snapshot_ref) || (raise Insika::NotFoundError, "harvest snapshot not found: #{snapshot_ref}") # The log row whose snapshot_ref matches — but a promotion that never # recorded its row (a crash between the writes and the append) rolls # back by snapshot, and the rollback stamp catches up on whatever row # exists (D8's honest price, resolved by reference). promotion = promotion_for_snapshot(snap) operator = (AgentPayload.presence(p[:operator]) || command.[:operator] || "operator").to_s if snap.existed @write_skill.call(Insika::Command.build(:write_skill, { name: snap.skill, content: snap.content, agent: snap.agent })) else begin @delete_skill.call(Insika::Command.build(:delete_skill, { name: snap.skill, agent: snap.agent })) rescue Insika::NotFoundError # the desired state (gone) already holds — a snapshot taken for a # skill that never landed rolls back cleanly end end @set_skill_agents.call(Insika::Command.build(:set_skill_agents, { name: snap.skill, agent_ids: snap.enabled_for })) rolled = promotion ? @harvest_store.append_rollback(promotion_id: promotion.id, operator: operator, reason: p[:reason]) : nil @event_stream.emit(Insika::Event.new( type: :skill_rolled_back, data: { snapshot_ref: snapshot_ref, skill: snap.skill, agent: snap.agent, operator: operator }.compact, meta: { at: Time.now.utc.iso8601 } )) rolled || promotion end |