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.
@@ -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,8 @@
1
+ # rbs_inline: enabled
2
+
3
+ class ShipmentJob < ApplicationJob
4
+ def perform(order_id:)
5
+ order = Order.find(order_id)
6
+ ShippingProvider.create_shipment(idempotency_key: "order-#{order.id}", order_reference: order.reference)
7
+ end
8
+ 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.
@@ -1,5 +1,5 @@
1
1
  # rbs_inline: enabled
2
2
 
3
3
  module SolidObjects
4
- VERSION = "0.17.1"
4
+ VERSION = "0.17.3"
5
5
  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.17.1
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-08 00:00:00.000000000 Z
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