Class: SolidObjects::Actor
- Inherits:
-
Object
- Object
- SolidObjects::Actor
show all
- Defined in:
- lib/solid_objects/actor.rb,
sig/generated/lib/solid_objects/actor.rbs
Defined Under Namespace
Classes: CommitActionIntent, EffectIntent, OutboundMessageIntent, ReminderIntent
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#activate ⇒ void
-
#commit_action(name, **arguments) ⇒ nil
-
#current_message ⇒ MessageContext?
-
#deactivate ⇒ void
-
#discard_intents ⇒ void
-
#drain_commit_action_intents ⇒ Array[CommitActionIntent]
-
#drain_effect_intents ⇒ Array[EffectIntent]
-
#drain_outbound_message_intents ⇒ Array[OutboundMessageIntent]
-
#drain_reminder_intents ⇒ Array[ReminderIntent]
-
#emit(name, on_success: nil, on_failure: nil, **arguments) ⇒ nil
-
#guard_application_writes(operation) { ... } ⇒ Object
-
#initialize(actor_id:, state:) ⇒ Actor
constructor
-
#invoke(message_name, arguments) ⇒ Object
-
#keyword_arguments(arguments) ⇒ Hash[Symbol, untyped]
-
#observable_value(name) ⇒ Object
-
#observable_values ⇒ Hash[String, untyped]
-
#reject(code, message, details: {}) ⇒ bot
-
#schedule(name, at:, every: nil, missed: :latest, arguments: {}) ⇒ nil
-
#send_to(reference, message_name, available_at: nil, idempotency_key: nil, **arguments) ⇒ nil
-
#stage_outbound_message(reference, message_name, arguments, available_at: nil, idempotency_key: nil) ⇒ OutboundMessageIntent
-
#validate_effect_callback!(message_name) ⇒ void
Constructor Details
#initialize(actor_id:, state:) ⇒ Actor
Returns a new instance of Actor.
142
143
144
145
146
147
148
149
|
# File 'lib/solid_objects/actor.rb', line 142
def initialize(actor_id:, state:)
@actor_id = actor_id
@state = state
@effect_intents = []
@commit_action_intents = []
@reminder_intents = []
@outbound_message_intents = []
end
|
Instance Attribute Details
#actor_id ⇒ Object
139
140
141
|
# File 'lib/solid_objects/actor.rb', line 139
def actor_id
@actor_id
end
|
#commit_action_intents ⇒ Object
Returns the value of attribute commit_action_intents.
308
309
310
|
# File 'lib/solid_objects/actor.rb', line 308
def commit_action_intents
@commit_action_intents
end
|
#effect_intents ⇒ Object
Returns the value of attribute effect_intents.
308
309
310
|
# File 'lib/solid_objects/actor.rb', line 308
def effect_intents
@effect_intents
end
|
#outbound_message_intents ⇒ Object
Returns the value of attribute outbound_message_intents.
308
309
310
|
# File 'lib/solid_objects/actor.rb', line 308
def outbound_message_intents
@outbound_message_intents
end
|
#reminder_intents ⇒ Object
Returns the value of attribute reminder_intents.
308
309
310
|
# File 'lib/solid_objects/actor.rb', line 308
def reminder_intents
@reminder_intents
end
|
#state ⇒ Object
139
140
141
|
# File 'lib/solid_objects/actor.rb', line 139
def state
@state
end
|
Class Method Details
.actor_type(value = nil) ⇒ String
19
20
21
22
23
24
25
26
|
# File 'lib/solid_objects/actor.rb', line 19
def actor_type(value = nil)
if value
@actor_type = value.to_s
SolidObjects.register_actor(@actor_type, self)
end
@actor_type ||= default_actor_type
end
|
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/solid_objects/actor.rb', line 29
def attribute(name, default: nil)
attribute_name = name.to_sym
ensure_attribute_methods_available!(attribute_name)
attribute = definition.add_attribute(attribute_name, default:)
@defining_attribute_methods = true
begin
define_method(attribute_name) { state.fetch(attribute_name) }
define_method(:"#{attribute_name}=") { |value| state.write(attribute_name, value) }
generated_attribute_methods[attribute_name] = true
generated_attribute_methods[:"#{attribute_name}="] = true
ensure
@defining_attribute_methods = false
end
attribute
end
|
90
91
92
|
# File 'lib/solid_objects/actor.rb', line 90
def definition
(@definition ||= ActorDefinition.new).synchronize_instance_messages(self)
end
|
.ensure_registered! ⇒ Class
.inherited(subclass) ⇒ void
This method returns an undefined value.
12
13
14
15
16
|
# File 'lib/solid_objects/actor.rb', line 12
def inherited(subclass)
super
subclass.instance_variable_set(:@definition, definition.duplicate)
subclass.instance_variable_set(:@generated_attribute_methods, generated_attribute_methods.dup)
end
|
46
47
48
|
# File 'lib/solid_objects/actor.rb', line 46
def message(name, &block)
definition.add_message(name, block)
end
|
67
68
69
|
# File 'lib/solid_objects/actor.rb', line 67
def migrate_state(from:, to:, &block)
definition.add_state_migration(from, to, block)
end
|
.observable(name, &block) ⇒ void
This method returns an undefined value.
56
57
58
|
# File 'lib/solid_objects/actor.rb', line 56
def observable(name, &block)
definition.add_observable(name, block)
end
|
.on_activate { ... } ⇒ Proc
72
73
74
75
|
# File 'lib/solid_objects/actor.rb', line 72
def on_activate(&block)
definition.activation_hooks << block
block
end
|
.on_deactivate { ... } ⇒ Proc
78
79
80
81
|
# File 'lib/solid_objects/actor.rb', line 78
def on_deactivate(&block)
definition.deactivation_hooks << block
block
end
|
51
52
53
|
# File 'lib/solid_objects/actor.rb', line 51
def query(name, &block)
definition.add_query(name, block)
end
|
84
85
86
87
|
# File 'lib/solid_objects/actor.rb', line 84
def ref(actor_id)
ensure_registered!
Reference.new(actor_type:, actor_id: actor_id.to_s)
end
|
.state_version(version = nil) ⇒ Integer
61
62
63
64
|
# File 'lib/solid_objects/actor.rb', line 61
def state_version(version = nil)
definition.set_state_version(version) if version
definition.state_version
end
|
Instance Method Details
#activate ⇒ void
This method returns an undefined value.
253
254
255
256
257
|
# File 'lib/solid_objects/actor.rb', line 253
def activate
guard_application_writes("on_activate") do
self.class.definition.activation_hooks.each { |hook| instance_exec(&hook) }
end
end
|
#commit_action(name, **arguments) ⇒ nil
182
183
184
185
186
187
188
189
190
|
# File 'lib/solid_objects/actor.rb', line 182
def commit_action(name, **arguments)
CommitActionIntent.new(
name: name.to_s,
arguments: Serialization.dump(arguments)
).tap do |intent|
commit_action_intents << intent
end
nil
end
|
#deactivate ⇒ void
This method returns an undefined value.
260
261
262
263
264
|
# File 'lib/solid_objects/actor.rb', line 260
def deactivate
guard_application_writes("on_deactivate") do
self.class.definition.deactivation_hooks.each { |hook| instance_exec(&hook) }
end
end
|
#discard_intents ⇒ void
This method returns an undefined value.
299
300
301
302
303
304
|
# File 'lib/solid_objects/actor.rb', line 299
def discard_intents
effect_intents.clear
commit_action_intents.clear
reminder_intents.clear
outbound_message_intents.clear
end
|
#drain_commit_action_intents ⇒ Array[CommitActionIntent]
284
285
286
|
# File 'lib/solid_objects/actor.rb', line 284
def drain_commit_action_intents
commit_action_intents.shift(commit_action_intents.length)
end
|
#drain_effect_intents ⇒ Array[EffectIntent]
279
280
281
|
# File 'lib/solid_objects/actor.rb', line 279
def drain_effect_intents
effect_intents.shift(effect_intents.length)
end
|
294
295
296
|
# File 'lib/solid_objects/actor.rb', line 294
def drain_outbound_message_intents
outbound_message_intents.shift(outbound_message_intents.length)
end
|
#drain_reminder_intents ⇒ Array[ReminderIntent]
289
290
291
|
# File 'lib/solid_objects/actor.rb', line 289
def drain_reminder_intents
reminder_intents.shift(reminder_intents.length)
end
|
#emit(name, on_success: nil, on_failure: nil, **arguments) ⇒ nil
167
168
169
170
171
172
173
174
175
176
177
178
179
|
# File 'lib/solid_objects/actor.rb', line 167
def emit(name, on_success: nil, on_failure: nil, **arguments)
validate_effect_callback!(on_success)
validate_effect_callback!(on_failure)
EffectIntent.new(
name: name.to_s,
arguments: Serialization.dump(arguments),
success_message_name: on_success&.to_s,
failure_message_name: on_failure&.to_s
).tap do |intent|
effect_intents << intent
end
nil
end
|
#guard_application_writes(operation) { ... } ⇒ Object
314
315
316
317
318
319
320
321
|
# File 'lib/solid_objects/actor.rb', line 314
def guard_application_writes(operation, &block)
ApplicationWriteGuard.call(
actor_type: self.class.actor_type,
actor_id:,
operation:,
&block
)
end
|
#invoke(message_name, arguments) ⇒ Object
222
223
224
225
226
227
228
229
230
|
# File 'lib/solid_objects/actor.rb', line 222
def invoke(message_name, arguments)
handler = self.class.definition.messages[message_name.to_sym] ||
self.class.definition.queries[message_name.to_sym]
raise UnknownMessage, "unknown message #{message_name.inspect} for #{self.class.actor_type}" unless handler
guard_application_writes(message_name.to_s) do
instance_exec(**keyword_arguments(arguments), &handler.block)
end
end
|
#keyword_arguments(arguments) ⇒ Hash[Symbol, untyped]
324
325
326
|
# File 'lib/solid_objects/actor.rb', line 324
def keyword_arguments(arguments)
arguments.each_with_object({}) { |(key, value), converted| converted[key.to_sym] = value }
end
|
#observable_value(name) ⇒ Object
242
243
244
245
246
247
248
249
250
|
# File 'lib/solid_objects/actor.rb', line 242
def observable_value(name)
observable_name = name.to_sym
handler = self.class.definition.observables[observable_name]
raise UnknownMessage, "unknown observable #{name.inspect}" unless handler
guard_application_writes("observable.#{observable_name}") do
Serialization.dump(instance_exec(&handler.block))
end
end
|
#observable_values ⇒ Hash[String, untyped]
233
234
235
236
237
238
239
|
# File 'lib/solid_objects/actor.rb', line 233
def observable_values
guard_application_writes("observables") do
self.class.definition.observables.each_with_object({}) do |(name, handler), values|
values[name.to_s] = Serialization.dump(instance_exec(&handler.block))
end
end
end
|
#reject(code, message, details: {}) ⇒ bot
157
158
159
160
161
162
163
164
|
# File 'lib/solid_objects/actor.rb', line 157
def reject(code, message, details: {})
rejection_code = code.to_s
unless rejection_code.match?(/\A[a-z][a-z0-9_]*\z/)
raise ArgumentError, "rejection code must contain lowercase letters, digits, and underscores"
end
raise Rejected.new(code: rejection_code, message:, details:)
end
|
#schedule(name, at:, every: nil, missed: :latest, arguments: {}) ⇒ nil
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
# File 'lib/solid_objects/actor.rb', line 193
def schedule(name, at:, every: nil, missed: :latest, arguments: {})
interval_seconds = every&.to_f
if interval_seconds && !interval_seconds.positive?
raise ArgumentError, "reminder interval must be positive"
end
missed_policy = missed.to_s
unless %w[all latest].include?(missed_policy)
raise ArgumentError, "missed reminder policy must be all or latest"
end
ReminderIntent.new(
name: name.to_s,
at:,
arguments: Serialization.dump(arguments),
interval_seconds:,
missed_policy:
).tap do |intent|
reminder_intents << intent
end
nil
end
|
#send_to(reference, message_name, available_at: nil, idempotency_key: nil, **arguments) ⇒ nil
216
217
218
219
|
# File 'lib/solid_objects/actor.rb', line 216
def send_to(reference, message_name, available_at: nil, idempotency_key: nil, **arguments)
stage_outbound_message(reference, message_name, arguments, available_at:, idempotency_key:)
nil
end
|
#stage_outbound_message(reference, message_name, arguments, available_at: nil, idempotency_key: nil) ⇒ OutboundMessageIntent
267
268
269
270
271
272
273
274
275
276
|
# File 'lib/solid_objects/actor.rb', line 267
def stage_outbound_message(reference, message_name, arguments, available_at: nil, idempotency_key: nil)
OutboundMessageIntent.new(
actor_type: reference.actor_type,
actor_id: reference.actor_id,
message_name: message_name.to_s,
arguments: Serialization.dump(arguments),
available_at:,
idempotency_key:
).tap { |intent| outbound_message_intents << intent }
end
|
#validate_effect_callback!(message_name) ⇒ void
This method returns an undefined value.
329
330
331
332
333
334
|
# File 'lib/solid_objects/actor.rb', line 329
def validate_effect_callback!(message_name)
return unless message_name
return if self.class.definition.messages.key?(message_name.to_sym)
raise UnknownMessage, "unknown effect callback message #{message_name.inspect}"
end
|