solid_objects 0.16.1 → 0.17.1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +100 -0
  3. data/README.md +9 -0
  4. data/Rakefile +5 -0
  5. data/app/models/solid_objects/message.rb +15 -0
  6. data/docs/agents.md +253 -0
  7. data/docs/architecture.md +16 -6
  8. data/docs/authorization.md +10 -3
  9. data/docs/observability.md +186 -0
  10. data/docs/operations.md +10 -8
  11. data/docs/realtime.md +4 -3
  12. data/docs/reminders.md +3 -1
  13. data/docs/roadmap.md +17 -1
  14. data/docs/security.md +2 -2
  15. data/docs/transmission.md +17 -6
  16. data/docs/virtual-actors.md +226 -0
  17. data/examples/quickstart/README.md +246 -0
  18. data/examples/quickstart/app/actors/ticket_sale.rb +22 -0
  19. data/examples/quickstart/smoke.rb +421 -0
  20. data/lib/solid_objects/activation.rb +6 -3
  21. data/lib/solid_objects/actor.rb +29 -2
  22. data/lib/solid_objects/actor_channel.rb +9 -1
  23. data/lib/solid_objects/actor_snapshot.rb +14 -8
  24. data/lib/solid_objects/broadcast_executor.rb +1 -0
  25. data/lib/solid_objects/client.rb +15 -1
  26. data/lib/solid_objects/configuration.rb +4 -0
  27. data/lib/solid_objects/database_adapters/sqlite.rb +7 -1
  28. data/lib/solid_objects/diagnostics.rb +83 -0
  29. data/lib/solid_objects/effect_executor.rb +4 -0
  30. data/lib/solid_objects/errors.rb +3 -0
  31. data/lib/solid_objects/executor.rb +34 -16
  32. data/lib/solid_objects/instrumentation.rb +22 -1
  33. data/lib/solid_objects/log_subscriber.rb +1 -1
  34. data/lib/solid_objects/mailbox.rb +5 -1
  35. data/lib/solid_objects/message_reference.rb +9 -9
  36. data/lib/solid_objects/observer_registry.rb +47 -0
  37. data/lib/solid_objects/payload_broadcast.rb +9 -8
  38. data/lib/solid_objects/reference.rb +19 -0
  39. data/lib/solid_objects/reminder_scheduler.rb +5 -0
  40. data/lib/solid_objects/state_snapshot.rb +1 -0
  41. data/lib/solid_objects/supervisor.rb +3 -6
  42. data/lib/solid_objects/synchronous_invocation.rb +1 -21
  43. data/lib/solid_objects/telemetry.rb +137 -0
  44. data/lib/solid_objects/version.rb +1 -1
  45. data/lib/solid_objects/wake_up_adapters/postgresql.rb +1 -2
  46. data/lib/solid_objects/wake_up_adapters/redis.rb +1 -2
  47. data/lib/solid_objects/worker.rb +1 -2
  48. data/lib/solid_objects.rb +10 -0
  49. data/sig/generated/lib/solid_objects/actor.rbs +9 -0
  50. data/sig/generated/lib/solid_objects/actor_channel.rbs +3 -0
  51. data/sig/generated/lib/solid_objects/actor_snapshot.rbs +7 -2
  52. data/sig/generated/lib/solid_objects/client.rbs +3 -0
  53. data/sig/generated/lib/solid_objects/configuration.rbs +7 -3
  54. data/sig/generated/lib/solid_objects/diagnostics.rbs +25 -0
  55. data/sig/generated/lib/solid_objects/errors.rbs +3 -0
  56. data/sig/generated/lib/solid_objects/executor.rbs +10 -2
  57. data/sig/generated/lib/solid_objects/message_reference.rbs +6 -6
  58. data/sig/generated/lib/solid_objects/observer_registry.rbs +29 -0
  59. data/sig/generated/lib/solid_objects/payload_broadcast.rbs +2 -4
  60. data/sig/generated/lib/solid_objects/reference.rbs +9 -0
  61. data/sig/generated/lib/solid_objects/synchronous_invocation.rbs +0 -3
  62. data/sig/generated/lib/solid_objects/telemetry.rbs +30 -0
  63. data/sig/generated/lib/solid_objects.rbs +3 -0
  64. data/sig/generated/models/solid_objects/message.rbs +3 -0
  65. data/sig/public/json_value.rbs +3 -0
  66. data/sig/public/telemetry.rbs +49 -0
  67. data/sig/support/framework.rbs +5 -0
  68. metadata +24 -9
@@ -2,7 +2,6 @@
2
2
 
3
3
  module SolidObjects
4
4
  class PayloadBroadcast
5
- MAXIMUM_PAYLOAD_BYTES = 1_048_576
6
5
  REVISION_OBSERVABLE = "solid_objects.revision"
7
6
 
8
7
  # @rbs @snapshot: ActorSnapshot
@@ -42,7 +41,7 @@ module SolidObjects
42
41
  def rendered_payload(handler)
43
42
  payload = Serialization.dump(
44
43
  evaluated_payload(handler),
45
- max_bytes: MAXIMUM_PAYLOAD_BYTES
44
+ max_bytes: SolidObjects.configuration.max_payload_bytes
46
45
  )
47
46
  return payload if payload.is_a?(Hash) || payload.is_a?(Array)
48
47
 
@@ -56,10 +55,12 @@ module SolidObjects
56
55
  # unaffected.
57
56
  # @rbs (ActorDefinition::Handler) -> untyped
58
57
  def evaluated_payload(handler)
59
- actor = snapshot.actor
60
- actor.instance_exec(actor, authorization_context, &handler.block)
58
+ actor = snapshot.build_actor
59
+ actor.read_projection("payload.#{name}") do
60
+ actor.instance_exec(actor, authorization_context, &handler.block)
61
+ end
61
62
  rescue NameError => error
62
- raise unless class_level_receiver?(error)
63
+ raise unless class_level_receiver?(error, actor)
63
64
 
64
65
  raise InvalidPayloadBroadcast,
65
66
  "payload broadcast #{name.inspect} called #{error.name.inspect} on the " \
@@ -70,9 +71,9 @@ module SolidObjects
70
71
  # Distinguishes a block that relied on the old class-level receiver from an
71
72
  # ordinary typo, so the one behaviour change reports itself instead of
72
73
  # surfacing as an unexplained NameError.
73
- # @rbs (NameError[untyped]) -> bool
74
- def class_level_receiver?(error)
75
- error.receiver.equal?(snapshot.actor) &&
74
+ # @rbs (NameError[BasicObject], Actor?) -> bool
75
+ def class_level_receiver?(error, actor)
76
+ error.receiver.equal?(actor) &&
76
77
  snapshot.actor_class.respond_to?(error.name)
77
78
  rescue ArgumentError, NameError
78
79
  false
@@ -16,6 +16,25 @@ module SolidObjects
16
16
  freeze
17
17
  end
18
18
 
19
+ # @rbs (?limit: Integer, ?authorization_context: untyped) -> actor_diagnostics
20
+ def diagnostics(limit: 100, authorization_context: nil)
21
+ Diagnostics.new(self).summary(limit:, authorization_context:)
22
+ end
23
+
24
+ # @rbs (?authorization_context: untyped) { (portable_event) -> void } -> Proc
25
+ def observe(authorization_context: nil, &block)
26
+ Diagnostics.new(self).observe(authorization_context:, &block)
27
+ end
28
+
29
+ # @rbs (String, ?authorization_context: untyped) { (portable_event) -> void } -> Proc
30
+ def on(name, authorization_context: nil, &block)
31
+ raise ArgumentError, "an actor observer requires a block" unless block
32
+
33
+ observe(authorization_context:) do |event|
34
+ block.call(event) if event.fetch("name") == "solid_objects.#{name}"
35
+ end
36
+ end
37
+
19
38
  # @rbs (?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
20
39
  def async(available_at: nil, idempotency_key: nil, authorization_context: nil)
21
40
  OperationDispatcher.new(
@@ -166,9 +166,14 @@ module SolidObjects
166
166
  mailbox.announce(message)
167
167
  SolidObjects.instrument(
168
168
  :"reminder.enqueued",
169
+ instance_id: reminder.instance_id,
170
+ message_id: message.id,
171
+ attempt: message.attempt_count,
172
+ lateness_milliseconds: [ (((now || database_adapter.database_now) - reminder.next_run_at) * 1000).round, 0 ].max,
169
173
  reminder_id: reminder.id,
170
174
  actor_type: reminder.actor_type,
171
175
  actor_id: reminder.actor_id,
176
+ operation: reminder.operation,
172
177
  occurrence: reminder.occurrence
173
178
  )
174
179
  MessageReference.from_message(message)
@@ -10,6 +10,7 @@ module SolidObjects
10
10
  actor_snapshot = ActorSnapshot.new(reference)
11
11
  @actor_class = actor_snapshot.actor_class
12
12
  @data = Serialization.readonly_copy(actor_snapshot.actor.state.to_h)
13
+ SolidObjects.instrument(:"snapshot.read", actor_type: reference.actor_type, actor_id: reference.actor_id, instance_id: actor_snapshot.instance_id.zero? ? nil : actor_snapshot.instance_id, revision: actor_snapshot.revision)
13
14
  end
14
15
 
15
16
  # @rbs () -> Hash[String, untyped]
@@ -97,8 +97,7 @@ module SolidObjects
97
97
  rescue => error
98
98
  SolidObjects.instrument(
99
99
  :"supervisor.monitor_failed",
100
- error_class: error.class.name,
101
- error_message: error.message
100
+ error_class: error.class.name
102
101
  )
103
102
  end
104
103
  sleep SolidObjects.configuration.supervisor_monitor_interval
@@ -161,8 +160,7 @@ module SolidObjects
161
160
  failures += 1
162
161
  SolidObjects.instrument(
163
162
  :"supervisor.retention_failed",
164
- error_class: error.class.name,
165
- error_message: error.message
163
+ error_class: error.class.name
166
164
  )
167
165
  end
168
166
  wait_for_next_retention(failures)
@@ -220,8 +218,7 @@ module SolidObjects
220
218
  rescue => error
221
219
  SolidObjects.instrument(
222
220
  :"supervisor.redrive_failed",
223
- error_class: error.class.name,
224
- error_message: error.message
221
+ error_class: error.class.name
225
222
  )
226
223
  false
227
224
  end
@@ -78,27 +78,7 @@ module SolidObjects
78
78
 
79
79
  # @rbs (Message) -> untyped
80
80
  def completed_result(message)
81
- raise_rejection(message) if message.rejected?
82
- if message.dead?
83
- raise MessageFailed.new(
84
- "actor message failed permanently",
85
- message_id: message.id,
86
- details: message.error || {}
87
- )
88
- end
89
-
90
- Serialization.readonly_copy(message.result)
91
- end
92
-
93
- # @rbs (Message) -> bot
94
- def raise_rejection(message)
95
- rejection = message.rejection
96
- raise Rejected.new(
97
- code: rejection.fetch("code"),
98
- message: rejection.fetch("message"),
99
- details: rejection.fetch("details"),
100
- message_id: message.id
101
- )
81
+ message.result!
102
82
  end
103
83
 
104
84
  # @rbs () -> ProcessRegistry
@@ -0,0 +1,137 @@
1
+ # rbs_inline: enabled
2
+
3
+ module SolidObjects
4
+ module Telemetry
5
+ FIELDS = %w[
6
+ activationGeneration activationOwnerId actorId actorType ageMilliseconds attempt broadcastId
7
+ broadcastWorkers byteCount code commitAction component componentCount count currentIntervalMilliseconds
8
+ deliveryMode depth durationMilliseconds effectId effectName effectWorkers errorName failureCount
9
+ generation idlePollingIntervalMilliseconds incarnation instanceId intervalMilliseconds
10
+ latenessMilliseconds messageId name nextRunAt occurrence operation outboxKind outcome ownerId payload
11
+ phase pollingIntervalMilliseconds previousIntervalMilliseconds previousRunAt processId processKind
12
+ reason reminderId reminderSchedulers requestId retryable revision role sequence status thresholdBytes
13
+ timeoutMilliseconds truncated waitingOn workers
14
+ ].freeze #: Array[String]
15
+ ALIASES = {
16
+ "errorClass" => "errorName",
17
+ "stateRevision" => "revision",
18
+ "durationMs" => "durationMilliseconds",
19
+ "commitActionName" => "commitAction",
20
+ "payloadName" => "payload"
21
+ }.freeze #: Hash[String, String]
22
+
23
+ class << self
24
+ # @rbs (Effect | Broadcast) -> void
25
+ def outbox(record)
26
+ return unless SolidObjects.configuration.instrumentation || ActiveSupport::Notifications.notifier.listening?("solid_objects.outbox.age")
27
+
28
+ instance = record.instance
29
+ SolidObjects.instrument(
30
+ :"outbox.age",
31
+ instance_id: record.instance_id,
32
+ actor_type: instance.actor_type,
33
+ actor_id: instance.actor_id,
34
+ message_id: record.message_id,
35
+ attempt: record.attempt_count,
36
+ outbox_kind: record.is_a?(Effect) ? "effect" : "broadcast",
37
+ age_milliseconds: [ ((SolidObjects.database_adapter.database_now - record.available_at) * 1000).round, 0 ].max,
38
+ **outbox_identity(record)
39
+ )
40
+ rescue
41
+ nil
42
+ end
43
+
44
+ # @rbs (Symbol, Hash[Symbol, Object]) -> void
45
+ def emit(name, payload)
46
+ observer = SolidObjects.configuration.instrumentation
47
+ return unless observer
48
+
49
+ deliver(observer, event(name, payload))
50
+ rescue
51
+ nil
52
+ end
53
+
54
+ # @rbs (event_observer, portable_event) -> void
55
+ def deliver(observer, event)
56
+ observer.call(event)
57
+ rescue => error
58
+ log_delivery_failure(event.fetch("name"), error)
59
+ end
60
+
61
+ # @rbs (Symbol, Hash[Symbol, Object]) -> portable_event
62
+ def event(name, payload)
63
+ attributes = safe_attributes(payload)
64
+ adapter = DatabaseAdapter.family(Record.connection).to_s
65
+ event_name = "solid_objects.#{name}"
66
+ labels = { "event" => event_name, "adapter" => adapter, "actorType" => attributes["actorType"].to_s }
67
+ metrics = [ { "name" => "solid_objects.events", "kind" => "counter", "unit" => "1", "value" => 1, "labels" => labels } ]
68
+ [
69
+ [ "durationMilliseconds", "solid_objects.duration", "histogram", "ms" ],
70
+ [ "latenessMilliseconds", "solid_objects.reminder.lateness", "histogram", "ms" ],
71
+ [ "ageMilliseconds", "solid_objects.outbox.age", "histogram", "ms" ],
72
+ [ "depth", "solid_objects.mailbox.depth", "gauge", "1" ]
73
+ ].each do |field, metric, kind, unit|
74
+ value = attributes[field]
75
+ next unless value.is_a?(Numeric) && value.finite?
76
+
77
+ metrics << { "name" => metric, "kind" => kind, "unit" => unit, "value" => [ value, 0 ].max, "labels" => labels }
78
+ end
79
+ Serialization.readonly_copy(
80
+ "schemaVersion" => 1,
81
+ "name" => event_name,
82
+ "occurredAt" => Time.now.utc.iso8601(3),
83
+ "adapter" => adapter,
84
+ "actorType" => attributes["actorType"]&.to_s,
85
+ "actorId" => attributes["actorId"]&.to_s,
86
+ "incarnation" => (attributes["incarnation"] || attributes["instanceId"])&.to_s,
87
+ "revision" => attributes["revision"]&.to_s,
88
+ "messageId" => attributes["messageId"]&.to_s,
89
+ "attempt" => attributes.fetch("attempt", 0),
90
+ "attributes" => attributes,
91
+ "metrics" => metrics
92
+ )
93
+ end
94
+
95
+ # @rbs (Hash[Symbol, Object]) -> Hash[String, telemetry_value]
96
+ def safe_attributes(payload)
97
+ payload.each_with_object({}) do |(key, value), attributes|
98
+ value = value.to_s if key == :reason && value.is_a?(Symbol)
99
+ if %i[previous_interval current_interval].include?(key) && value.is_a?(Numeric)
100
+ attributes["#{key.to_s.camelize(:lower)}Milliseconds"] = (value * 1000).round
101
+ next
102
+ end
103
+ name = key.to_s.camelize(:lower)
104
+ name = ALIASES.fetch(name, name)
105
+ next unless FIELDS.include?(name)
106
+ next unless value.nil? || value.is_a?(String) || value.is_a?(Numeric) || value == true || value == false
107
+
108
+ value = value.camelize(:lower) if name == "waitingOn" && value.is_a?(String)
109
+ value = value.to_s if !value.nil? && (name.end_with?("Id") || %w[revision sequence generation activationGeneration].include?(name))
110
+ attributes[name] = value
111
+ end
112
+ end
113
+
114
+ private
115
+
116
+ # @rbs (Effect | Broadcast) -> Hash[Symbol, String | Integer]
117
+ def outbox_identity(record)
118
+ return { effect_id: record.effect_id, effect_name: record.name } if record.is_a?(Effect)
119
+
120
+ { broadcast_id: record.broadcast_id, revision: record.message.sequence }
121
+ end
122
+
123
+ # @rbs (String, Exception) -> void
124
+ def log_delivery_failure(event_name, error)
125
+ SolidObjects.configuration.logger.error(
126
+ {
127
+ event: "solid_objects.instrumentation.failed",
128
+ instrumentation_event: event_name,
129
+ error_class: error.class.name
130
+ }
131
+ )
132
+ rescue
133
+ nil
134
+ end
135
+ end
136
+ end
137
+ end
@@ -1,5 +1,5 @@
1
1
  # rbs_inline: enabled
2
2
 
3
3
  module SolidObjects
4
- VERSION = "0.16.1"
4
+ VERSION = "0.17.1"
5
5
  end
@@ -145,8 +145,7 @@ module SolidObjects
145
145
  :"wake_up.failed",
146
146
  adapter: "postgresql",
147
147
  operation: operation.to_s,
148
- error_class: error.class.name,
149
- error_message: error.message
148
+ error_class: error.class.name
150
149
  )
151
150
  end
152
151
  end
@@ -208,8 +208,7 @@ module SolidObjects
208
208
  :"wake_up.failed",
209
209
  adapter: "redis",
210
210
  operation: operation.to_s,
211
- error_class: error.class.name,
212
- error_message: error.message
211
+ error_class: error.class.name
213
212
  )
214
213
  end
215
214
  end
@@ -69,8 +69,7 @@ module SolidObjects
69
69
  SolidObjects.configuration.logger.error(
70
70
  event: "solid_objects.worker.error",
71
71
  process_id: process_registry.process_record&.id,
72
- error_class: error.class.name,
73
- error_message: error.message
72
+ error_class: error.class.name
74
73
  )
75
74
  0
76
75
  end
data/lib/solid_objects.rb CHANGED
@@ -16,6 +16,8 @@ require "solid_objects/sync_deadline"
16
16
  require "solid_objects/callable_keywords"
17
17
  require "solid_objects/configuration"
18
18
  require "solid_objects/instrumentation"
19
+ require "solid_objects/telemetry"
20
+ require "solid_objects/diagnostics"
19
21
  require "solid_objects/log_subscriber"
20
22
  require "solid_objects/serialization"
21
23
  require "solid_objects/context"
@@ -67,6 +69,7 @@ require "solid_objects/effect_payload"
67
69
  require "solid_objects/effect_recovery_coordinator"
68
70
  require "solid_objects/process_heartbeat"
69
71
  require "solid_objects/commit_action_registry"
72
+ require "solid_objects/observer_registry"
70
73
  require "solid_objects/lease"
71
74
  require "solid_objects/lease_renewer"
72
75
  # The reminder scheduler and the effect executor enqueue through the mailbox,
@@ -139,6 +142,11 @@ module SolidObjects
139
142
  commit_action_registry.register(name, handler)
140
143
  end
141
144
 
145
+ # @rbs () -> ObserverRegistry
146
+ def observer_registry
147
+ @observer_registry ||= ObserverRegistry.new
148
+ end
149
+
142
150
  # @rbs () -> Client
143
151
  def client
144
152
  require "solid_objects/client"
@@ -203,6 +211,8 @@ module SolidObjects
203
211
  @caller_process = nil
204
212
  @effect_registry = EffectRegistry.new
205
213
  @commit_action_registry = CommitActionRegistry.new
214
+ @observer_registry&.clear
215
+ @observer_registry = ObserverRegistry.new
206
216
  @dead_letters = nil
207
217
  @redrives = nil
208
218
  @administration = nil
@@ -348,6 +348,12 @@ module SolidObjects
348
348
  # @rbs () -> void
349
349
  def discard_intents: () -> void
350
350
 
351
+ # @rbs () -> Integer
352
+ def intent_count: () -> Integer
353
+
354
+ # @rbs [Result] (String) { () -> Result } -> Result
355
+ def read_projection: [Result] (String) { () -> Result } -> Result
356
+
351
357
  private
352
358
 
353
359
  attr_reader effect_intents: untyped
@@ -360,6 +366,9 @@ module SolidObjects
360
366
 
361
367
  attr_reader outbound_message_intents: untyped
362
368
 
369
+ # @rbs () -> Array[Array[Hash[Symbol, Object]]]
370
+ def intent_snapshot: () -> Array[Array[Hash[Symbol, Object]]]
371
+
363
372
  # @rbs (String) { () -> untyped } -> untyped
364
373
  def guard_application_writes: (String) { () -> untyped } -> untyped
365
374
 
@@ -7,6 +7,9 @@ module SolidObjects
7
7
  # @rbs () -> void
8
8
  def subscribed: () -> void
9
9
 
10
+ # @rbs () -> void
11
+ def unsubscribed: () -> void
12
+
10
13
  private
11
14
 
12
15
  attr_reader reference: untyped
@@ -12,6 +12,8 @@ module SolidObjects
12
12
 
13
13
  @revision: Integer
14
14
 
15
+ @state_data: Hash[String, json_value]
16
+
15
17
  @observable_values: Hash[String, untyped]?
16
18
 
17
19
  @observable_value_cache: Hash[String, untyped]
@@ -35,11 +37,14 @@ module SolidObjects
35
37
  # @rbs (Symbol | String) -> untyped
36
38
  def observable_value: (Symbol | String) -> untyped
37
39
 
40
+ # @rbs () -> Actor
41
+ def build_actor: () -> Actor
42
+
38
43
  private
39
44
 
40
45
  attr_reader instance: untyped
41
46
 
42
- # @rbs () -> Actor
43
- def build_actor: () -> Actor
47
+ # @rbs () -> Hash[String, json_value]
48
+ def migrated_state: () -> Hash[String, json_value]
44
49
  end
45
50
  end
@@ -16,6 +16,9 @@ module SolidObjects
16
16
  # @rbs (MessageReference, timeout: Numeric, ?authorization_context: untyped) -> untyped
17
17
  def wait: (MessageReference, timeout: Numeric, ?authorization_context: untyped) -> untyped
18
18
 
19
+ # @rbs (MessageReference, ?authorization_context: untyped) -> Message
20
+ def read_message: (MessageReference, ?authorization_context: untyped) -> Message
21
+
19
22
  # @rbs (?reference: Reference?, ?request_id: String?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference?
20
23
  def find_by: (?reference: Reference?, ?request_id: String?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference?
21
24
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module SolidObjects
4
4
  class Configuration
5
- @transmission_actor_type_resolver: Proc
5
+ @reminder_scheduler_count: Integer
6
6
 
7
7
  @broadcast_worker_count: Integer
8
8
 
@@ -36,6 +36,8 @@ module SolidObjects
36
36
 
37
37
  @table_name_prefix: String
38
38
 
39
+ @transmission_actor_type_resolver: Proc
40
+
39
41
  @administration_identity: Proc
40
42
 
41
43
  @authorize_transmission: Proc
@@ -64,9 +66,9 @@ module SolidObjects
64
66
 
65
67
  @logger: untyped
66
68
 
67
- @connects_to: Hash[Symbol, untyped]?
69
+ @instrumentation: event_observer?
68
70
 
69
- @reminder_scheduler_count: Integer
71
+ @connects_to: Hash[Symbol, untyped]?
70
72
 
71
73
  @polling_interval: Float
72
74
 
@@ -214,6 +216,8 @@ module SolidObjects
214
216
 
215
217
  attr_accessor transmission_actor_type_resolver: untyped
216
218
 
219
+ attr_accessor instrumentation: event_observer?
220
+
217
221
  # @rbs @additional_components: Array[untyped]
218
222
  attr_reader additional_components: untyped
219
223
 
@@ -0,0 +1,25 @@
1
+ # Generated from lib/solid_objects/diagnostics.rb with RBS::Inline
2
+
3
+ module SolidObjects
4
+ class Diagnostics
5
+ # @rbs @reference: Reference
6
+ # @rbs (Reference) -> void
7
+ def initialize: (Reference) -> void
8
+
9
+ # @rbs (?limit: Integer, ?authorization_context: untyped) -> actor_diagnostics
10
+ def summary: (?limit: Integer, ?authorization_context: untyped) -> actor_diagnostics
11
+
12
+ # @rbs (?authorization_context: untyped) { (portable_event) -> void } -> Proc
13
+ def observe: (?authorization_context: untyped) { (portable_event) -> void } -> Proc
14
+
15
+ private
16
+
17
+ attr_reader reference: Reference
18
+
19
+ # @rbs (Symbol, ?authorization_context: untyped) -> void
20
+ def authorize!: (Symbol, ?authorization_context: untyped) -> void
21
+
22
+ # @rbs (Array[Time?], now: Time, limit: Integer) -> diagnostic_summary
23
+ def summarize: (Array[Time?], now: Time, limit: Integer) -> diagnostic_summary
24
+ end
25
+ end
@@ -7,6 +7,9 @@ module SolidObjects
7
7
  class NonRetryableError < Error
8
8
  end
9
9
 
10
+ class QueryMutatedState < NonRetryableError
11
+ end
12
+
10
13
  class UnsupportedDatabase < Error
11
14
  end
12
15
 
@@ -4,6 +4,8 @@ module SolidObjects
4
4
  class Executor
5
5
  @completion_transaction: untyped
6
6
 
7
+ @started_at: Float
8
+
7
9
  @message: Message
8
10
 
9
11
  @activation: Activation
@@ -26,8 +28,8 @@ module SolidObjects
26
28
  # @rbs (MessageContext) -> untyped
27
29
  def invoke_actor: (MessageContext) -> untyped
28
30
 
29
- # @rbs (Hash[String, untyped], Hash[String, untyped]) -> void
30
- def ensure_query_did_not_mutate_state!: (Hash[String, untyped], Hash[String, untyped]) -> void
31
+ # @rbs (Hash[String, json_value], Hash[String, json_value]) -> void
32
+ def ensure_query_is_read_only!: (Hash[String, json_value], Hash[String, json_value]) -> void
31
33
 
32
34
  # @rbs (Hash[String, untyped], Hash[String, untyped]) -> Hash[String, untyped]
33
35
  def changed_observables: (Hash[String, untyped], Hash[String, untyped]) -> Hash[String, untyped]
@@ -103,6 +105,12 @@ module SolidObjects
103
105
  # @rbs (message: Message, error_details: Hash[String, untyped], now: Time) -> DeadLetter
104
106
  def create_dead_letter: (message: Message, error_details: Hash[String, untyped], now: Time) -> DeadLetter
105
107
 
108
+ # @rbs () -> bool
109
+ def recovery_message?: () -> bool
110
+
111
+ # @rbs () -> (Integer | Float)
112
+ def elapsed_milliseconds: () -> (Integer | Float)
113
+
106
114
  # @rbs () -> Hash[Symbol, untyped]
107
115
  def instrumentation_payload: () -> Hash[Symbol, untyped]
108
116
  end
@@ -28,14 +28,14 @@ module SolidObjects
28
28
  # @rbs (id: Integer, request_id: String, actor_type: String, actor_id: String, sequence: Integer) -> void
29
29
  def initialize: (id: Integer, request_id: String, actor_type: String, actor_id: String, sequence: Integer) -> void
30
30
 
31
- # @rbs () -> String
32
- def status: () -> String
31
+ # @rbs (?authorization_context: untyped) -> String
32
+ def status: (?authorization_context: untyped) -> String
33
33
 
34
- # @rbs () -> untyped
35
- def result: () -> untyped
34
+ # @rbs (?authorization_context: untyped) -> json_value
35
+ def result: (?authorization_context: untyped) -> json_value
36
36
 
37
- # @rbs () -> Outcome
38
- def outcome: () -> Outcome
37
+ # @rbs (?authorization_context: untyped) -> Outcome
38
+ def outcome: (?authorization_context: untyped) -> Outcome
39
39
 
40
40
  # @rbs (?timeout: Numeric, ?authorization_context: untyped) -> untyped
41
41
  def wait: (?timeout: Numeric, ?authorization_context: untyped) -> untyped
@@ -0,0 +1,29 @@
1
+ # Generated from lib/solid_objects/observer_registry.rb with RBS::Inline
2
+
3
+ module SolidObjects
4
+ class ObserverRegistry
5
+ MAXIMUM_OBSERVERS: ::Integer
6
+
7
+ @subscriptions: Array[Object]
8
+
9
+ @mutex: Mutex
10
+
11
+ # @rbs () -> void
12
+ def initialize: () -> void
13
+
14
+ # @rbs () { (ActiveSupport::Notifications::Event) -> void } -> Proc
15
+ def subscribe: () { (ActiveSupport::Notifications::Event) -> void } -> Proc
16
+
17
+ # @rbs () -> void
18
+ def clear: () -> void
19
+
20
+ private
21
+
22
+ attr_reader subscriptions: Array[Object]
23
+
24
+ attr_reader mutex: Mutex
25
+
26
+ # @rbs (Object) -> void
27
+ def unsubscribe: (Object) -> void
28
+ end
29
+ end
@@ -2,8 +2,6 @@
2
2
 
3
3
  module SolidObjects
4
4
  class PayloadBroadcast
5
- MAXIMUM_PAYLOAD_BYTES: ::Integer
6
-
7
5
  REVISION_OBSERVABLE: ::String
8
6
 
9
7
  @snapshot: ActorSnapshot
@@ -39,8 +37,8 @@ module SolidObjects
39
37
  # Distinguishes a block that relied on the old class-level receiver from an
40
38
  # ordinary typo, so the one behaviour change reports itself instead of
41
39
  # surfacing as an unexplained NameError.
42
- # @rbs (NameError[untyped]) -> bool
43
- def class_level_receiver?: (NameError[untyped]) -> bool
40
+ # @rbs (NameError[BasicObject], Actor?) -> bool
41
+ def class_level_receiver?: (NameError[BasicObject], Actor?) -> bool
44
42
 
45
43
  # @rbs () -> void
46
44
  def authorize!: () -> void
@@ -13,6 +13,15 @@ module SolidObjects
13
13
  # @rbs (actor_type: String, actor_id: String) -> void
14
14
  def initialize: (actor_type: String, actor_id: String) -> void
15
15
 
16
+ # @rbs (?limit: Integer, ?authorization_context: untyped) -> actor_diagnostics
17
+ def diagnostics: (?limit: Integer, ?authorization_context: untyped) -> actor_diagnostics
18
+
19
+ # @rbs (?authorization_context: untyped) { (portable_event) -> void } -> Proc
20
+ def observe: (?authorization_context: untyped) { (portable_event) -> void } -> Proc
21
+
22
+ # @rbs (String, ?authorization_context: untyped) { (portable_event) -> void } -> Proc
23
+ def on: (String, ?authorization_context: untyped) { (portable_event) -> void } -> Proc
24
+
16
25
  # @rbs (?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
17
26
  def async: (?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
18
27
 
@@ -24,9 +24,6 @@ module SolidObjects
24
24
  # @rbs (Message) -> untyped
25
25
  def completed_result: (Message) -> untyped
26
26
 
27
- # @rbs (Message) -> bot
28
- def raise_rejection: (Message) -> bot
29
-
30
27
  # @rbs () -> ProcessRegistry
31
28
  def process_registry: () -> ProcessRegistry
32
29