solid_objects 0.4.3 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +54 -7
- data/app/assets/javascripts/solid_objects/component_refresh.js +124 -0
- data/app/controllers/solid_objects/components_controller.rb +31 -9
- data/app/helpers/solid_objects/actor_helper.rb +8 -1
- data/docs/adr/0009-realtime-updates.md +18 -1
- data/docs/architecture.md +34 -18
- data/docs/authorization.md +24 -0
- data/docs/correctness.md +27 -5
- data/docs/operations.md +20 -2
- data/docs/realtime.md +78 -13
- data/docs/roadmap.md +6 -5
- data/examples/application/app/views/chat_rooms/show.html.erb +3 -1
- data/lib/solid_objects/actor_view.rb +40 -13
- data/lib/solid_objects/component_registration.rb +61 -16
- data/lib/solid_objects/component_renderer.rb +14 -17
- data/lib/solid_objects/component_subscriptions.rb +7 -7
- data/lib/solid_objects/component_token.rb +70 -2
- data/lib/solid_objects/database_adapters/sqlite.rb +43 -5
- data/lib/solid_objects/doctor.rb +46 -8
- data/lib/solid_objects/dom_identity.rb +12 -3
- data/lib/solid_objects/engine.rb +7 -0
- data/lib/solid_objects/synchronous_invocation.rb +16 -1
- data/lib/solid_objects/turbo_stream_renderer.rb +14 -5
- data/lib/solid_objects/version.rb +1 -1
- data/sig/generated/controllers/solid_objects/components_controller.rbs +6 -0
- data/sig/generated/lib/solid_objects/actor_view.rbs +10 -4
- data/sig/generated/lib/solid_objects/component_registration.rbs +34 -10
- data/sig/generated/lib/solid_objects/component_renderer.rbs +4 -8
- data/sig/generated/lib/solid_objects/component_token.rbs +24 -2
- data/sig/generated/lib/solid_objects/database_adapters/sqlite.rbs +9 -0
- data/sig/generated/lib/solid_objects/doctor.rbs +12 -0
- data/sig/generated/lib/solid_objects/dom_identity.rbs +5 -2
- data/sig/generated/lib/solid_objects/synchronous_invocation.rbs +8 -0
- data/sig/generated/lib/solid_objects/turbo_stream_renderer.rbs +3 -0
- metadata +3 -2
|
@@ -7,23 +7,38 @@ module SolidObjects
|
|
|
7
7
|
PURPOSE = "solid_objects.actor_component"
|
|
8
8
|
MAXIMUM_TOKEN_BYTES = 16_384
|
|
9
9
|
MAXIMUM_DEPENDENCIES = 50
|
|
10
|
+
MAXIMUM_LOCALS = 50
|
|
11
|
+
MAXIMUM_COMPONENT_KEY_BYTES = 512
|
|
12
|
+
REFRESH_METHODS = %w[replace morph].freeze
|
|
13
|
+
RESERVED_LOCALS = %w[actor authorization_context component_key].freeze
|
|
14
|
+
RUBY_KEYWORDS = %w[
|
|
15
|
+
alias and begin break case class def defined do else elsif end ensure
|
|
16
|
+
false for if in module next nil not or redo rescue retry return self
|
|
17
|
+
super then true undef unless until when while yield
|
|
18
|
+
].freeze
|
|
10
19
|
|
|
11
20
|
module_function
|
|
12
21
|
|
|
13
|
-
# @rbs (reference: Reference, component_name: String, dependencies: Array[String], instance_id: Integer, revision: Integer, refresh_path: String) -> String
|
|
22
|
+
# @rbs (reference: Reference, component_name: String, dependencies: Array[String], instance_id: Integer, revision: Integer, refresh_path: String, ?component_key: untyped, ?locals: Hash[untyped, untyped], ?refresh_method: String | Symbol) -> String
|
|
14
23
|
def generate(
|
|
15
24
|
reference:,
|
|
16
25
|
component_name:,
|
|
17
26
|
dependencies:,
|
|
18
27
|
instance_id:,
|
|
19
28
|
revision:,
|
|
20
|
-
refresh_path
|
|
29
|
+
refresh_path:,
|
|
30
|
+
component_key: nil,
|
|
31
|
+
locals: {},
|
|
32
|
+
refresh_method: "replace"
|
|
21
33
|
)
|
|
22
34
|
payload = {
|
|
23
35
|
"actor_type" => reference.actor_type,
|
|
24
36
|
"actor_id" => reference.actor_id,
|
|
25
37
|
"component_name" => component_name,
|
|
38
|
+
"component_key" => Serialization.dump(component_key),
|
|
26
39
|
"dependencies" => dependencies,
|
|
40
|
+
"locals" => Serialization.dump(locals),
|
|
41
|
+
"refresh_method" => refresh_method.to_s,
|
|
27
42
|
"instance_id" => instance_id,
|
|
28
43
|
"revision" => revision,
|
|
29
44
|
"refresh_path" => refresh_path
|
|
@@ -41,6 +56,7 @@ module SolidObjects
|
|
|
41
56
|
end
|
|
42
57
|
|
|
43
58
|
payload = verifier.verified(token, purpose: PURPOSE)
|
|
59
|
+
apply_defaults!(payload)
|
|
44
60
|
validate_payload!(payload)
|
|
45
61
|
payload
|
|
46
62
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
|
@@ -54,6 +70,8 @@ module SolidObjects
|
|
|
54
70
|
payload["actor_id"].is_a?(String) &&
|
|
55
71
|
payload["component_name"].is_a?(String) &&
|
|
56
72
|
payload["dependencies"].is_a?(Array) &&
|
|
73
|
+
payload["locals"].is_a?(Hash) &&
|
|
74
|
+
payload["refresh_method"].is_a?(String) &&
|
|
57
75
|
payload["instance_id"].is_a?(Integer) &&
|
|
58
76
|
payload["revision"].is_a?(Integer) &&
|
|
59
77
|
payload["refresh_path"].is_a?(String)
|
|
@@ -61,7 +79,10 @@ module SolidObjects
|
|
|
61
79
|
end
|
|
62
80
|
|
|
63
81
|
validate_component_name!(payload.fetch("component_name"))
|
|
82
|
+
validate_component_key!(payload["component_key"])
|
|
64
83
|
validate_dependencies!(payload.fetch("dependencies"))
|
|
84
|
+
validate_locals!(payload.fetch("locals"))
|
|
85
|
+
validate_refresh_method!(payload.fetch("refresh_method"))
|
|
65
86
|
validate_revision!(
|
|
66
87
|
payload.fetch("instance_id"),
|
|
67
88
|
payload.fetch("revision")
|
|
@@ -71,6 +92,16 @@ module SolidObjects
|
|
|
71
92
|
end
|
|
72
93
|
private_class_method :validate_payload!
|
|
73
94
|
|
|
95
|
+
# @rbs (Hash[String, untyped]?) -> void
|
|
96
|
+
def apply_defaults!(payload)
|
|
97
|
+
return unless payload.is_a?(Hash)
|
|
98
|
+
|
|
99
|
+
payload["component_key"] = nil unless payload.key?("component_key")
|
|
100
|
+
payload["locals"] = {} unless payload.key?("locals")
|
|
101
|
+
payload["refresh_method"] = "replace" unless payload.key?("refresh_method")
|
|
102
|
+
end
|
|
103
|
+
private_class_method :apply_defaults!
|
|
104
|
+
|
|
74
105
|
# @rbs (String) -> void
|
|
75
106
|
def validate_component_name!(component_name)
|
|
76
107
|
return if component_name.match?(/\A[a-zA-Z0-9_]+\z/)
|
|
@@ -79,6 +110,20 @@ module SolidObjects
|
|
|
79
110
|
end
|
|
80
111
|
private_class_method :validate_component_name!
|
|
81
112
|
|
|
113
|
+
# @rbs (untyped) -> void
|
|
114
|
+
def validate_component_key!(component_key)
|
|
115
|
+
return if component_key.nil?
|
|
116
|
+
return if component_key.is_a?(Integer)
|
|
117
|
+
if component_key.is_a?(String) &&
|
|
118
|
+
component_key.bytesize.positive? &&
|
|
119
|
+
component_key.bytesize <= MAXIMUM_COMPONENT_KEY_BYTES
|
|
120
|
+
return
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
raise InvalidComponentToken, "invalid actor component key"
|
|
124
|
+
end
|
|
125
|
+
private_class_method :validate_component_key!
|
|
126
|
+
|
|
82
127
|
# @rbs (Array[untyped]) -> void
|
|
83
128
|
def validate_dependencies!(dependencies)
|
|
84
129
|
valid = dependencies.any? &&
|
|
@@ -91,6 +136,29 @@ module SolidObjects
|
|
|
91
136
|
end
|
|
92
137
|
private_class_method :validate_dependencies!
|
|
93
138
|
|
|
139
|
+
# @rbs (Hash[untyped, untyped]) -> void
|
|
140
|
+
def validate_locals!(locals)
|
|
141
|
+
valid = locals.length <= MAXIMUM_LOCALS &&
|
|
142
|
+
locals.keys.all? do |name|
|
|
143
|
+
name.is_a?(String) &&
|
|
144
|
+
name.match?(/\A[a-z_][a-zA-Z0-9_]*\z/) &&
|
|
145
|
+
!RESERVED_LOCALS.include?(name) &&
|
|
146
|
+
!RUBY_KEYWORDS.include?(name)
|
|
147
|
+
end
|
|
148
|
+
return if valid
|
|
149
|
+
|
|
150
|
+
raise InvalidComponentToken, "invalid actor component locals"
|
|
151
|
+
end
|
|
152
|
+
private_class_method :validate_locals!
|
|
153
|
+
|
|
154
|
+
# @rbs (String) -> void
|
|
155
|
+
def validate_refresh_method!(refresh_method)
|
|
156
|
+
return if REFRESH_METHODS.include?(refresh_method)
|
|
157
|
+
|
|
158
|
+
raise InvalidComponentToken, "invalid actor component refresh method"
|
|
159
|
+
end
|
|
160
|
+
private_class_method :validate_refresh_method!
|
|
161
|
+
|
|
94
162
|
# @rbs (Integer, Integer) -> void
|
|
95
163
|
def validate_revision!(instance_id, revision)
|
|
96
164
|
return unless instance_id.negative? || revision.negative?
|
|
@@ -67,11 +67,49 @@ module SolidObjects
|
|
|
67
67
|
def with_transaction_deadline(connection)
|
|
68
68
|
return yield unless SyncDeadline.active?
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
busy_wait = restorable_busy_wait(connection)
|
|
71
|
+
return yield unless busy_wait
|
|
72
|
+
|
|
73
|
+
begin
|
|
74
|
+
connection.execute("PRAGMA busy_timeout = 0")
|
|
75
|
+
yield
|
|
76
|
+
ensure
|
|
77
|
+
restore_busy_wait(connection, busy_wait)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @rbs (untyped) -> Hash[Symbol, untyped]?
|
|
82
|
+
def restorable_busy_wait(connection)
|
|
83
|
+
pragma_timeout = connection.select_value("PRAGMA busy_timeout").to_i
|
|
84
|
+
return { pragma_timeout: } if pragma_timeout.positive?
|
|
85
|
+
|
|
86
|
+
handler_timeout = configured_busy_handler_timeout(connection)
|
|
87
|
+
return nil unless handler_timeout
|
|
88
|
+
|
|
89
|
+
{ pragma_timeout:, handler_timeout: }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @rbs (untyped, Hash[Symbol, untyped]) -> void
|
|
93
|
+
def restore_busy_wait(connection, busy_wait)
|
|
94
|
+
handler_timeout = busy_wait[:handler_timeout]
|
|
95
|
+
if handler_timeout
|
|
96
|
+
connection.raw_connection.busy_handler_timeout = handler_timeout
|
|
97
|
+
return
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
connection.execute("PRAGMA busy_timeout = #{busy_wait.fetch(:pragma_timeout)}")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @rbs (untyped) -> Integer?
|
|
104
|
+
def configured_busy_handler_timeout(connection)
|
|
105
|
+
return nil unless connection.respond_to?(:raw_connection)
|
|
106
|
+
return nil unless connection.raw_connection.respond_to?(:busy_handler_timeout=)
|
|
107
|
+
|
|
108
|
+
pool = connection.respond_to?(:pool) ? connection.pool : nil
|
|
109
|
+
return nil unless pool.respond_to?(:db_config)
|
|
110
|
+
|
|
111
|
+
timeout = pool.db_config.configuration_hash[:timeout]
|
|
112
|
+
timeout&.to_i
|
|
75
113
|
end
|
|
76
114
|
|
|
77
115
|
# @rbs (Exception) -> bool
|
data/lib/solid_objects/doctor.rb
CHANGED
|
@@ -215,25 +215,63 @@ module SolidObjects
|
|
|
215
215
|
# @rbs () -> Check
|
|
216
216
|
def check_sync_round_trip
|
|
217
217
|
actor_id = SecureRandom.uuid
|
|
218
|
+
probe_registry = ProcessRegistry.new
|
|
219
|
+
check = run_sync_probe(actor_id, probe_registry)
|
|
220
|
+
leftovers = remove_probe_records(actor_id:, probe_registry:)
|
|
221
|
+
return check if leftovers.empty? || check.failed?
|
|
222
|
+
|
|
223
|
+
warn_check(
|
|
224
|
+
:sync_round_trip,
|
|
225
|
+
"#{check.message}; could not remove the #{leftovers.join(" and ")}"
|
|
226
|
+
)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# @rbs (String, ProcessRegistry) -> Check
|
|
230
|
+
def run_sync_probe(actor_id, probe_registry)
|
|
231
|
+
probe_registry.register(kind: "caller", metadata: { execution: "doctor" })
|
|
218
232
|
value = SecureRandom.hex(8)
|
|
219
|
-
process_registry = SolidObjects.caller_process.process_registry
|
|
220
|
-
reference = ProbeActor.ref(actor_id)
|
|
221
233
|
message_reference = Mailbox.new.enqueue(
|
|
222
|
-
|
|
234
|
+
ProbeActor.ref(actor_id),
|
|
223
235
|
:ping,
|
|
224
236
|
{ value: },
|
|
225
237
|
kind: "sync"
|
|
226
238
|
)
|
|
227
|
-
result = SynchronousInvocation
|
|
239
|
+
result = SynchronousInvocation
|
|
240
|
+
.new(process_registry: probe_registry)
|
|
241
|
+
.call(message_reference, timeout: 5.seconds)
|
|
228
242
|
raise Error, "unexpected round-trip result" unless result == value
|
|
229
243
|
|
|
230
244
|
pass(:sync_round_trip, "durable synchronous actor call completed without a worker")
|
|
231
245
|
rescue => error
|
|
232
246
|
fail_check(:sync_round_trip, "#{error.class}: #{error.message}")
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# @rbs (actor_id: String, probe_registry: ProcessRegistry) -> Array[String]
|
|
250
|
+
def remove_probe_records(actor_id:, probe_registry:)
|
|
251
|
+
leftovers = []
|
|
252
|
+
leftovers << "probe actor" unless delete_probe_actor(actor_id)
|
|
253
|
+
leftovers << "probe caller process" unless delete_probe_caller_process(probe_registry)
|
|
254
|
+
leftovers
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# @rbs (String) -> bool
|
|
258
|
+
def delete_probe_actor(actor_id)
|
|
259
|
+
Instance.where(actor_type: ProbeActor.actor_type, actor_id:).delete_all
|
|
260
|
+
true
|
|
261
|
+
rescue
|
|
262
|
+
false
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# @rbs (ProcessRegistry) -> bool
|
|
266
|
+
def delete_probe_caller_process(probe_registry)
|
|
267
|
+
process_record = probe_registry.process_record
|
|
268
|
+
return true unless process_record
|
|
269
|
+
|
|
270
|
+
probe_registry.stop
|
|
271
|
+
process_record.delete
|
|
272
|
+
true
|
|
273
|
+
rescue
|
|
274
|
+
false
|
|
237
275
|
end
|
|
238
276
|
|
|
239
277
|
# @rbs (Check, Check) -> bool
|
|
@@ -16,9 +16,12 @@ module SolidObjects
|
|
|
16
16
|
"#{scope(reference)}_observable_#{normalized_name(name)}"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# @rbs (Reference, Symbol | String) -> String
|
|
20
|
-
def component(reference, name)
|
|
21
|
-
"#{scope(reference)}_component_#{normalized_name(name)}"
|
|
19
|
+
# @rbs (Reference, Symbol | String, ?key: String | Integer?) -> String
|
|
20
|
+
def component(reference, name, key: nil)
|
|
21
|
+
identity = "#{scope(reference)}_component_#{normalized_name(name)}"
|
|
22
|
+
return identity unless key
|
|
23
|
+
|
|
24
|
+
"#{identity}_#{component_key_digest(key)}"
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
# @rbs (Reference) -> String
|
|
@@ -34,5 +37,11 @@ module SolidObjects
|
|
|
34
37
|
name.to_s.gsub(/[^a-zA-Z0-9_-]/, "_")
|
|
35
38
|
end
|
|
36
39
|
private_class_method :normalized_name
|
|
40
|
+
|
|
41
|
+
# @rbs (String | Integer) -> String
|
|
42
|
+
def component_key_digest(key)
|
|
43
|
+
Digest::SHA256.hexdigest(JSON.generate(key)).first(24)
|
|
44
|
+
end
|
|
45
|
+
private_class_method :component_key_digest
|
|
37
46
|
end
|
|
38
47
|
end
|
data/lib/solid_objects/engine.rb
CHANGED
|
@@ -26,6 +26,13 @@ module SolidObjects
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
initializer "solid_objects.assets" do |application|
|
|
30
|
+
next unless application.config.respond_to?(:assets)
|
|
31
|
+
next unless application.config.assets.respond_to?(:precompile)
|
|
32
|
+
|
|
33
|
+
application.config.assets.precompile << "solid_objects/component_refresh.js"
|
|
34
|
+
end
|
|
35
|
+
|
|
29
36
|
rake_tasks do
|
|
30
37
|
tasks_path = File.expand_path("../tasks", __dir__)
|
|
31
38
|
Dir[File.join(tasks_path, "**/*.rake")].sort.each { |task| load task }
|
|
@@ -6,6 +6,13 @@ require "solid_objects/sync_diagnostics"
|
|
|
6
6
|
|
|
7
7
|
module SolidObjects
|
|
8
8
|
class SynchronousInvocation
|
|
9
|
+
# @rbs @dedicated_process_registry: ProcessRegistry?
|
|
10
|
+
|
|
11
|
+
# @rbs (?process_registry: ProcessRegistry?) -> void
|
|
12
|
+
def initialize(process_registry: nil)
|
|
13
|
+
@dedicated_process_registry = process_registry
|
|
14
|
+
end
|
|
15
|
+
|
|
9
16
|
# @rbs (MessageReference, timeout: Numeric) -> untyped
|
|
10
17
|
def call(message_reference, timeout:)
|
|
11
18
|
return call_before_deadline(message_reference, timeout:) if SyncDeadline.active?
|
|
@@ -92,9 +99,17 @@ module SolidObjects
|
|
|
92
99
|
)
|
|
93
100
|
end
|
|
94
101
|
|
|
102
|
+
# @rbs () -> ProcessRegistry
|
|
103
|
+
def process_registry
|
|
104
|
+
dedicated_registry = @dedicated_process_registry
|
|
105
|
+
return SolidObjects.caller_process.process_registry unless dedicated_registry
|
|
106
|
+
|
|
107
|
+
dedicated_registry.tap(&:heartbeat)
|
|
108
|
+
end
|
|
109
|
+
|
|
95
110
|
# @rbs (Message, deadline: Float) -> Integer
|
|
96
111
|
def assist(message, deadline:)
|
|
97
|
-
process_registry =
|
|
112
|
+
process_registry = self.process_registry
|
|
98
113
|
activation = ActivationManager
|
|
99
114
|
.new(owner_id: process_registry.process_record.id)
|
|
100
115
|
.claim(instance_id: message.instance_id)
|
|
@@ -40,15 +40,14 @@ module SolidObjects
|
|
|
40
40
|
|
|
41
41
|
# @rbs (ComponentRegistration, Integer, Integer) -> String
|
|
42
42
|
def component_refresh(registration, instance_id, revision)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
43
|
+
return morph_component_refresh(registration, instance_id, revision) if registration.morph?
|
|
44
|
+
|
|
45
|
+
target = registration.dom_id
|
|
47
46
|
source = ERB::Util.html_escape(
|
|
48
47
|
registration.refresh_url(instance_id, revision)
|
|
49
48
|
)
|
|
50
49
|
revision_value = "#{instance_id}:#{revision}"
|
|
51
|
-
%(<turbo-stream action="replace" target="#{target}"><template><turbo-frame id="#{target}" src="#{source}" data-solid-objects-revision="#{revision_value}"></turbo-frame></template></turbo-stream>)
|
|
50
|
+
%(<turbo-stream action="replace" target="#{target}"><template><turbo-frame id="#{target}" src="#{source}" data-solid-objects-revision="#{revision_value}" data-solid-objects-refresh="replace"></turbo-frame></template></turbo-stream>)
|
|
52
51
|
end
|
|
53
52
|
|
|
54
53
|
# @rbs (String) -> Hash[String, untyped]?
|
|
@@ -75,5 +74,15 @@ module SolidObjects
|
|
|
75
74
|
JSON.generate(value)
|
|
76
75
|
end
|
|
77
76
|
private_class_method :display_value
|
|
77
|
+
|
|
78
|
+
# @rbs (ComponentRegistration, Integer, Integer) -> String
|
|
79
|
+
def morph_component_refresh(registration, instance_id, revision)
|
|
80
|
+
source = ERB::Util.html_escape(
|
|
81
|
+
registration.refresh_url(instance_id, revision)
|
|
82
|
+
)
|
|
83
|
+
scope = DomIdentity.scope(registration.reference)
|
|
84
|
+
%(<turbo-stream action="append" target="#{scope}"><template><solid-objects-refresh data-target="#{registration.dom_id}" data-source="#{source}" data-refresh-method="morph"></solid-objects-refresh></template></turbo-stream>)
|
|
85
|
+
end
|
|
86
|
+
private_class_method :morph_component_refresh
|
|
78
87
|
end
|
|
79
88
|
end
|
|
@@ -7,6 +7,12 @@ module SolidObjects
|
|
|
7
7
|
|
|
8
8
|
private
|
|
9
9
|
|
|
10
|
+
# @rbs (Hash[Symbol, untyped]) -> void
|
|
11
|
+
def refresh: (Hash[Symbol, untyped]) -> void
|
|
12
|
+
|
|
13
|
+
# @rbs (ComponentRegistration) -> Hash[Symbol, untyped]
|
|
14
|
+
def registration_payload: (ComponentRegistration) -> Hash[Symbol, untyped]
|
|
15
|
+
|
|
10
16
|
# @rbs () -> Array[Integer]
|
|
11
17
|
def requested_revision_key: () -> Array[Integer]
|
|
12
18
|
|
|
@@ -22,8 +22,8 @@ module SolidObjects
|
|
|
22
22
|
# @rbs (Symbol | String) -> untyped
|
|
23
23
|
def value: (Symbol | String) -> untyped
|
|
24
24
|
|
|
25
|
-
# @rbs (Symbol | String, ?observes: Symbol | String | Array[Symbol | String]?, ?partial: String?) -> untyped
|
|
26
|
-
def component: (Symbol | String, ?observes: Symbol | String | Array[Symbol | String]?, ?partial: String?) -> untyped
|
|
25
|
+
# @rbs (Symbol | String, ?observes: Symbol | String | Array[Symbol | String]?, ?partial: String?, ?key: untyped, ?locals: Hash[untyped, untyped], ?refresh: String | Symbol) -> untyped
|
|
26
|
+
def component: (Symbol | String, ?observes: Symbol | String | Array[Symbol | String]?, ?partial: String?, ?key: untyped, ?locals: Hash[untyped, untyped], ?refresh: String | Symbol) -> untyped
|
|
27
27
|
|
|
28
28
|
# @rbs () -> Array[String]
|
|
29
29
|
def component_tokens: () -> Array[String]
|
|
@@ -31,6 +31,9 @@ module SolidObjects
|
|
|
31
31
|
# @rbs () -> Array[String]
|
|
32
32
|
def scalar_observable_names: () -> Array[String]
|
|
33
33
|
|
|
34
|
+
# @rbs () -> bool
|
|
35
|
+
def morph_components?: () -> bool
|
|
36
|
+
|
|
34
37
|
# @rbs () -> State
|
|
35
38
|
def state: () -> State
|
|
36
39
|
|
|
@@ -73,8 +76,11 @@ module SolidObjects
|
|
|
73
76
|
# @rbs (Array[String]) -> void
|
|
74
77
|
def validate_dependencies!: (Array[String]) -> void
|
|
75
78
|
|
|
76
|
-
# @rbs (
|
|
77
|
-
def ensure_unique_component!: (
|
|
79
|
+
# @rbs (ComponentRegistration) -> void
|
|
80
|
+
def ensure_unique_component!: (ComponentRegistration) -> void
|
|
81
|
+
|
|
82
|
+
# @rbs (key: untyped, locals: Hash[untyped, untyped], refresh: String | Symbol) -> void
|
|
83
|
+
def validate_static_options!: (key: untyped, locals: Hash[untyped, untyped], refresh: String | Symbol) -> void
|
|
78
84
|
|
|
79
85
|
# @rbs () -> Proc | ComponentPathResolver
|
|
80
86
|
def component_path_resolver: () -> Proc
|
|
@@ -2,26 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidObjects
|
|
4
4
|
class ComponentRegistration
|
|
5
|
-
@
|
|
5
|
+
@token: String
|
|
6
6
|
|
|
7
|
-
@
|
|
7
|
+
@refresh_path: String
|
|
8
8
|
|
|
9
|
-
@
|
|
9
|
+
@revision: Integer
|
|
10
10
|
|
|
11
11
|
@instance_id: Integer
|
|
12
12
|
|
|
13
|
-
@
|
|
13
|
+
@refresh_method: String
|
|
14
14
|
|
|
15
|
-
@
|
|
15
|
+
@locals: Hash[String, untyped]
|
|
16
16
|
|
|
17
|
-
@
|
|
17
|
+
@dependencies: Array[String]
|
|
18
|
+
|
|
19
|
+
@component_key: String | Integer?
|
|
20
|
+
|
|
21
|
+
@component_name: String
|
|
22
|
+
|
|
23
|
+
@reference: Reference
|
|
18
24
|
|
|
19
25
|
attr_reader reference: untyped
|
|
20
26
|
|
|
21
27
|
attr_reader component_name: untyped
|
|
22
28
|
|
|
29
|
+
attr_reader component_key: untyped
|
|
30
|
+
|
|
23
31
|
attr_reader dependencies: untyped
|
|
24
32
|
|
|
33
|
+
attr_reader locals: untyped
|
|
34
|
+
|
|
35
|
+
attr_reader refresh_method: untyped
|
|
36
|
+
|
|
25
37
|
attr_reader instance_id: untyped
|
|
26
38
|
|
|
27
39
|
attr_reader revision: untyped
|
|
@@ -30,21 +42,33 @@ module SolidObjects
|
|
|
30
42
|
|
|
31
43
|
attr_reader token: untyped
|
|
32
44
|
|
|
33
|
-
# @rbs (reference: Reference, component_name: String, dependencies: Array[String], instance_id: Integer, revision: Integer, refresh_path: String, token: String) -> void
|
|
34
|
-
def initialize: (reference: Reference, component_name: String, dependencies: Array[String], instance_id: Integer, revision: Integer, refresh_path: String, token: String) -> void
|
|
45
|
+
# @rbs (reference: Reference, component_name: String, component_key: String | Integer?, dependencies: Array[String], locals: Hash[String, untyped], refresh_method: String, instance_id: Integer, revision: Integer, refresh_path: String, token: String) -> void
|
|
46
|
+
def initialize: (reference: Reference, component_name: String, component_key: String | Integer?, dependencies: Array[String], locals: Hash[String, untyped], refresh_method: String, instance_id: Integer, revision: Integer, refresh_path: String, token: String) -> void
|
|
35
47
|
|
|
36
|
-
# @rbs (reference: Reference, component_name: String, dependencies: Array[String], snapshot: ActorSnapshot, refresh_path: String) -> ComponentRegistration
|
|
37
|
-
def self.issue: (reference: Reference, component_name: String, dependencies: Array[String], snapshot: ActorSnapshot, refresh_path: String) -> ComponentRegistration
|
|
48
|
+
# @rbs (reference: Reference, component_name: String, component_key: untyped, dependencies: Array[String], locals: Hash[untyped, untyped], refresh_method: String | Symbol, snapshot: ActorSnapshot, refresh_path: String) -> ComponentRegistration
|
|
49
|
+
def self.issue: (reference: Reference, component_name: String, component_key: untyped, dependencies: Array[String], locals: Hash[untyped, untyped], refresh_method: String | Symbol, snapshot: ActorSnapshot, refresh_path: String) -> ComponentRegistration
|
|
38
50
|
|
|
39
51
|
# @rbs (String) -> ComponentRegistration
|
|
40
52
|
def self.from_token: (String) -> ComponentRegistration
|
|
41
53
|
|
|
54
|
+
# @rbs (Hash[String, untyped], token: String) -> ComponentRegistration
|
|
55
|
+
private def self.build: (Hash[String, untyped], token: String) -> ComponentRegistration
|
|
56
|
+
|
|
42
57
|
# @rbs (Reference, Array[String]) -> void
|
|
43
58
|
private def self.validate_dependencies!: (Reference, Array[String]) -> void
|
|
44
59
|
|
|
45
60
|
# @rbs () -> Array[Integer]
|
|
46
61
|
def revision_key: () -> Array[Integer]
|
|
47
62
|
|
|
63
|
+
# @rbs () -> String
|
|
64
|
+
def dom_id: () -> String
|
|
65
|
+
|
|
66
|
+
# @rbs () -> bool
|
|
67
|
+
def morph?: () -> bool
|
|
68
|
+
|
|
69
|
+
# @rbs () -> Hash[String, untyped]
|
|
70
|
+
def authorization_arguments: () -> Hash[String, untyped]
|
|
71
|
+
|
|
48
72
|
# @rbs (Integer, Integer) -> String
|
|
49
73
|
def refresh_url: (Integer, Integer) -> String
|
|
50
74
|
end
|
|
@@ -4,16 +4,14 @@ module SolidObjects
|
|
|
4
4
|
class ComponentRenderer
|
|
5
5
|
@snapshot: ActorSnapshot
|
|
6
6
|
|
|
7
|
-
@
|
|
8
|
-
|
|
9
|
-
@dependencies: Array[String]
|
|
7
|
+
@registration: ComponentRegistration
|
|
10
8
|
|
|
11
9
|
@view_context: untyped
|
|
12
10
|
|
|
13
11
|
@authorization_context: untyped
|
|
14
12
|
|
|
15
|
-
# @rbs (snapshot: ActorSnapshot,
|
|
16
|
-
def initialize: (snapshot: ActorSnapshot,
|
|
13
|
+
# @rbs (snapshot: ActorSnapshot, registration: ComponentRegistration, view_context: untyped, authorization_context: untyped) -> void
|
|
14
|
+
def initialize: (snapshot: ActorSnapshot, registration: ComponentRegistration, view_context: untyped, authorization_context: untyped) -> void
|
|
17
15
|
|
|
18
16
|
# @rbs () -> untyped
|
|
19
17
|
def call: () -> untyped
|
|
@@ -22,9 +20,7 @@ module SolidObjects
|
|
|
22
20
|
|
|
23
21
|
attr_reader snapshot: untyped
|
|
24
22
|
|
|
25
|
-
attr_reader
|
|
26
|
-
|
|
27
|
-
attr_reader dependencies: untyped
|
|
23
|
+
attr_reader registration: untyped
|
|
28
24
|
|
|
29
25
|
attr_reader view_context: untyped
|
|
30
26
|
|
|
@@ -8,8 +8,18 @@ module SolidObjects
|
|
|
8
8
|
|
|
9
9
|
MAXIMUM_DEPENDENCIES: ::Integer
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
MAXIMUM_LOCALS: ::Integer
|
|
12
|
+
|
|
13
|
+
MAXIMUM_COMPONENT_KEY_BYTES: ::Integer
|
|
14
|
+
|
|
15
|
+
REFRESH_METHODS: untyped
|
|
16
|
+
|
|
17
|
+
RESERVED_LOCALS: untyped
|
|
18
|
+
|
|
19
|
+
RUBY_KEYWORDS: untyped
|
|
20
|
+
|
|
21
|
+
# @rbs (reference: Reference, component_name: String, dependencies: Array[String], instance_id: Integer, revision: Integer, refresh_path: String, ?component_key: untyped, ?locals: Hash[untyped, untyped], ?refresh_method: String | Symbol) -> String
|
|
22
|
+
def self?.generate: (reference: Reference, component_name: String, dependencies: Array[String], instance_id: Integer, revision: Integer, refresh_path: String, ?component_key: untyped, ?locals: Hash[untyped, untyped], ?refresh_method: String | Symbol) -> String
|
|
13
23
|
|
|
14
24
|
# @rbs (String) -> Hash[String, untyped]
|
|
15
25
|
def self?.verify: (String) -> Hash[String, untyped]
|
|
@@ -17,12 +27,24 @@ module SolidObjects
|
|
|
17
27
|
# @rbs (Hash[String, untyped]) -> Hash[String, untyped]
|
|
18
28
|
def self?.validate_payload!: (Hash[String, untyped]) -> Hash[String, untyped]
|
|
19
29
|
|
|
30
|
+
# @rbs (Hash[String, untyped]?) -> void
|
|
31
|
+
def self?.apply_defaults!: (Hash[String, untyped]?) -> void
|
|
32
|
+
|
|
20
33
|
# @rbs (String) -> void
|
|
21
34
|
def self?.validate_component_name!: (String) -> void
|
|
22
35
|
|
|
36
|
+
# @rbs (untyped) -> void
|
|
37
|
+
def self?.validate_component_key!: (untyped) -> void
|
|
38
|
+
|
|
23
39
|
# @rbs (Array[untyped]) -> void
|
|
24
40
|
def self?.validate_dependencies!: (Array[untyped]) -> void
|
|
25
41
|
|
|
42
|
+
# @rbs (Hash[untyped, untyped]) -> void
|
|
43
|
+
def self?.validate_locals!: (Hash[untyped, untyped]) -> void
|
|
44
|
+
|
|
45
|
+
# @rbs (String) -> void
|
|
46
|
+
def self?.validate_refresh_method!: (String) -> void
|
|
47
|
+
|
|
26
48
|
# @rbs (Integer, Integer) -> void
|
|
27
49
|
def self?.validate_revision!: (Integer, Integer) -> void
|
|
28
50
|
|
|
@@ -26,6 +26,15 @@ module SolidObjects
|
|
|
26
26
|
# @rbs (untyped) { () -> untyped } -> untyped
|
|
27
27
|
def with_transaction_deadline: (untyped) { () -> untyped } -> untyped
|
|
28
28
|
|
|
29
|
+
# @rbs (untyped) -> Hash[Symbol, untyped]?
|
|
30
|
+
def restorable_busy_wait: (untyped) -> Hash[Symbol, untyped]?
|
|
31
|
+
|
|
32
|
+
# @rbs (untyped, Hash[Symbol, untyped]) -> void
|
|
33
|
+
def restore_busy_wait: (untyped, Hash[Symbol, untyped]) -> void
|
|
34
|
+
|
|
35
|
+
# @rbs (untyped) -> Integer?
|
|
36
|
+
def configured_busy_handler_timeout: (untyped) -> Integer?
|
|
37
|
+
|
|
29
38
|
# @rbs (Exception) -> bool
|
|
30
39
|
def deadline_error?: (Exception) -> bool
|
|
31
40
|
|
|
@@ -78,6 +78,18 @@ module SolidObjects
|
|
|
78
78
|
# @rbs () -> Check
|
|
79
79
|
def check_sync_round_trip: () -> Check
|
|
80
80
|
|
|
81
|
+
# @rbs (String, ProcessRegistry) -> Check
|
|
82
|
+
def run_sync_probe: (String, ProcessRegistry) -> Check
|
|
83
|
+
|
|
84
|
+
# @rbs (actor_id: String, probe_registry: ProcessRegistry) -> Array[String]
|
|
85
|
+
def remove_probe_records: (actor_id: String, probe_registry: ProcessRegistry) -> Array[String]
|
|
86
|
+
|
|
87
|
+
# @rbs (String) -> bool
|
|
88
|
+
def delete_probe_actor: (String) -> bool
|
|
89
|
+
|
|
90
|
+
# @rbs (ProcessRegistry) -> bool
|
|
91
|
+
def delete_probe_caller_process: (ProcessRegistry) -> bool
|
|
92
|
+
|
|
81
93
|
# @rbs (Check, Check) -> bool
|
|
82
94
|
def ready_for_round_trip?: (Check, Check) -> bool
|
|
83
95
|
|
|
@@ -8,13 +8,16 @@ module SolidObjects
|
|
|
8
8
|
# @rbs (Reference, Symbol | String) -> String
|
|
9
9
|
def self?.observable: (Reference, Symbol | String) -> String
|
|
10
10
|
|
|
11
|
-
# @rbs (Reference, Symbol | String) -> String
|
|
12
|
-
def self?.component: (Reference, Symbol | String) -> String
|
|
11
|
+
# @rbs (Reference, Symbol | String, ?key: String | Integer?) -> String
|
|
12
|
+
def self?.component: (Reference, Symbol | String, ?key: String | Integer?) -> String
|
|
13
13
|
|
|
14
14
|
# @rbs (Reference) -> String
|
|
15
15
|
def self?.identity_digest: (Reference) -> String
|
|
16
16
|
|
|
17
17
|
# @rbs (Symbol | String) -> String
|
|
18
18
|
def self?.normalized_name: (Symbol | String) -> String
|
|
19
|
+
|
|
20
|
+
# @rbs (String | Integer) -> String
|
|
21
|
+
def self?.component_key_digest: (String | Integer) -> String
|
|
19
22
|
end
|
|
20
23
|
end
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidObjects
|
|
4
4
|
class SynchronousInvocation
|
|
5
|
+
@dedicated_process_registry: ProcessRegistry?
|
|
6
|
+
|
|
7
|
+
# @rbs (?process_registry: ProcessRegistry?) -> void
|
|
8
|
+
def initialize: (?process_registry: ProcessRegistry?) -> void
|
|
9
|
+
|
|
5
10
|
# @rbs (MessageReference, timeout: Numeric) -> untyped
|
|
6
11
|
def call: (MessageReference, timeout: Numeric) -> untyped
|
|
7
12
|
|
|
@@ -22,6 +27,9 @@ module SolidObjects
|
|
|
22
27
|
# @rbs (Message) -> bot
|
|
23
28
|
def raise_rejection: (Message) -> bot
|
|
24
29
|
|
|
30
|
+
# @rbs () -> ProcessRegistry
|
|
31
|
+
def process_registry: () -> ProcessRegistry
|
|
32
|
+
|
|
25
33
|
# @rbs (Message, deadline: Float) -> Integer
|
|
26
34
|
def assist: (Message, deadline: Float) -> Integer
|
|
27
35
|
|