solid_objects 0.17.1 → 0.17.3
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 +34 -0
- data/README.md +13 -1
- data/docs/agents.md +27 -0
- data/docs/guides/expiring-reservations.md +175 -0
- data/docs/guides/ordered-jobs.md +232 -0
- data/docs/guides/race-conditions.md +236 -0
- data/docs/guides/transactional-outbox.md +156 -0
- data/examples/guides/expiring_reservations/seat_inventory.rb +81 -0
- data/examples/guides/ordered_jobs/account.rb +23 -0
- data/examples/guides/ordered_jobs/apply_entry_job.rb +9 -0
- data/examples/guides/ordered_jobs/apply_entry_unordered_job.rb +7 -0
- data/examples/guides/ordered_jobs/create_ledger_entries.rb +14 -0
- data/examples/guides/ordered_jobs/ledger_account.rb +22 -0
- data/examples/guides/ordered_jobs/ledger_entry.rb +4 -0
- data/examples/guides/ordered_jobs/solid_objects.rb +10 -0
- data/examples/guides/race_conditions/event.rb +15 -0
- data/examples/guides/race_conditions/event_tickets.rb +66 -0
- data/examples/guides/transactional_outbox/checkout.rb +22 -0
- data/examples/guides/transactional_outbox/order.rb +17 -0
- data/examples/guides/transactional_outbox/outbox_message.rb +14 -0
- data/examples/guides/transactional_outbox/shipment_job.rb +8 -0
- data/examples/guides/transactional_outbox/solid_objects.rb +12 -0
- data/examples/quickstart/README.md +3 -0
- data/lib/solid_objects/version.rb +1 -1
- metadata +23 -3
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
2
|
+
|
|
3
|
+
class Checkout < SolidObjects::Actor
|
|
4
|
+
attribute :status, default: "open"
|
|
5
|
+
attribute :total_cents, default: 0
|
|
6
|
+
attribute :shipment_id, default: nil
|
|
7
|
+
|
|
8
|
+
def place(total_cents:)
|
|
9
|
+
return status unless status == "open"
|
|
10
|
+
|
|
11
|
+
self.status = "placed"
|
|
12
|
+
self.total_cents = total_cents
|
|
13
|
+
commit_action(:record_order, reference: actor_id, total_cents:)
|
|
14
|
+
emit(:request_shipment, order_reference: actor_id, on_success: :shipment_requested)
|
|
15
|
+
status
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def shipment_requested(effect_id:, arguments:, result:)
|
|
19
|
+
self.status = "shipping"
|
|
20
|
+
self.shipment_id = result.fetch("shipment_id")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
2
|
+
|
|
3
|
+
class Order < ApplicationRecord
|
|
4
|
+
def self.place_and_enqueue!(reference:, total_cents:)
|
|
5
|
+
order = create!(reference:, total_cents:)
|
|
6
|
+
ShipmentJob.perform_later(order_id: order.id)
|
|
7
|
+
order
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.place_with_outbox!(reference:, total_cents:)
|
|
11
|
+
transaction do
|
|
12
|
+
order = create!(reference:, total_cents:)
|
|
13
|
+
OutboxMessage.create!(name: "request_shipment", arguments: { "order_id" => order.id })
|
|
14
|
+
order
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
2
|
+
|
|
3
|
+
class OutboxMessage < ApplicationRecord
|
|
4
|
+
JOBS = { "request_shipment" => ShipmentJob }.freeze
|
|
5
|
+
|
|
6
|
+
scope :pending, -> { where(delivered_at: nil).order(:id) }
|
|
7
|
+
|
|
8
|
+
def self.relay(limit: 100)
|
|
9
|
+
pending.limit(limit).each do |message|
|
|
10
|
+
JOBS.fetch(message.name).perform_later(**message.arguments.symbolize_keys)
|
|
11
|
+
message.update!(delivered_at: Time.current)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# rbs_inline: enabled
|
|
2
|
+
|
|
3
|
+
SolidObjects.register_commit_action(:record_order) do |arguments, _context|
|
|
4
|
+
Order.create!(reference: arguments.fetch("reference"), total_cents: arguments.fetch("total_cents"))
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
SolidObjects.register_effect(:request_shipment) do |arguments, context|
|
|
8
|
+
ShippingProvider.create_shipment(
|
|
9
|
+
idempotency_key: context.id,
|
|
10
|
+
order_reference: arguments.fetch("order_reference")
|
|
11
|
+
)
|
|
12
|
+
end
|
|
@@ -46,6 +46,9 @@ bin/rails db:migrate
|
|
|
46
46
|
bin/rails solid_objects:doctor
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
`bundle add solid_objects` installs the current release. Do not pin an older
|
|
50
|
+
version from memory; the API changed between releases.
|
|
51
|
+
|
|
49
52
|
The generator writes `config/initializers/solid_objects.rb` and copies the
|
|
50
53
|
migrations. The migrations add the Solid Objects tables to the application's
|
|
51
54
|
existing database.
|
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.17.
|
|
4
|
+
version: 0.17.3
|
|
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-10-
|
|
11
|
+
date: 2026-10-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actioncable
|
|
@@ -280,7 +280,8 @@ description: 'Solid Objects is a SQL-backed virtual actor library for Ruby on Ra
|
|
|
280
280
|
with durable state, ordered operations, and automatic activation. It brings the
|
|
281
281
|
Cloudflare Durable Objects programming model to Rails: addressable objects with
|
|
282
282
|
ordered mailboxes, fenced activation, per-object reminders, transactional effects,
|
|
283
|
-
and reactive ERB. It runs on MySQL, PostgreSQL, and SQLite without Redis
|
|
283
|
+
and reactive ERB. It runs on MySQL, PostgreSQL, and SQLite without Redis, and requires
|
|
284
|
+
Ruby 3.3 or newer and Rails 7.1 or newer.'
|
|
284
285
|
email:
|
|
285
286
|
executables:
|
|
286
287
|
- solid_objects
|
|
@@ -361,6 +362,10 @@ files:
|
|
|
361
362
|
- docs/development.md
|
|
362
363
|
- docs/effect-recovery.md
|
|
363
364
|
- docs/fit.md
|
|
365
|
+
- docs/guides/expiring-reservations.md
|
|
366
|
+
- docs/guides/ordered-jobs.md
|
|
367
|
+
- docs/guides/race-conditions.md
|
|
368
|
+
- docs/guides/transactional-outbox.md
|
|
364
369
|
- docs/implementation-plan.md
|
|
365
370
|
- docs/local-testing.md
|
|
366
371
|
- docs/migrating-existing-state.md
|
|
@@ -390,6 +395,21 @@ files:
|
|
|
390
395
|
- examples/at_least_once/demo.rb
|
|
391
396
|
- examples/at_least_once/effect_worker.rb
|
|
392
397
|
- examples/at_least_once/sink.rb
|
|
398
|
+
- examples/guides/expiring_reservations/seat_inventory.rb
|
|
399
|
+
- examples/guides/ordered_jobs/account.rb
|
|
400
|
+
- examples/guides/ordered_jobs/apply_entry_job.rb
|
|
401
|
+
- examples/guides/ordered_jobs/apply_entry_unordered_job.rb
|
|
402
|
+
- examples/guides/ordered_jobs/create_ledger_entries.rb
|
|
403
|
+
- examples/guides/ordered_jobs/ledger_account.rb
|
|
404
|
+
- examples/guides/ordered_jobs/ledger_entry.rb
|
|
405
|
+
- examples/guides/ordered_jobs/solid_objects.rb
|
|
406
|
+
- examples/guides/race_conditions/event.rb
|
|
407
|
+
- examples/guides/race_conditions/event_tickets.rb
|
|
408
|
+
- examples/guides/transactional_outbox/checkout.rb
|
|
409
|
+
- examples/guides/transactional_outbox/order.rb
|
|
410
|
+
- examples/guides/transactional_outbox/outbox_message.rb
|
|
411
|
+
- examples/guides/transactional_outbox/shipment_job.rb
|
|
412
|
+
- examples/guides/transactional_outbox/solid_objects.rb
|
|
393
413
|
- examples/quickstart/README.md
|
|
394
414
|
- examples/quickstart/app/actors/ticket_sale.rb
|
|
395
415
|
- examples/quickstart/smoke.rb
|