solid_objects 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +39 -16
  4. data/app/controllers/solid_objects/components_controller.rb +4 -4
  5. data/app/models/solid_objects/message.rb +1 -1
  6. data/app/views/solid_objects/dead_letters/index.html.erb +1 -1
  7. data/app/views/solid_objects/instances/show.html.erb +1 -1
  8. data/benchmark/support.rb +10 -10
  9. data/db/migrate/20260813000000_rename_message_dispatch_columns.rb +53 -0
  10. data/docs/architecture.md +11 -9
  11. data/docs/authorization.md +2 -2
  12. data/docs/database-schema.md +4 -4
  13. data/docs/development.md +1 -1
  14. data/docs/migrating-existing-state.md +1 -3
  15. data/docs/roadmap.md +1 -1
  16. data/lib/solid_objects/actor.rb +43 -32
  17. data/lib/solid_objects/actor_channel.rb +3 -3
  18. data/lib/solid_objects/actor_definition.rb +9 -6
  19. data/lib/solid_objects/actor_view.rb +1 -1
  20. data/lib/solid_objects/application_write_guard.rb +1 -1
  21. data/lib/solid_objects/client.rb +52 -52
  22. data/lib/solid_objects/component_registration.rb +2 -2
  23. data/lib/solid_objects/component_renderer.rb +1 -1
  24. data/lib/solid_objects/component_subscriptions.rb +21 -21
  25. data/lib/solid_objects/database_adapters/sqlite.rb +7 -1
  26. data/lib/solid_objects/dead_letter_manager.rb +4 -4
  27. data/lib/solid_objects/doctor.rb +8 -8
  28. data/lib/solid_objects/effect_executor.rb +22 -22
  29. data/lib/solid_objects/errors.rb +27 -27
  30. data/lib/solid_objects/executor.rb +40 -38
  31. data/lib/solid_objects/lease.rb +3 -3
  32. data/lib/solid_objects/mailbox.rb +34 -27
  33. data/lib/solid_objects/operation_dispatcher.rb +51 -0
  34. data/lib/solid_objects/payload_broadcast.rb +1 -1
  35. data/lib/solid_objects/reference.rb +60 -29
  36. data/lib/solid_objects/reminder_scheduler.rb +6 -6
  37. data/lib/solid_objects/sync_diagnostics.rb +6 -6
  38. data/lib/solid_objects/turbo_stream_renderer.rb +13 -13
  39. data/lib/solid_objects/version.rb +1 -1
  40. data/lib/solid_objects.rb +1 -0
  41. data/sig/generated/controllers/solid_objects/components_controller.rbs +2 -2
  42. data/sig/generated/lib/solid_objects/actor.rbs +17 -17
  43. data/sig/generated/lib/solid_objects/actor_definition.rbs +4 -4
  44. data/sig/generated/lib/solid_objects/client.rbs +8 -8
  45. data/sig/generated/lib/solid_objects/component_registration.rbs +2 -2
  46. data/sig/generated/lib/solid_objects/component_subscriptions.rbs +8 -8
  47. data/sig/generated/lib/solid_objects/database_adapters/sqlite.rbs +3 -0
  48. data/sig/generated/lib/solid_objects/effect_executor.rbs +2 -2
  49. data/sig/generated/lib/solid_objects/errors.rbs +18 -18
  50. data/sig/generated/lib/solid_objects/executor.rbs +10 -10
  51. data/sig/generated/lib/solid_objects/lease.rbs +2 -2
  52. data/sig/generated/lib/solid_objects/mailbox.rbs +8 -8
  53. data/sig/generated/lib/solid_objects/operation_dispatcher.rbs +35 -0
  54. data/sig/generated/lib/solid_objects/reference.rbs +7 -4
  55. data/sig/generated/lib/solid_objects/sync_diagnostics.rbs +2 -2
  56. data/sig/generated/lib/solid_objects/turbo_stream_renderer.rbs +8 -8
  57. metadata +5 -2
@@ -32,9 +32,9 @@ module SolidObjects
32
32
  snapshot = ActorSnapshot.new(reference)
33
33
  scalar_observable_names(snapshot).each do |name|
34
34
  transmit TurboStreamRenderer.observable_value(
35
- reference,
36
- name,
37
- snapshot.observable_value(name)
35
+ reference:,
36
+ name:,
37
+ value: snapshot.observable_value(name)
38
38
  )
39
39
  end
40
40
  refresh_outdated_components(snapshot)
@@ -45,6 +45,7 @@ module SolidObjects
45
45
  # @rbs (Symbol | String, default: untyped) -> StateDefinition::Attribute
46
46
  def add_attribute(name, default:)
47
47
  attribute_name = name.to_sym
48
+ OperationDispatcher.validate_operation_name!(attribute_name)
48
49
  if messages.key?(attribute_name) || queries.key?(attribute_name)
49
50
  raise InvalidActor, "#{attribute_name.inspect} is already defined"
50
51
  end
@@ -60,7 +61,7 @@ module SolidObjects
60
61
 
61
62
  # @rbs (Symbol | String, Proc) -> Handler
62
63
  def add_message(name, block)
63
- add_handler(messages, name, block)
64
+ add_handler(collection: messages, name:, block:)
64
65
  end
65
66
 
66
67
  # @rbs (Symbol | String, Proc) -> Handler
@@ -72,7 +73,7 @@ module SolidObjects
72
73
  end
73
74
  end
74
75
 
75
- add_handler(queries, name, block)
76
+ add_handler(collection: queries, name:, block:)
76
77
  end
77
78
 
78
79
  # @rbs (Symbol | String, Proc?) -> Handler
@@ -121,8 +122,8 @@ module SolidObjects
121
122
  @state_version = version
122
123
  end
123
124
 
124
- # @rbs (Integer, Integer, Proc) -> StateMigration
125
- def add_state_migration(from, to, block)
125
+ # @rbs (from: Integer, to: Integer, block: Proc) -> StateMigration
126
+ def add_state_migration(from:, to:, block:)
126
127
  unless to == from + 1
127
128
  raise InvalidActor, "state migrations must advance exactly one version"
128
129
  end
@@ -183,6 +184,7 @@ module SolidObjects
183
184
 
184
185
  # @rbs (Symbol) -> Handler
185
186
  def add_method_message(name)
187
+ OperationDispatcher.validate_operation_name!(name)
186
188
  if messages.key?(name) || queries.key?(name)
187
189
  raise InvalidActor, "#{name.inspect} is already defined"
188
190
  end
@@ -222,9 +224,10 @@ module SolidObjects
222
224
  end
223
225
  end
224
226
 
225
- # @rbs (Hash[Symbol, Handler], Symbol | String, Proc) -> Handler
226
- def add_handler(collection, name, block)
227
+ # @rbs (collection: Hash[Symbol, Handler], name: Symbol | String, block: Proc) -> Handler
228
+ def add_handler(collection:, name:, block:)
227
229
  handler_name = name.to_sym
230
+ OperationDispatcher.validate_operation_name!(handler_name)
228
231
  raise InvalidActor, "#{handler_name.inspect} is already defined" if messages.key?(handler_name) || queries.key?(handler_name)
229
232
 
230
233
  Handler.new(name: handler_name, block:).tap { |handler| collection[handler_name] = handler }
@@ -154,7 +154,7 @@ module SolidObjects
154
154
  authorized = SolidObjects.configuration.authorize_query.call(
155
155
  actor_type: reference.actor_type,
156
156
  actor_id: reference.actor_id,
157
- message_name: name.to_s,
157
+ operation: name.to_s,
158
158
  arguments: {},
159
159
  authorization_context:
160
160
  )
@@ -16,7 +16,7 @@ module SolidObjects
16
16
  raise ApplicationWriteForbidden.new(
17
17
  actor_type:,
18
18
  actor_id:,
19
- message_name: operation
19
+ operation:
20
20
  )
21
21
  end
22
22
  end
@@ -12,50 +12,50 @@ module SolidObjects
12
12
  @mailbox = mailbox
13
13
  end
14
14
 
15
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference
16
- def async(reference, message_name, arguments, available_at: nil, idempotency_key: nil, authorization_context: nil)
15
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference
16
+ def async(reference:, operation:, arguments:, available_at: nil, idempotency_key: nil, authorization_context: nil)
17
17
  actor_class = SolidObjects.registry.fetch(reference.actor_type)
18
- message_symbol = message_name.to_sym
19
- raise UnknownMessage, "unknown message #{message_name.inspect}" unless actor_class.definition.messages.key?(message_symbol)
18
+ operation_symbol = operation.to_sym
19
+ raise UnknownMessage, "unknown operation #{operation.inspect}" unless actor_class.definition.messages.key?(operation_symbol)
20
20
 
21
21
  authorize!(
22
- SolidObjects.configuration.authorize_message,
23
- reference,
24
- message_name,
25
- arguments,
22
+ hook: SolidObjects.configuration.authorize_message,
23
+ reference:,
24
+ operation:,
25
+ arguments:,
26
26
  authorization_context:
27
27
  )
28
28
  mailbox.enqueue(
29
- reference,
30
- message_name,
31
- arguments,
32
- kind: "async",
29
+ reference:,
30
+ operation:,
31
+ arguments:,
32
+ delivery_mode: "async",
33
33
  available_at:,
34
34
  idempotency_key:
35
35
  )
36
36
  end
37
37
 
38
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> untyped
39
- def sync(reference, message_name, arguments, timeout:, idempotency_key: nil, authorization_context: nil)
38
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> untyped
39
+ def sync(reference:, operation:, arguments:, timeout:, idempotency_key: nil, authorization_context: nil)
40
40
  actor_class = SolidObjects.registry.fetch(reference.actor_type)
41
- message_symbol = message_name.to_sym
42
- query = actor_class.definition.queries.key?(message_symbol)
43
- actor_message = actor_class.definition.messages.key?(message_symbol)
44
- raise UnknownMessage, "unknown message #{message_name.inspect}" unless query || actor_message
41
+ operation_symbol = operation.to_sym
42
+ query = actor_class.definition.queries.key?(operation_symbol)
43
+ actor_message = actor_class.definition.messages.key?(operation_symbol)
44
+ raise UnknownMessage, "unknown operation #{operation.inspect}" unless query || actor_message
45
45
 
46
46
  authorize!(
47
- query ? SolidObjects.configuration.authorize_query : SolidObjects.configuration.authorize_message,
48
- reference,
49
- message_name,
50
- arguments,
47
+ hook: query ? SolidObjects.configuration.authorize_query : SolidObjects.configuration.authorize_message,
48
+ reference:,
49
+ operation:,
50
+ arguments:,
51
51
  authorization_context:
52
52
  )
53
- reject_sync_inside_transaction!(reference, message_name)
53
+ reject_sync_inside_transaction!(reference, operation)
54
54
  SyncDeadline.with(timeout:) do
55
55
  message_reference = enqueue_sync(
56
- reference,
57
- message_name,
58
- arguments,
56
+ reference:,
57
+ operation:,
58
+ arguments:,
59
59
  idempotency_key:,
60
60
  timeout:
61
61
  )
@@ -75,19 +75,19 @@ module SolidObjects
75
75
  actor_id: message.actor_id
76
76
  )
77
77
  actor_class = SolidObjects.registry.fetch(reference.actor_type)
78
- query = actor_class.definition.queries.key?(message.message_name.to_sym)
79
- actor_message = actor_class.definition.messages.key?(message.message_name.to_sym)
78
+ query = actor_class.definition.queries.key?(message.operation.to_sym)
79
+ actor_message = actor_class.definition.messages.key?(message.operation.to_sym)
80
80
  unless query || actor_message
81
- raise UnknownMessage, "unknown message #{message.message_name.inspect}"
81
+ raise UnknownMessage, "unknown operation #{message.operation.inspect}"
82
82
  end
83
83
  authorize!(
84
- query ? SolidObjects.configuration.authorize_query : SolidObjects.configuration.authorize_message,
85
- reference,
86
- message.message_name,
87
- message.arguments,
84
+ hook: query ? SolidObjects.configuration.authorize_query : SolidObjects.configuration.authorize_message,
85
+ reference:,
86
+ operation: message.operation,
87
+ arguments: message.arguments,
88
88
  authorization_context:
89
89
  )
90
- reject_sync_inside_transaction!(reference, message.message_name)
90
+ reject_sync_inside_transaction!(reference, message.operation)
91
91
  SynchronousInvocation.new.call(message_reference, timeout:)
92
92
  end
93
93
  rescue DatabaseDeadlineExceeded
@@ -98,10 +98,10 @@ module SolidObjects
98
98
  def snapshot(reference, authorization_context: nil)
99
99
  SolidObjects.registry.fetch(reference.actor_type)
100
100
  authorize!(
101
- SolidObjects.configuration.authorize_query,
102
- reference,
103
- "__snapshot__",
104
- {},
101
+ hook: SolidObjects.configuration.authorize_query,
102
+ reference:,
103
+ operation: "__snapshot__",
104
+ arguments: {},
105
105
  authorization_context:
106
106
  )
107
107
  StateSnapshot.new(reference)
@@ -140,13 +140,13 @@ module SolidObjects
140
140
 
141
141
  attr_reader :mailbox
142
142
 
143
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], idempotency_key: String?, timeout: Numeric) -> MessageReference
144
- def enqueue_sync(reference, message_name, arguments, idempotency_key:, timeout:)
143
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], idempotency_key: String?, timeout: Numeric) -> MessageReference
144
+ def enqueue_sync(reference:, operation:, arguments:, idempotency_key:, timeout:)
145
145
  mailbox.enqueue(
146
- reference,
147
- message_name,
148
- arguments,
149
- kind: "sync",
146
+ reference:,
147
+ operation:,
148
+ arguments:,
149
+ delivery_mode: "sync",
150
150
  idempotency_key:
151
151
  )
152
152
  rescue DatabaseDeadlineExceeded
@@ -154,13 +154,13 @@ module SolidObjects
154
154
  :"sync.enqueue_timeout",
155
155
  actor_type: reference.actor_type,
156
156
  actor_id: reference.actor_id,
157
- message_name: message_name.to_s
157
+ operation: operation.to_s
158
158
  )
159
159
  raise SyncEnqueueTimeout.new(
160
160
  timeout:,
161
161
  actor_type: reference.actor_type,
162
162
  actor_id: reference.actor_id,
163
- message_name: message_name.to_s
163
+ operation: operation.to_s
164
164
  )
165
165
  end
166
166
 
@@ -176,28 +176,28 @@ module SolidObjects
176
176
  end
177
177
 
178
178
  # @rbs (Reference, Symbol | String) -> void
179
- def reject_sync_inside_transaction!(reference, message_name)
179
+ def reject_sync_inside_transaction!(reference, operation)
180
180
  return unless SolidObjects::Record.connection.transaction_open?
181
181
 
182
182
  SolidObjects.instrument(
183
183
  :"sync.transaction_rejected",
184
184
  actor_type: reference.actor_type,
185
185
  actor_id: reference.actor_id,
186
- message_name: message_name.to_s
186
+ operation: operation.to_s
187
187
  )
188
188
  raise SyncInsideTransaction.new(
189
189
  actor_type: reference.actor_type,
190
190
  actor_id: reference.actor_id,
191
- message_name: message_name.to_s
191
+ operation: operation.to_s
192
192
  )
193
193
  end
194
194
 
195
- # @rbs (Proc, Reference, Symbol | String, Hash[Symbol | String, untyped], authorization_context: untyped) -> void
196
- def authorize!(hook, reference, message_name, arguments, authorization_context:)
195
+ # @rbs (hook: Proc, reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], authorization_context: untyped) -> void
196
+ def authorize!(hook:, reference:, operation:, arguments:, authorization_context:)
197
197
  authorized = hook.call(
198
198
  actor_type: reference.actor_type,
199
199
  actor_id: reference.actor_id,
200
- message_name: message_name.to_s,
200
+ operation: operation.to_s,
201
201
  arguments:,
202
202
  authorization_context:
203
203
  )
@@ -156,8 +156,8 @@ module SolidObjects
156
156
  locals.merge("component_key" => component_key).freeze
157
157
  end
158
158
 
159
- # @rbs (Array[ComponentRegistration], Integer, Integer) -> String
160
- def batch_refresh_url(registrations, instance_id, revision)
159
+ # @rbs (registrations: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> String
160
+ def batch_refresh_url(registrations:, instance_id:, revision:)
161
161
  query = URI.encode_www_form(
162
162
  [
163
163
  [ "instance_id", instance_id ],
@@ -60,7 +60,7 @@ module SolidObjects
60
60
  authorized = SolidObjects.configuration.authorize_query.call(
61
61
  actor_type: snapshot.reference.actor_type,
62
62
  actor_id: snapshot.reference.actor_id,
63
- message_name: observable_name,
63
+ operation: observable_name,
64
64
  arguments: registration.authorization_arguments,
65
65
  authorization_context:
66
66
  )
@@ -50,21 +50,21 @@ module SolidObjects
50
50
  revision = invalidation.fetch("revision")
51
51
  changed = registrations.select do |registration|
52
52
  registration.dependencies.include?(observable_name) &&
53
- newer_revision?(registration.dom_id, instance_id, revision)
53
+ newer_revision?(dom_id: registration.dom_id, instance_id:, revision:)
54
54
  end
55
- refresh_streams(changed, instance_id, revision)
55
+ refresh_streams(changed:, instance_id:, revision:)
56
56
  end
57
57
 
58
58
  # @rbs (ActorSnapshot) -> Array[String]
59
59
  def reconnect_refreshes(snapshot)
60
60
  stale = registrations.select do |registration|
61
61
  newer_revision?(
62
- registration.dom_id,
63
- snapshot.instance_id,
64
- snapshot.revision
62
+ dom_id: registration.dom_id,
63
+ instance_id: snapshot.instance_id,
64
+ revision: snapshot.revision
65
65
  )
66
66
  end
67
- refresh_streams(stale, snapshot.instance_id, snapshot.revision)
67
+ refresh_streams(changed: stale, instance_id: snapshot.instance_id, revision: snapshot.revision)
68
68
  end
69
69
 
70
70
  class << self
@@ -86,36 +86,36 @@ module SolidObjects
86
86
 
87
87
  # Live invalidations and reconnect replays share this, so a reconnecting
88
88
  # client pays the same number of requests a connected one does.
89
- # @rbs (Array[ComponentRegistration], Integer, Integer) -> Array[String]
90
- def refresh_streams(changed, instance_id, revision)
89
+ # @rbs (changed: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> Array[String]
90
+ def refresh_streams(changed:, instance_id:, revision:)
91
91
  batched, individual = changed.partition(&:batch)
92
92
  streams = individual.map do |registration|
93
- refresh(registration, instance_id, revision)
93
+ refresh(registration:, instance_id:, revision:)
94
94
  end
95
95
  batched.group_by(&:batch).each_value do |group|
96
- group.each { |registration| record_revision(registration, instance_id, revision) }
97
- streams << TurboStreamRenderer.batch_refresh(group, instance_id, revision)
96
+ group.each { |registration| record_revision(registration:, instance_id:, revision:) }
97
+ streams << TurboStreamRenderer.batch_refresh(registrations: group, instance_id:, revision:)
98
98
  end
99
99
  streams
100
100
  end
101
101
 
102
- # @rbs (ComponentRegistration, Integer, Integer) -> void
103
- def record_revision(registration, instance_id, revision)
102
+ # @rbs (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> void
103
+ def record_revision(registration:, instance_id:, revision:)
104
104
  revisions[registration.dom_id] = [ instance_id, revision ]
105
105
  end
106
106
 
107
- # @rbs (ComponentRegistration, Integer, Integer) -> String
108
- def refresh(registration, instance_id, revision)
109
- record_revision(registration, instance_id, revision)
107
+ # @rbs (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
108
+ def refresh(registration:, instance_id:, revision:)
109
+ record_revision(registration:, instance_id:, revision:)
110
110
  TurboStreamRenderer.component_refresh(
111
- registration,
112
- instance_id,
113
- revision
111
+ registration:,
112
+ instance_id:,
113
+ revision:
114
114
  )
115
115
  end
116
116
 
117
- # @rbs (String, Integer, Integer) -> bool
118
- def newer_revision?(dom_id, instance_id, revision)
117
+ # @rbs (dom_id: String, instance_id: Integer, revision: Integer) -> bool
118
+ def newer_revision?(dom_id:, instance_id:, revision:)
119
119
  current = revisions.fetch(dom_id)
120
120
  (current <=> [ instance_id, revision ]) == -1
121
121
  end
@@ -141,7 +141,13 @@ module SolidObjects
141
141
  def deadline_error?(error)
142
142
  return false unless SyncDeadline.active?
143
143
 
144
- busy_error?(error)
144
+ busy_error?(error) || reconnect_blocked_error?(error)
145
+ end
146
+
147
+ # @rbs (Exception) -> bool
148
+ def reconnect_blocked_error?(error)
149
+ error.message.include?("SQLite3::CantOpenException") &&
150
+ error.message.include?("PRAGMA journal_mode='wal'")
145
151
  end
146
152
 
147
153
  # @rbs (Exception) -> bool
@@ -16,13 +16,13 @@ module SolidObjects
16
16
 
17
17
  original_message = dead_letter.message
18
18
  message_reference = Mailbox.new.enqueue(
19
- Reference.new(
19
+ reference: Reference.new(
20
20
  actor_type: dead_letter.actor_type,
21
21
  actor_id: dead_letter.actor_id
22
22
  ),
23
- dead_letter.message_name,
24
- dead_letter.arguments,
25
- kind: original_message.message_kind,
23
+ operation: dead_letter.operation,
24
+ arguments: dead_letter.arguments,
25
+ delivery_mode: original_message.delivery_mode,
26
26
  idempotency_key: "dead-letter:#{dead_letter.id}"
27
27
  )
28
28
  dead_letter.update!(retried_message_id: message_reference.id)
@@ -68,7 +68,7 @@ module SolidObjects
68
68
  activation_generation
69
69
  ],
70
70
  messages: %w[
71
- id instance_id message_kind arguments sequence attempt_count request_id
71
+ id instance_id delivery_mode arguments sequence attempt_count request_id
72
72
  result error rejection completed_at rejected_at
73
73
  ],
74
74
  ready_messages: %w[id message_id instance_id sequence available_at],
@@ -76,7 +76,7 @@ module SolidObjects
76
76
  id message_id instance_id process_id activation_token
77
77
  activation_generation claimed_at
78
78
  ],
79
- reminders: %w[id instance_id message_name next_run_at status],
79
+ reminders: %w[id instance_id operation next_run_at status],
80
80
  effects: %w[id message_id instance_id effect_id status available_at],
81
81
  broadcasts: %w[id message_id instance_id broadcast_id status available_at],
82
82
  dead_letters: %w[id message_id instance_id actor_type actor_id attempts]
@@ -247,10 +247,10 @@ module SolidObjects
247
247
  probe_registry.register(kind: "caller", metadata: { execution: "doctor" })
248
248
  value = SecureRandom.hex(8)
249
249
  message_reference = Mailbox.new.enqueue(
250
- ProbeActor.ref(actor_id),
251
- :ping,
252
- { value: },
253
- kind: "sync"
250
+ reference: ProbeActor.ref(actor_id),
251
+ operation: :ping,
252
+ arguments: { value: },
253
+ delivery_mode: "sync"
254
254
  )
255
255
  result = SynchronousInvocation
256
256
  .new(process_registry: probe_registry)
@@ -314,11 +314,11 @@ module SolidObjects
314
314
  }
315
315
  {
316
316
  authorize_message: actor_arguments.merge(
317
- message_name: "ping",
317
+ operation: "ping",
318
318
  arguments: { "value" => "doctor" }
319
319
  ),
320
320
  authorize_query: actor_arguments.merge(
321
- message_name: "value",
321
+ operation: "value",
322
322
  arguments: {}
323
323
  ),
324
324
  authorize_destroy: actor_arguments,
@@ -122,18 +122,18 @@ module SolidObjects
122
122
  actor_id: arguments.fetch("actor_id")
123
123
  )
124
124
  actor_class = SolidObjects.registry.fetch(reference.actor_type)
125
- message_name = arguments.fetch("message_name")
126
- unless actor_class.definition.messages.key?(message_name.to_sym)
127
- raise UnknownMessage, "unknown actor-to-actor message #{message_name.inspect}"
125
+ operation = arguments.fetch("operation")
126
+ unless actor_class.definition.messages.key?(operation.to_sym)
127
+ raise UnknownMessage, "unknown actor-to-actor operation #{operation.inspect}"
128
128
  end
129
129
 
130
130
  available_at = arguments["available_at"]
131
131
  available_at = Time.iso8601(available_at) if available_at
132
132
  Mailbox.new.enqueue(
133
- reference,
134
- message_name,
135
- arguments.fetch("arguments"),
136
- kind: "internal",
133
+ reference:,
134
+ operation:,
135
+ arguments: arguments.fetch("arguments"),
136
+ delivery_mode: "internal",
137
137
  available_at:,
138
138
  idempotency_key: effect.effect_id
139
139
  ).id
@@ -150,10 +150,10 @@ module SolidObjects
150
150
  locked_effect = Effect.lock.find(effect.id)
151
151
  verify_claim!(locked_effect)
152
152
  result_message = enqueue_result_message(
153
- locked_effect,
154
- locked_effect.success_message_name,
155
- "success",
156
- { "effect_id" => locked_effect.effect_id, "result" => serialized_result }
153
+ effect: locked_effect,
154
+ operation: locked_effect.success_operation,
155
+ outcome: "success",
156
+ arguments: { "effect_id" => locked_effect.effect_id, "result" => serialized_result }
157
157
  )
158
158
  locked_effect.update!(
159
159
  status: "completed",
@@ -188,10 +188,10 @@ module SolidObjects
188
188
  }
189
189
  if dead
190
190
  result_message = enqueue_result_message(
191
- locked_effect,
192
- locked_effect.failure_message_name,
193
- "failure",
194
- { "effect_id" => locked_effect.effect_id, "error" => error_details }
191
+ effect: locked_effect,
192
+ operation: locked_effect.failure_operation,
193
+ outcome: "failure",
194
+ arguments: { "effect_id" => locked_effect.effect_id, "error" => error_details }
195
195
  )
196
196
  end
197
197
  locked_effect.update!(
@@ -216,18 +216,18 @@ module SolidObjects
216
216
  raise LostActivation, "effect claim changed"
217
217
  end
218
218
 
219
- # @rbs (Effect, String?, String, Hash[String, untyped]) -> Message?
220
- def enqueue_result_message(effect, message_name, outcome, arguments)
221
- return unless message_name
219
+ # @rbs (effect: Effect, operation: String?, outcome: String, arguments: Hash[String, untyped]) -> Message?
220
+ def enqueue_result_message(effect:, operation:, outcome:, arguments:)
221
+ return unless operation
222
222
 
223
223
  Mailbox.new.enqueue_in_transaction(
224
- Reference.new(
224
+ reference: Reference.new(
225
225
  actor_type: effect.instance.actor_type,
226
226
  actor_id: effect.instance.actor_id
227
227
  ),
228
- message_name,
229
- arguments,
230
- kind: "internal",
228
+ operation:,
229
+ arguments:,
230
+ delivery_mode: "internal",
231
231
  idempotency_key: "effect:#{effect.effect_id}:#{outcome}"
232
232
  )
233
233
  end