19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
|
# File 'lib/ruby_slime/mongoid/interactor.rb', line 19
def call(*commands)
lazy_key = @state_key.respond_to?(:call)
state_record = if lazy_key
@mongoid_model.new
else
@mongoid_model.where({
_id: @state_key,
}).first_or_initialize
end
process = @load_process.call(
state: state_record.state,
)
metadata_buffer = {
next_position: state_record.next_position,
}
pending_events = commands.each do |command|
process.call(command)
end.then do
process.pending_events
end
return pending_events unless pending_events.present?
state_record.state = process.state
state_record.next_position += pending_events.size
state_record._id = @state_key.call if lazy_key
begin
pending_events
ensure
if state_record.new_record?
begin
state_record.save!
rescue ::Mongo::Error::OperationFailure => e
raise e unless e.code == 11000
raise StaleRecord
end
else
update_result = @mongoid_model.where({
_id: state_record._id,
lock_version: state_record.lock_version,
}).update_all({
'$set': {
state: state_record.state,
next_position: state_record.next_position,
}.compact,
'$inc': {
lock_version: 1,
},
})
raise StaleRecord unless 0 < update_result.matched_count
end
metadata_buffer[:state_key] = state_record._id
@event_handler&.call(
pending_events,
**metadata_buffer,
)
end
end
|