solid_objects 0.11.0 → 0.12.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +62 -20
  4. data/app/controllers/solid_objects/components_controller.rb +4 -4
  5. data/app/models/solid_objects/broadcast.rb +8 -0
  6. data/app/models/solid_objects/message.rb +1 -1
  7. data/app/views/solid_objects/dead_letters/index.html.erb +1 -1
  8. data/app/views/solid_objects/instances/show.html.erb +1 -1
  9. data/benchmark/support.rb +10 -10
  10. data/db/migrate/20260813000000_rename_message_dispatch_columns.rb +53 -0
  11. data/docs/architecture.md +14 -11
  12. data/docs/authorization.md +2 -2
  13. data/docs/database-schema.md +6 -6
  14. data/docs/development.md +13 -1
  15. data/docs/migrating-existing-state.md +1 -3
  16. data/docs/realtime.md +25 -3
  17. data/docs/roadmap.md +9 -5
  18. data/docs/security.md +8 -0
  19. data/examples/application/app/actors/shopping_cart_actor.rb +3 -3
  20. data/lib/solid_objects/actor.rb +49 -37
  21. data/lib/solid_objects/actor_channel.rb +10 -7
  22. data/lib/solid_objects/actor_definition.rb +24 -9
  23. data/lib/solid_objects/actor_view.rb +7 -2
  24. data/lib/solid_objects/application_write_guard.rb +1 -1
  25. data/lib/solid_objects/client.rb +52 -52
  26. data/lib/solid_objects/component_registration.rb +2 -2
  27. data/lib/solid_objects/component_renderer.rb +1 -1
  28. data/lib/solid_objects/component_subscriptions.rb +21 -21
  29. data/lib/solid_objects/database_adapters/sqlite.rb +7 -1
  30. data/lib/solid_objects/dead_letter_manager.rb +4 -4
  31. data/lib/solid_objects/doctor.rb +8 -8
  32. data/lib/solid_objects/effect_executor.rb +30 -22
  33. data/lib/solid_objects/errors.rb +30 -27
  34. data/lib/solid_objects/executor.rb +47 -39
  35. data/lib/solid_objects/lease.rb +3 -3
  36. data/lib/solid_objects/mailbox.rb +34 -27
  37. data/lib/solid_objects/operation_dispatcher.rb +51 -0
  38. data/lib/solid_objects/payload_broadcast.rb +1 -1
  39. data/lib/solid_objects/reference.rb +60 -29
  40. data/lib/solid_objects/reminder_scheduler.rb +34 -20
  41. data/lib/solid_objects/sync_diagnostics.rb +6 -6
  42. data/lib/solid_objects/test_helper.rb +16 -0
  43. data/lib/solid_objects/turbo_stream_renderer.rb +16 -16
  44. data/lib/solid_objects/version.rb +1 -1
  45. data/lib/solid_objects.rb +1 -0
  46. data/sig/generated/controllers/solid_objects/components_controller.rbs +2 -2
  47. data/sig/generated/lib/solid_objects/actor.rbs +19 -19
  48. data/sig/generated/lib/solid_objects/actor_definition.rbs +13 -6
  49. data/sig/generated/lib/solid_objects/client.rbs +8 -8
  50. data/sig/generated/lib/solid_objects/component_registration.rbs +2 -2
  51. data/sig/generated/lib/solid_objects/component_subscriptions.rbs +8 -8
  52. data/sig/generated/lib/solid_objects/database_adapters/sqlite.rbs +3 -0
  53. data/sig/generated/lib/solid_objects/effect_executor.rbs +2 -2
  54. data/sig/generated/lib/solid_objects/errors.rbs +21 -18
  55. data/sig/generated/lib/solid_objects/executor.rbs +10 -10
  56. data/sig/generated/lib/solid_objects/lease.rbs +2 -2
  57. data/sig/generated/lib/solid_objects/mailbox.rbs +8 -8
  58. data/sig/generated/lib/solid_objects/operation_dispatcher.rbs +35 -0
  59. data/sig/generated/lib/solid_objects/reference.rbs +7 -4
  60. data/sig/generated/lib/solid_objects/reminder_scheduler.rbs +9 -6
  61. data/sig/generated/lib/solid_objects/sync_diagnostics.rbs +2 -2
  62. data/sig/generated/lib/solid_objects/test_helper.rbs +3 -0
  63. data/sig/generated/lib/solid_objects/turbo_stream_renderer.rbs +8 -8
  64. data/sig/generated/models/solid_objects/broadcast.rbs +2 -0
  65. metadata +5 -2
@@ -44,6 +44,8 @@ module SolidObjects
44
44
 
45
45
  @payload_broadcasts: Hash[Symbol, Handler]
46
46
 
47
+ @observable_broadcasts: Hash[Symbol, Symbol]
48
+
47
49
  @observables: Hash[Symbol, Handler]
48
50
 
49
51
  @queries: Hash[Symbol, Handler]
@@ -82,8 +84,11 @@ module SolidObjects
82
84
  # @rbs (Symbol | String, Proc) -> Handler
83
85
  def add_query: (Symbol | String, Proc) -> Handler
84
86
 
85
- # @rbs (Symbol | String, Proc?) -> Handler
86
- def add_observable: (Symbol | String, Proc?) -> Handler
87
+ # @rbs (Symbol | String, Proc?, broadcast: Symbol) -> Handler
88
+ def add_observable: (Symbol | String, Proc?, broadcast: Symbol) -> Handler
89
+
90
+ # @rbs (Symbol | String) -> bool
91
+ def broadcasts_observable_value?: (Symbol | String) -> bool
87
92
 
88
93
  # @rbs (Symbol | String, Proc) -> Handler
89
94
  def add_payload_broadcast: (Symbol | String, Proc) -> Handler
@@ -94,8 +99,8 @@ module SolidObjects
94
99
  # @rbs (Integer) -> Integer
95
100
  def set_state_version: (Integer) -> Integer
96
101
 
97
- # @rbs (Integer, Integer, Proc) -> StateMigration
98
- def add_state_migration: (Integer, Integer, Proc) -> StateMigration
102
+ # @rbs (from: Integer, to: Integer, block: Proc) -> StateMigration
103
+ def add_state_migration: (from: Integer, to: Integer, block: Proc) -> StateMigration
99
104
 
100
105
  # @rbs (Integer, Hash[String, untyped]) -> Hash[String, untyped]
101
106
  def migrate_state: (Integer, Hash[String, untyped]) -> Hash[String, untyped]
@@ -109,6 +114,8 @@ module SolidObjects
109
114
 
110
115
  attr_reader method_messages: untyped
111
116
 
117
+ attr_reader observable_broadcasts: untyped
118
+
112
119
  # @rbs (Symbol) -> Handler
113
120
  def add_method_message: (Symbol) -> Handler
114
121
 
@@ -118,7 +125,7 @@ module SolidObjects
118
125
  # @rbs (Array[Symbol]) -> void
119
126
  def validate_attribute_methods!: (Array[Symbol]) -> void
120
127
 
121
- # @rbs (Hash[Symbol, Handler], Symbol | String, Proc) -> Handler
122
- def add_handler: (Hash[Symbol, Handler], Symbol | String, Proc) -> Handler
128
+ # @rbs (collection: Hash[Symbol, Handler], name: Symbol | String, block: Proc) -> Handler
129
+ def add_handler: (collection: Hash[Symbol, Handler], name: Symbol | String, block: Proc) -> Handler
123
130
  end
124
131
  end
@@ -7,11 +7,11 @@ module SolidObjects
7
7
  # @rbs (?mailbox: Mailbox) -> void
8
8
  def initialize: (?mailbox: Mailbox) -> void
9
9
 
10
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference
11
- def async: (Reference, Symbol | String, Hash[Symbol | String, untyped], ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference
10
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference
11
+ def async: (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> MessageReference
12
12
 
13
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> untyped
14
- def sync: (Reference, Symbol | String, Hash[Symbol | String, untyped], timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> untyped
13
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> untyped
14
+ def sync: (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> untyped
15
15
 
16
16
  # @rbs (MessageReference, timeout: Numeric, ?authorization_context: untyped) -> untyped
17
17
  def wait: (MessageReference, timeout: Numeric, ?authorization_context: untyped) -> untyped
@@ -26,8 +26,8 @@ module SolidObjects
26
26
 
27
27
  attr_reader mailbox: untyped
28
28
 
29
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], idempotency_key: String?, timeout: Numeric) -> MessageReference
30
- def enqueue_sync: (Reference, Symbol | String, Hash[Symbol | String, untyped], idempotency_key: String?, timeout: Numeric) -> MessageReference
29
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], idempotency_key: String?, timeout: Numeric) -> MessageReference
30
+ def enqueue_sync: (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], idempotency_key: String?, timeout: Numeric) -> MessageReference
31
31
 
32
32
  # @rbs (MessageReference, Message) -> void
33
33
  def validate_message_reference!: (MessageReference, Message) -> void
@@ -35,8 +35,8 @@ module SolidObjects
35
35
  # @rbs (Reference, Symbol | String) -> void
36
36
  def reject_sync_inside_transaction!: (Reference, Symbol | String) -> void
37
37
 
38
- # @rbs (Proc, Reference, Symbol | String, Hash[Symbol | String, untyped], authorization_context: untyped) -> void
39
- def authorize!: (Proc, Reference, Symbol | String, Hash[Symbol | String, untyped], authorization_context: untyped) -> void
38
+ # @rbs (hook: Proc, reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], authorization_context: untyped) -> void
39
+ def authorize!: (hook: Proc, reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], authorization_context: untyped) -> void
40
40
 
41
41
  # @rbs (Reference, authorization_context: untyped) -> void
42
42
  def authorize_destroy!: (Reference, authorization_context: untyped) -> void
@@ -73,8 +73,8 @@ module SolidObjects
73
73
  # @rbs () -> Hash[String, untyped]
74
74
  def authorization_arguments: () -> Hash[String, untyped]
75
75
 
76
- # @rbs (Array[ComponentRegistration], Integer, Integer) -> String
77
- def batch_refresh_url: (Array[ComponentRegistration], Integer, Integer) -> String
76
+ # @rbs (registrations: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> String
77
+ def batch_refresh_url: (registrations: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> String
78
78
 
79
79
  # @rbs (Integer, Integer) -> String
80
80
  def refresh_url: (Integer, Integer) -> String
@@ -33,16 +33,16 @@ module SolidObjects
33
33
 
34
34
  # Live invalidations and reconnect replays share this, so a reconnecting
35
35
  # client pays the same number of requests a connected one does.
36
- # @rbs (Array[ComponentRegistration], Integer, Integer) -> Array[String]
37
- def refresh_streams: (Array[ComponentRegistration], Integer, Integer) -> Array[String]
36
+ # @rbs (changed: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> Array[String]
37
+ def refresh_streams: (changed: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> Array[String]
38
38
 
39
- # @rbs (ComponentRegistration, Integer, Integer) -> void
40
- def record_revision: (ComponentRegistration, Integer, Integer) -> void
39
+ # @rbs (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> void
40
+ def record_revision: (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> void
41
41
 
42
- # @rbs (ComponentRegistration, Integer, Integer) -> String
43
- def refresh: (ComponentRegistration, Integer, Integer) -> String
42
+ # @rbs (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
43
+ def refresh: (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
44
44
 
45
- # @rbs (String, Integer, Integer) -> bool
46
- def newer_revision?: (String, Integer, Integer) -> bool
45
+ # @rbs (dom_id: String, instance_id: Integer, revision: Integer) -> bool
46
+ def newer_revision?: (dom_id: String, instance_id: Integer, revision: Integer) -> bool
47
47
  end
48
48
  end
@@ -49,6 +49,9 @@ module SolidObjects
49
49
  # @rbs (Exception) -> bool
50
50
  def deadline_error?: (Exception) -> bool
51
51
 
52
+ # @rbs (Exception) -> bool
53
+ def reconnect_blocked_error?: (Exception) -> bool
54
+
52
55
  # @rbs (Exception) -> bool
53
56
  def busy_error?: (Exception) -> bool
54
57
 
@@ -76,7 +76,7 @@ module SolidObjects
76
76
  # @rbs (Effect) -> void
77
77
  def verify_claim!: (Effect) -> void
78
78
 
79
- # @rbs (Effect, String?, String, Hash[String, untyped]) -> Message?
80
- def enqueue_result_message: (Effect, String?, String, Hash[String, untyped]) -> Message?
79
+ # @rbs (effect: Effect, operation: String?, outcome: String, arguments: Hash[String, untyped]) -> Message?
80
+ def enqueue_result_message: (effect: Effect, operation: String?, outcome: String, arguments: Hash[String, untyped]) -> Message?
81
81
  end
82
82
  end
@@ -71,7 +71,7 @@ module SolidObjects
71
71
 
72
72
  @actor_id: String
73
73
 
74
- @message_name: String
74
+ @operation: String
75
75
 
76
76
  attr_reader timeout: untyped
77
77
 
@@ -79,10 +79,10 @@ module SolidObjects
79
79
 
80
80
  attr_reader actor_id: untyped
81
81
 
82
- attr_reader message_name: untyped
82
+ attr_reader operation: untyped
83
83
 
84
- # @rbs (timeout: Numeric, actor_type: String, actor_id: String, message_name: String) -> void
85
- def initialize: (timeout: Numeric, actor_type: String, actor_id: String, message_name: String) -> void
84
+ # @rbs (timeout: Numeric, actor_type: String, actor_id: String, operation: String) -> void
85
+ def initialize: (timeout: Numeric, actor_type: String, actor_id: String, operation: String) -> void
86
86
  end
87
87
 
88
88
  class SyncTimeout < Error
@@ -92,7 +92,7 @@ module SolidObjects
92
92
 
93
93
  @actor_id: String
94
94
 
95
- @message_name: String
95
+ @operation: String
96
96
 
97
97
  @message_id: Integer
98
98
 
@@ -114,7 +114,7 @@ module SolidObjects
114
114
 
115
115
  attr_reader actor_id: untyped
116
116
 
117
- attr_reader message_name: untyped
117
+ attr_reader operation: untyped
118
118
 
119
119
  attr_reader message_id: untyped
120
120
 
@@ -130,8 +130,8 @@ module SolidObjects
130
130
 
131
131
  attr_reader blocker: untyped
132
132
 
133
- # @rbs (timeout: Numeric, actor_type: String, actor_id: String, message_name: String, message_id: Integer, request_id: String, sequence: Integer, status: String, waiting_on: String, activation: Hash[String, untyped], blocker: Hash[String, untyped]?) -> void
134
- def initialize: (timeout: Numeric, actor_type: String, actor_id: String, message_name: String, message_id: Integer, request_id: String, sequence: Integer, status: String, waiting_on: String, activation: Hash[String, untyped], blocker: Hash[String, untyped]?) -> void
133
+ # @rbs (timeout: Numeric, actor_type: String, actor_id: String, operation: String, message_id: Integer, request_id: String, sequence: Integer, status: String, waiting_on: String, activation: Hash[String, untyped], blocker: Hash[String, untyped]?) -> void
134
+ def initialize: (timeout: Numeric, actor_type: String, actor_id: String, operation: String, message_id: Integer, request_id: String, sequence: Integer, status: String, waiting_on: String, activation: Hash[String, untyped], blocker: Hash[String, untyped]?) -> void
135
135
 
136
136
  # @rbs () -> MessageReference
137
137
  def message_reference: () -> MessageReference
@@ -142,16 +142,16 @@ module SolidObjects
142
142
 
143
143
  @actor_id: String
144
144
 
145
- @message_name: String
145
+ @operation: String
146
146
 
147
147
  attr_reader actor_type: untyped
148
148
 
149
149
  attr_reader actor_id: untyped
150
150
 
151
- attr_reader message_name: untyped
151
+ attr_reader operation: untyped
152
152
 
153
- # @rbs (actor_type: String, actor_id: String, message_name: String) -> void
154
- def initialize: (actor_type: String, actor_id: String, message_name: String) -> void
153
+ # @rbs (actor_type: String, actor_id: String, operation: String) -> void
154
+ def initialize: (actor_type: String, actor_id: String, operation: String) -> void
155
155
  end
156
156
 
157
157
  class ApplicationWriteForbidden < NonRetryableError
@@ -159,26 +159,29 @@ module SolidObjects
159
159
 
160
160
  @actor_id: String
161
161
 
162
- @message_name: String
162
+ @operation: String
163
163
 
164
164
  attr_reader actor_type: untyped
165
165
 
166
166
  attr_reader actor_id: untyped
167
167
 
168
- attr_reader message_name: untyped
168
+ attr_reader operation: untyped
169
169
 
170
- # @rbs (actor_type: String, actor_id: String, message_name: String) -> void
171
- def initialize: (actor_type: String, actor_id: String, message_name: String) -> void
170
+ # @rbs (actor_type: String, actor_id: String, operation: String) -> void
171
+ def initialize: (actor_type: String, actor_id: String, operation: String) -> void
172
172
  end
173
173
 
174
174
  class CommitActionUnavailable < NonRetryableError
175
- # @rbs (actor_type: String, actor_id: String, message_name: String) -> void
176
- def initialize: (actor_type: String, actor_id: String, message_name: String) -> void
175
+ # @rbs (actor_type: String, actor_id: String, operation: String) -> void
176
+ def initialize: (actor_type: String, actor_id: String, operation: String) -> void
177
177
  end
178
178
 
179
179
  class UnknownCommitAction < NonRetryableError
180
180
  end
181
181
 
182
+ class InvalidRejectionCode < NonRetryableError
183
+ end
184
+
182
185
  class Rejected < Error
183
186
  @code: String
184
187
 
@@ -36,14 +36,14 @@ module SolidObjects
36
36
  # @rbs (Array[Actor::CommitActionIntent]) -> void
37
37
  def execute_commit_actions: (Array[Actor::CommitActionIntent]) -> void
38
38
 
39
- # @rbs (Actor::CommitActionIntent, Proc, CommitActionContext) -> untyped
40
- def execute_commit_action: (Actor::CommitActionIntent, Proc, CommitActionContext) -> untyped
39
+ # @rbs (intent: Actor::CommitActionIntent, handler: Proc, context: CommitActionContext) -> untyped
40
+ def execute_commit_action: (intent: Actor::CommitActionIntent, handler: Proc, context: CommitActionContext) -> untyped
41
41
 
42
42
  # @rbs () -> void
43
43
  def ensure_application_database_is_shared!: () -> void
44
44
 
45
- # @rbs (Message, Instance, Array[Actor::EffectIntent]) -> Array[Effect]
46
- def enqueue_effects: (Message, Instance, Array[Actor::EffectIntent]) -> Array[Effect]
45
+ # @rbs (message: Message, instance: Instance, intents: Array[Actor::EffectIntent]) -> Array[Effect]
46
+ def enqueue_effects: (message: Message, instance: Instance, intents: Array[Actor::EffectIntent]) -> Array[Effect]
47
47
 
48
48
  # A reminder is one named alarm per actor, so scheduling a name that is
49
49
  # already armed moves it rather than adding a second. An actor that arms a
@@ -62,11 +62,11 @@ module SolidObjects
62
62
  # @rbs (Reminder, Time?) -> Hash[Symbol, untyped]?
63
63
  def moved_reminder_payload: (Reminder, Time?) -> Hash[Symbol, untyped]?
64
64
 
65
- # @rbs (Message, Instance, Array[Actor::OutboundMessageIntent]) -> Array[Effect]
66
- def enqueue_actor_messages: (Message, Instance, Array[Actor::OutboundMessageIntent]) -> Array[Effect]
65
+ # @rbs (message: Message, instance: Instance, intents: Array[Actor::OutboundMessageIntent]) -> Array[Effect]
66
+ def enqueue_actor_messages: (message: Message, instance: Instance, intents: Array[Actor::OutboundMessageIntent]) -> Array[Effect]
67
67
 
68
- # @rbs (Message, Instance, Hash[String, untyped], state_changed: bool) -> void
69
- def enqueue_broadcasts: (Message, Instance, Hash[String, untyped], state_changed: bool) -> void
68
+ # @rbs (message: Message, instance: Instance, observable_changes: Hash[String, untyped], state_changed: bool) -> void
69
+ def enqueue_broadcasts: (message: Message, instance: Instance, observable_changes: Hash[String, untyped], state_changed: bool) -> void
70
70
 
71
71
  # @rbs () -> bool
72
72
  def payload_broadcasts?: () -> bool
@@ -83,8 +83,8 @@ module SolidObjects
83
83
  # @rbs (Exception) -> Hash[String, untyped]
84
84
  def serialized_error: (Exception) -> Hash[String, untyped]
85
85
 
86
- # @rbs (Message, Hash[String, untyped], Time) -> DeadLetter
87
- def create_dead_letter: (Message, Hash[String, untyped], Time) -> DeadLetter
86
+ # @rbs (message: Message, error_details: Hash[String, untyped], now: Time) -> DeadLetter
87
+ def create_dead_letter: (message: Message, error_details: Hash[String, untyped], now: Time) -> DeadLetter
88
88
 
89
89
  # @rbs () -> Hash[Symbol, untyped]
90
90
  def instrumentation_payload: () -> Hash[Symbol, untyped]
@@ -8,8 +8,8 @@ module SolidObjects
8
8
  # @rbs (instance_id: Integer, owner_id: String, ?activation_token: String, ?duration: Numeric, ?database_adapter: DatabaseAdapter) -> Lease?
9
9
  def self.acquire: (instance_id: Integer, owner_id: String, ?activation_token: String, ?duration: Numeric, ?database_adapter: DatabaseAdapter) -> Lease?
10
10
 
11
- # @rbs (Instance, String, Time) -> bool
12
- private def self.held_by_another_live_owner?: (Instance, String, Time) -> bool
11
+ # @rbs (instance: Instance, activation_token: String, now: Time) -> bool
12
+ private def self.held_by_another_live_owner?: (instance: Instance, activation_token: String, now: Time) -> bool
13
13
 
14
14
  @database_adapter: DatabaseAdapter
15
15
 
@@ -9,11 +9,11 @@ module SolidObjects
9
9
  # @rbs (?database_adapter: DatabaseAdapter) -> void
10
10
  def initialize: (?database_adapter: DatabaseAdapter) -> void
11
11
 
12
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], kind: String, ?available_at: Time?, idempotency_key: String?) -> MessageReference
13
- def enqueue: (Reference, Symbol | String, Hash[Symbol | String, untyped], kind: String, idempotency_key: String?, ?available_at: Time?) -> MessageReference
12
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], delivery_mode: String, ?available_at: Time?, idempotency_key: String?) -> MessageReference
13
+ def enqueue: (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], delivery_mode: String, idempotency_key: String?, ?available_at: Time?) -> MessageReference
14
14
 
15
- # @rbs (Reference, Symbol | String, Hash[Symbol | String, untyped], kind: String, ?available_at: Time?, idempotency_key: String?, ?actor_class: Class?) -> Message
16
- def enqueue_in_transaction: (Reference, Symbol | String, Hash[Symbol | String, untyped], kind: String, idempotency_key: String?, ?available_at: Time?, ?actor_class: Class?) -> Message
15
+ # @rbs (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], delivery_mode: String, ?available_at: Time?, idempotency_key: String?, ?actor_class: Class?) -> Message
16
+ def enqueue_in_transaction: (reference: Reference, operation: Symbol | String, arguments: Hash[Symbol | String, untyped], delivery_mode: String, idempotency_key: String?, ?available_at: Time?, ?actor_class: Class?) -> Message
17
17
 
18
18
  # @rbs (Message) -> void
19
19
  def announce: (Message) -> void
@@ -31,14 +31,14 @@ module SolidObjects
31
31
  # @rbs (Instance, String?) -> Message?
32
32
  def find_idempotent_message: (Instance, String?) -> Message?
33
33
 
34
- # @rbs (Message, Symbol | String, String, untyped) -> Message
35
- def validate_idempotent_message!: (Message, Symbol | String, String, untyped) -> Message
34
+ # @rbs (existing_message: Message, operation: Symbol | String, delivery_mode: String, arguments: untyped) -> Message
35
+ def validate_idempotent_message!: (existing_message: Message, operation: Symbol | String, delivery_mode: String, arguments: untyped) -> Message
36
36
 
37
37
  # @rbs (Instance) -> void
38
38
  def enforce_mailbox_limit!: (Instance) -> void
39
39
 
40
- # @rbs (Instance, Reference, Symbol | String, untyped, kind: String, available_at: Time?, idempotency_key: String?) -> Message
41
- def create_message: (Instance, Reference, Symbol | String, untyped, kind: String, available_at: Time?, idempotency_key: String?) -> Message
40
+ # @rbs (instance: Instance, reference: Reference, operation: Symbol | String, arguments: untyped, delivery_mode: String, available_at: Time?, idempotency_key: String?) -> Message
41
+ def create_message: (instance: Instance, reference: Reference, operation: Symbol | String, arguments: untyped, delivery_mode: String, available_at: Time?, idempotency_key: String?) -> Message
42
42
 
43
43
  # @rbs (Time?, Time) -> Time
44
44
  def normalize_availability: (Time?, Time) -> Time
@@ -0,0 +1,35 @@
1
+ # Generated from lib/solid_objects/operation_dispatcher.rb with RBS::Inline
2
+
3
+ module SolidObjects
4
+ class OperationDispatcher
5
+ @actor_type: String
6
+
7
+ @handlers: Hash[Symbol, ActorDefinition::Handler]
8
+
9
+ @dispatch: Proc
10
+
11
+ # @rbs (actor_type: String, handlers: Hash[Symbol, ActorDefinition::Handler]) { (Symbol, Hash[Symbol, untyped]) -> untyped } -> void
12
+ def initialize: (actor_type: String, handlers: Hash[Symbol, ActorDefinition::Handler]) { (Symbol, Hash[Symbol, untyped]) -> untyped } -> void
13
+
14
+ # @rbs (Symbol, *untyped, **untyped) -> untyped
15
+ def method_missing: (Symbol, *untyped, **untyped) -> untyped
16
+
17
+ # @rbs (Symbol, bool) -> bool
18
+ def respond_to_missing?: (Symbol, bool) -> bool
19
+
20
+ private
21
+
22
+ attr_reader actor_type: untyped
23
+
24
+ attr_reader handlers: untyped
25
+
26
+ attr_reader dispatch: untyped
27
+
28
+ RESERVED_REFERENCE_METHOD_NAMES: untyped
29
+
30
+ RESERVED_OPERATION_NAMES: untyped
31
+
32
+ # @rbs (Symbol | String) -> void
33
+ def self.validate_operation_name!: (Symbol | String) -> void
34
+ end
35
+ end
@@ -13,11 +13,11 @@ 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 (Symbol | String, ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped, **untyped) -> MessageReference?
17
- def async: (Symbol | String, ?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped, **untyped) -> MessageReference?
16
+ # @rbs (?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
17
+ def async: (?available_at: Time?, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
18
18
 
19
- # @rbs (Symbol | String, ?timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped, **untyped) -> untyped
20
- def sync: (Symbol | String, ?timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped, **untyped) -> untyped
19
+ # @rbs (?timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
20
+ def sync: (?timeout: Numeric, ?idempotency_key: String?, ?authorization_context: untyped) -> OperationDispatcher
21
21
 
22
22
  # @rbs (?authorization_context: untyped) -> bool
23
23
  def destroy: (?authorization_context: untyped) -> bool
@@ -36,6 +36,9 @@ module SolidObjects
36
36
 
37
37
  private
38
38
 
39
+ # @rbs (Symbol | String, Hash[Symbol, untyped], timeout: Numeric, idempotency_key: String?, authorization_context: untyped) -> untyped
40
+ def invoke_synchronously: (Symbol | String, Hash[Symbol, untyped], timeout: Numeric, idempotency_key: String?, authorization_context: untyped) -> untyped
41
+
39
42
  # @rbs (Symbol | String) -> bool
40
43
  def actor_message?: (Symbol | String) -> bool
41
44
 
@@ -13,8 +13,8 @@ module SolidObjects
13
13
  # @rbs (?process_registry: ProcessRegistry, ?database_adapter: DatabaseAdapter) -> void
14
14
  def initialize: (?process_registry: ProcessRegistry, ?database_adapter: DatabaseAdapter) -> void
15
15
 
16
- # @rbs () -> bool
17
- def run_once: () -> bool
16
+ # @rbs (?now: Time?) -> bool
17
+ def run_once: (?now: Time?) -> bool
18
18
 
19
19
  # @rbs () -> void
20
20
  def stop: () -> void
@@ -37,11 +37,11 @@ module SolidObjects
37
37
 
38
38
  attr_reader database_adapter: untyped
39
39
 
40
- # @rbs () -> Reminder?
41
- def claim_next: () -> Reminder?
40
+ # @rbs (now: Time?) -> Reminder?
41
+ def claim_next: (now: Time?) -> Reminder?
42
42
 
43
- # @rbs (Reminder) -> MessageReference?
44
- def enqueue: (Reminder) -> MessageReference?
43
+ # @rbs (Reminder, now: Time?) -> MessageReference?
44
+ def enqueue: (Reminder, now: Time?) -> MessageReference?
45
45
 
46
46
  # @rbs (Reminder) -> void
47
47
  def release: (Reminder) -> void
@@ -51,5 +51,8 @@ module SolidObjects
51
51
 
52
52
  # @rbs (Reminder, Time) -> Time
53
53
  def next_run_at: (Reminder, Time) -> Time
54
+
55
+ # @rbs (Time?) -> Time?
56
+ def normalize_test_time: (Time?) -> Time?
54
57
  end
55
58
  end
@@ -19,8 +19,8 @@ module SolidObjects
19
19
  # @rbs (Message) -> String
20
20
  def message_status: (Message) -> String
21
21
 
22
- # @rbs (Message, Instance, Message?) -> String
23
- def waiting_reason: (Message, Instance, Message?) -> String
22
+ # @rbs (message: Message, instance: Instance, blocker: Message?) -> String
23
+ def waiting_reason: (message: Message, instance: Instance, blocker: Message?) -> String
24
24
 
25
25
  # @rbs (ReadyMessage?) -> bool
26
26
  def future?: (ReadyMessage?) -> bool
@@ -26,6 +26,9 @@ module SolidObjects
26
26
  # @rbs (?roles: Array[Symbol], ?max_passes: Integer) -> Integer
27
27
  def drain_solid_objects: (?roles: Array[Symbol], ?max_passes: Integer) -> Integer
28
28
 
29
+ # @rbs (now: Time, ?max_reminders: Integer) -> Integer
30
+ def run_due_reminders: (now: Time, ?max_reminders: Integer) -> Integer
31
+
29
32
  private
30
33
 
31
34
  # @rbs (Array[Symbol]) -> Array[Worker | EffectExecutor | ReminderScheduler | BroadcastExecutor]
@@ -9,14 +9,14 @@ module SolidObjects
9
9
  # @rbs (Broadcast) -> String
10
10
  def self?.observable: (Broadcast) -> String
11
11
 
12
- # @rbs (Reference, Symbol | String, untyped) -> String
13
- def self?.observable_value: (Reference, Symbol | String, untyped) -> String
12
+ # @rbs (reference: Reference, name: Symbol | String, value: untyped) -> String
13
+ def self?.observable_value: (reference: Reference, name: Symbol | String, value: untyped) -> String
14
14
 
15
- # @rbs (ComponentRegistration, Integer, Integer) -> String
16
- def self?.component_refresh: (ComponentRegistration, Integer, Integer) -> String
15
+ # @rbs (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
16
+ def self?.component_refresh: (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
17
17
 
18
- # @rbs (Array[ComponentRegistration], Integer, Integer) -> String
19
- def self?.batch_refresh: (Array[ComponentRegistration], Integer, Integer) -> String
18
+ # @rbs (registrations: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> String
19
+ def self?.batch_refresh: (registrations: Array[ComponentRegistration], instance_id: Integer, revision: Integer) -> String
20
20
 
21
21
  # @rbs (Hash[String, untyped]) -> String
22
22
  def self?.state_payload: (Hash[String, untyped]) -> String
@@ -27,7 +27,7 @@ module SolidObjects
27
27
  # @rbs (untyped) -> String
28
28
  def self?.display_value: (untyped) -> String
29
29
 
30
- # @rbs (ComponentRegistration, Integer, Integer) -> String
31
- def self?.morph_component_refresh: (ComponentRegistration, Integer, Integer) -> String
30
+ # @rbs (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
31
+ def self?.morph_component_refresh: (registration: ComponentRegistration, instance_id: Integer, revision: Integer) -> String
32
32
  end
33
33
  end
@@ -2,5 +2,7 @@
2
2
 
3
3
  module SolidObjects
4
4
  class Broadcast < Record
5
+ # @rbs () -> bool
6
+ def broadcasts_value?: () -> bool
5
7
  end
6
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Carlson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-11 00:00:00.000000000 Z
11
+ date: 2026-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actioncable
@@ -312,6 +312,7 @@ files:
312
312
  - config/routes.rb
313
313
  - db/migrate/20260805000000_create_solid_objects_tables.rb
314
314
  - db/migrate/20260806000000_add_state_revision_to_solid_objects_instances.rb
315
+ - db/migrate/20260813000000_rename_message_dispatch_columns.rb
315
316
  - docs/adr/0001-postgresql-backend.md
316
317
  - docs/adr/0002-jsonb-actor-state.md
317
318
  - docs/adr/0003-mailbox-ordering.md
@@ -401,6 +402,7 @@ files:
401
402
  - lib/solid_objects/mailbox.rb
402
403
  - lib/solid_objects/message_pruner.rb
403
404
  - lib/solid_objects/message_reference.rb
405
+ - lib/solid_objects/operation_dispatcher.rb
404
406
  - lib/solid_objects/payload_broadcast.rb
405
407
  - lib/solid_objects/process_pruner.rb
406
408
  - lib/solid_objects/process_registry.rb
@@ -476,6 +478,7 @@ files:
476
478
  - sig/generated/lib/solid_objects/mailbox.rbs
477
479
  - sig/generated/lib/solid_objects/message_pruner.rbs
478
480
  - sig/generated/lib/solid_objects/message_reference.rbs
481
+ - sig/generated/lib/solid_objects/operation_dispatcher.rbs
479
482
  - sig/generated/lib/solid_objects/payload_broadcast.rbs
480
483
  - sig/generated/lib/solid_objects/process_pruner.rbs
481
484
  - sig/generated/lib/solid_objects/process_registry.rbs