Blog ·
Solid Objects 1.0
Version 1.0 sets the public API promise for the Ruby on Rails gem and the Node.js package.
I released Solid Objects 1.0.0 for Ruby on Rails and Node.js under the MIT license. Solid Objects is a SQL-backed virtual actor library with stable actor identities, durable state, ordered operations, and automatic activation. State lives in the SQLite, PostgreSQL, or MySQL database that the application already uses.
What version 1.0 promises, and what it does not
The public API follows Semantic Versioning from 1.0.0. A patch release corrects defects. A minor release adds behavior without a public API break. Only a major release can break code that uses the public API.
The README and docs/ files in each repository define the public API. The new
docs/versioning.md files state the promise and its limits for
Rails
and
Node.js.
The promise excludes undocumented classes and exports, database schema, error message
text, and log text. Error classes remain within the promise. A minor release can add
tables, columns, and indexes, and supplies the migration. The npm package's Cloudflare
Durable Objects backend, solid-objects/cloudflare, stays experimental and
outside the promise.
A minor release can raise the minimum version of a language runtime or a database. It does this only for a version that its own project no longer supports. A patch release does not raise a minimum version.
Version 1.0 is a promise about the API. It is not a claim of measured scale.
One first-party application with more than 100,000 users runs it in production. That is a count of users, not a measure of load. I know of no production use by other people.
The project has one maintainer. The benchmarks in the repositories are development measurements and do not guarantee capacity. Longer soak tests remain open work.
Both runtimes now have the same core capabilities. The JavaScript repository records each
capability, and each difference, in docs/parity.md. Tests run against SQLite,
PostgreSQL, and MySQL.
The last breaking change
schedule returns an object. A reminder exists only after code calls an
operation on that object.
Before 1.0, a turn that called no operation on that object stored no reminder and gave no error. The intended hold or timeout did not exist. My own blog included this mistake in a code sample. I corrected that sample.
The wrong call stops after the arguments: schedule(at: time, key: buyer) in
Ruby, and this.schedule({ at: holdEnd, key: buyer }) in TypeScript. The
correct call names an operation on the result.
schedule(at: 10.minutes.from_now, key: buyer).expire(buyer:)
this.schedule({ at: holdEnd, key: buyer }).expire({ buyer })
From 1.0, that mistake raises ScheduleWithoutOperation, or
SolidObjects::ScheduleWithoutOperation in Ruby. The runtime does not retry
the turn. The message becomes a dead letter. The turn commits no state and no reminder.
A turn can keep the object and call an operation later in the same turn. Correct code does not change.
An observable cannot call schedule, with or without an operation. The turn
that reads the observable fails with QueryMutatedState.
The 0.x releases changed the API between minor versions. A version below 1.0 tells readers to expect that. This mistake was the last case where wrong code failed with no error. With this correction, I am ready to stop API breaks.
How to upgrade
-
Before the upgrade, find each
schedulecall in actors. Confirm that an operation follows each call in the same turn. -
For Rails, run
bundle update solid_objects, thenbin/rails solid_objects:doctor. - For Node.js, run
npm install solid-objects@latest.
The doctor has a new json check. At boot, the gem also warns if Active
Support cannot decode JSON with the installed json gem. This affects
json 3.x on Rails older than 8.1.4. Add gem "json", "~> 2" to
the Gemfile, or use a newer Rails release.
Version 1.0.0 changes no schema or configuration.
What comes next
I will run longer soak tests and benchmarks with documented PostgreSQL and MySQL
configuration. The commercial packages solid_objects_pro and
@solidobjects/pro will follow the open-source packages at 1.0.0.