solid-objects 1.0.4 → 1.0.6
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.
- package/CHANGELOG.md +58 -0
- package/README.md +7 -0
- package/dist/actor-runtime.d.ts +3 -0
- package/dist/actor-runtime.d.ts.map +1 -1
- package/dist/database/sqlite.d.ts +6 -0
- package/dist/database/sqlite.d.ts.map +1 -1
- package/dist/database/sqlite.js +23 -2
- package/dist/database/sqlite.js.map +1 -1
- package/dist/runtime.d.ts +2 -7
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/agents.md +12 -5
- package/docs/api.md +61 -13
- package/docs/benchmarks.md +208 -69
- package/docs/compare/ai-agents.md +252 -0
- package/docs/compare/dbos.md +14 -3
- package/docs/compare/graphile-worker.md +13 -3
- package/docs/compare/restate.md +14 -4
- package/docs/compare/rivetkit.md +2 -3
- package/docs/comparisons.md +1 -0
- package/docs/configuration.md +22 -3
- package/docs/correctness.md +7 -7
- package/docs/guides/persistent-rooms.md +1 -1
- package/docs/guides/race-conditions.md +1 -1
- package/docs/parity.md +7 -2
- package/docs/virtual-actors.md +6 -7
- package/package.json +5 -4
package/docs/compare/dbos.md
CHANGED
|
@@ -24,6 +24,16 @@ The DBOS facts come from the [DBOS documentation](https://docs.dbos.dev) and the
|
|
|
24
24
|
|
|
25
25
|
Two DBOS pages differ on more than one process. The FAQ says "Conductor is required for correct workflow recovery in applications that use more than one process". The recovery page describes recovery without Conductor: each process has an executor ID, and a restarted process recovers its own pending workflows.
|
|
26
26
|
|
|
27
|
+
## How do durable sleep, send, and recv work in DBOS?
|
|
28
|
+
|
|
29
|
+
`DBOS.sleep` is a durable sleep inside a workflow. It takes milliseconds. DBOS "saves the wakeup time in the database so that even if the workflow is interrupted and restarted multiple times while sleeping, it still wakes up on schedule" ([DBOS workflow tutorial](https://docs.dbos.dev/typescript/tutorials/workflow-tutorial), checked October 18, 2026). `DBOS.send` sends a message to a workflow, and `DBOS.recv` in that workflow waits for it. "Messages are dequeued first-in, first-out from a queue associated with the topic" ([DBOS methods reference](https://docs.dbos.dev/typescript/reference/methods)).
|
|
30
|
+
|
|
31
|
+
- `DBOS.recv` waits up to `timeoutSeconds` and then returns `null`. "The default timeout is 60 seconds" ([DBOS workflow communication](https://docs.dbos.dev/typescript/tutorials/workflow-communication)).
|
|
32
|
+
- "If you're sending a message from a workflow, DBOS guarantees exactly-once delivery" ([DBOS workflow communication](https://docs.dbos.dev/typescript/tutorials/workflow-communication)).
|
|
33
|
+
- With `delaySeconds` on enqueue, the workflow "is initially placed in `DELAYED` status and transitions to `ENQUEUED` after the delay expires" ([DBOS methods reference](https://docs.dbos.dev/typescript/reference/methods)).
|
|
34
|
+
- A partitioned queue with `partitionConcurrency: 1` runs one workflow at a time for each `queuePartitionKey`.
|
|
35
|
+
- In Solid Objects, a message to the actor replaces `send` and `recv`, and a reminder (`this.schedule({ at, key }).operation(input)`) replaces a durable sleep. Solid Objects has no durable wait inside a turn. The turn that stores the reminder ends, so other messages for the same cart run before the reminder runs.
|
|
36
|
+
|
|
27
37
|
## Choose DBOS when
|
|
28
38
|
|
|
29
39
|
- The work is a sequence of steps, and a completed step must not run again after a crash.
|
|
@@ -351,11 +361,10 @@ How it works:
|
|
|
351
361
|
|
|
352
362
|
**Is Solid Objects mature enough?** Here are the facts:
|
|
353
363
|
|
|
354
|
-
- First public release of the npm package: August 13, 2026.
|
|
355
364
|
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
|
|
356
365
|
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
|
|
357
|
-
- 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.
|
|
358
|
-
- The [benchmarks](../benchmarks.md) are development measurements.
|
|
366
|
+
- 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.
|
|
367
|
+
- The [benchmarks](../benchmarks.md) are development measurements. [Versioning](../versioning.md) states what version 1.0 does not claim.
|
|
359
368
|
|
|
360
369
|
DBOS has a company, a hosted service, and a longer history. If those matter more than state for each cart, choose DBOS.
|
|
361
370
|
|
|
@@ -382,6 +391,8 @@ Checked October 15, 2026:
|
|
|
382
391
|
- [DBOS upgrading workflows](https://docs.dbos.dev/typescript/tutorials/upgrading-workflows)
|
|
383
392
|
- [Migrating from Temporal to DBOS](https://docs.dbos.dev/explanations/migrating-from-temporal)
|
|
384
393
|
- [DBOS pricing](https://www.dbos.dev/dbos-pricing)
|
|
394
|
+
- [DBOS methods reference](https://docs.dbos.dev/typescript/reference/methods) (checked October 18, 2026)
|
|
395
|
+
- [DBOS workflow communication](https://docs.dbos.dev/typescript/tutorials/workflow-communication) (checked October 18, 2026)
|
|
385
396
|
|
|
386
397
|
## More information
|
|
387
398
|
|
|
@@ -23,6 +23,16 @@ Solid Objects is an independent project. It is not affiliated with Graphile.
|
|
|
23
23
|
|
|
24
24
|
The Graphile Worker facts come from the [Graphile Worker documentation](https://worker.graphile.org/docs) and its [source code](https://github.com/graphile/worker) (checked October 15, 2026).
|
|
25
25
|
|
|
26
|
+
## Do jobs with the same `queue_name` run serially?
|
|
27
|
+
|
|
28
|
+
Yes. Jobs in the same named queue run one at a time. The SQL function `graphile_worker.add_job` takes `queue_name`, and the JavaScript `addJob` takes `queueName`: "if you want certain tasks to run one at a time, add them to the same named queue" ([Graphile Worker `add_job`](https://worker.graphile.org/docs/sql-add-job), checked October 18, 2026).
|
|
29
|
+
|
|
30
|
+
- The `TaskSpec` type describes `queueName` as "The queue to run this task under (only specify if you want jobs in this queue to run serially)" ([`addJob`](https://worker.graphile.org/docs/library/add-job)).
|
|
31
|
+
- Serial is not the same as ordered after a failure. See the "Order after a failure" row above.
|
|
32
|
+
- `job_key` (`jobKey` in JavaScript) is a "unique identifier for the job, used to replace, update or remove it later if needed" ([`add_job`](https://worker.graphile.org/docs/sql-add-job)). `job_key_mode` (`jobKeyMode` in JavaScript) is `replace` (the default), `preserve_run_at`, or `unsafe_dedupe` ([job keys](https://worker.graphile.org/docs/job-key)).
|
|
33
|
+
- `run_at` (`runAt` in JavaScript) is "a timestamp after which to run the job; defaults to now".
|
|
34
|
+
- In Solid Objects, the actor ID replaces `queue_name`, and `this.schedule({ at, key }).operation(input)` replaces `run_at` with a `job_key`.
|
|
35
|
+
|
|
26
36
|
## Choose Graphile Worker when
|
|
27
37
|
|
|
28
38
|
- The work is background jobs, such as emails, webhooks, or reports.
|
|
@@ -256,11 +266,10 @@ How it works:
|
|
|
256
266
|
|
|
257
267
|
**Is Solid Objects mature enough?** Here are the facts:
|
|
258
268
|
|
|
259
|
-
- First public release of the npm package: August 13, 2026.
|
|
260
269
|
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
|
|
261
270
|
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
|
|
262
|
-
- 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.
|
|
263
|
-
- The [benchmarks](../benchmarks.md) are development measurements.
|
|
271
|
+
- 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.
|
|
272
|
+
- The [benchmarks](../benchmarks.md) are development measurements. [Versioning](../versioning.md) states what version 1.0 does not claim.
|
|
264
273
|
|
|
265
274
|
**Why Node.js 24.4 or newer?** The SQLite adapter reads integer columns as `BigInt`. Node.js 24.4.0 is the first release that accepts `readBigInts` on the built-in SQLite module. See [support](../support.md).
|
|
266
275
|
|
|
@@ -278,6 +287,7 @@ Checked October 15, 2026:
|
|
|
278
287
|
|
|
279
288
|
- [Graphile Worker introduction](https://worker.graphile.org/docs)
|
|
280
289
|
- [Graphile Worker `addJob`](https://worker.graphile.org/docs/library/add-job)
|
|
290
|
+
- [Graphile Worker `add_job` in SQL](https://worker.graphile.org/docs/sql-add-job) (checked October 18, 2026)
|
|
281
291
|
- [Graphile Worker job keys](https://worker.graphile.org/docs/job-key)
|
|
282
292
|
- [Graphile Worker error handling](https://worker.graphile.org/docs/error-handling)
|
|
283
293
|
- [Graphile Worker exponential backoff](https://worker.graphile.org/docs/exponential-backoff)
|
package/docs/compare/restate.md
CHANGED
|
@@ -20,6 +20,15 @@ Solid Objects is an independent project. It is not affiliated with Restate.
|
|
|
20
20
|
|
|
21
21
|
The Restate facts come from the [Restate documentation](https://docs.restate.dev) and the [Restate server licence](https://github.com/restatedev/restate/blob/main/LICENSE) (checked October 15, 2026).
|
|
22
22
|
|
|
23
|
+
## How do delayed messages and timers work in Restate?
|
|
24
|
+
|
|
25
|
+
Restate names two ways to schedule work later in TypeScript. You can send a delayed message ([`restate.rpc.sendOpts({ delay })`](https://docs.restate.dev/develop/ts/service-communication)), or you can sleep (`ctx.sleep`) and then send a message. Restate recommends delayed messages, because "Other requests to the same Virtual Object can be processed during the delay period" ([Restate scheduling and timers](https://docs.restate.dev/develop/ts/durable-timers), checked October 18, 2026).
|
|
26
|
+
|
|
27
|
+
- Restate "tracks and manages timers, ensuring they survive failures and restarts".
|
|
28
|
+
- "If you sleep in an exclusive handler in a Virtual Object, all other calls to this object will be queued."
|
|
29
|
+
- The SDK pages, the TypeScript pages included, call this a delayed message. Some operations pages, such as versioning and managing invocations, call it a delayed call.
|
|
30
|
+
- In Solid Objects, `this.schedule({ at, key }).operation(input)` stores a reminder in the same SQL transaction as the turn. The turn ends at once, so other messages do not wait. One operation and key hold one alarm, and you can [cancel a reminder](../api.md#cancelling-a-reminder).
|
|
31
|
+
|
|
23
32
|
## Choose Restate when
|
|
24
33
|
|
|
25
34
|
- You want a journal of each step, so that a retry resumes after the last completed step.
|
|
@@ -252,11 +261,10 @@ A model call can run again after a crash, because effects run at least once. If
|
|
|
252
261
|
|
|
253
262
|
**Is Solid Objects mature enough?** Here are the facts:
|
|
254
263
|
|
|
255
|
-
- First public release of the npm package: August 13, 2026.
|
|
256
264
|
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
|
|
257
265
|
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
|
|
258
|
-
- 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.
|
|
259
|
-
- The [benchmarks](../benchmarks.md) are development measurements.
|
|
266
|
+
- 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.
|
|
267
|
+
- The [benchmarks](../benchmarks.md) are development measurements. [Versioning](../versioning.md) states what version 1.0 does not claim.
|
|
260
268
|
|
|
261
269
|
Restate reached 1.0 in June 2024. If a longer history matters more than keeping the state in your own database, choose Restate.
|
|
262
270
|
|
|
@@ -273,13 +281,15 @@ Restate reached 1.0 in June 2024. If a longer history matters more than keeping
|
|
|
273
281
|
Checked October 15, 2026:
|
|
274
282
|
|
|
275
283
|
- [Restate services and virtual objects](https://docs.restate.dev/foundations/services)
|
|
276
|
-
- [Restate service communication and delayed
|
|
284
|
+
- [Restate service communication and delayed messages](https://docs.restate.dev/develop/ts/service-communication)
|
|
277
285
|
- [Restate durable steps](https://docs.restate.dev/develop/ts/durable-steps)
|
|
278
286
|
- [Restate durable agents](https://docs.restate.dev/ai/patterns/durable-agents)
|
|
279
287
|
- [Restate agent sessions](https://docs.restate.dev/ai/patterns/sessions)
|
|
280
288
|
- [Restate sagas](https://docs.restate.dev/guides/sagas)
|
|
281
289
|
- [Restate service configuration](https://docs.restate.dev/services/configuration)
|
|
282
290
|
- [Restate server overview](https://docs.restate.dev/server/overview)
|
|
291
|
+
- [Restate databases guide](https://docs.restate.dev/guides/databases)
|
|
292
|
+
- [Restate scheduling and timers](https://docs.restate.dev/develop/ts/durable-timers) (checked October 18, 2026)
|
|
283
293
|
- [Restate server licence](https://github.com/restatedev/restate/blob/main/LICENSE)
|
|
284
294
|
|
|
285
295
|
## More information
|
package/docs/compare/rivetkit.md
CHANGED
|
@@ -244,11 +244,10 @@ How it works:
|
|
|
244
244
|
|
|
245
245
|
**Is Solid Objects mature enough?** Here are the facts:
|
|
246
246
|
|
|
247
|
-
- First public release of the npm package: August 13, 2026.
|
|
248
247
|
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
|
|
249
248
|
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
|
|
250
|
-
- 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.
|
|
251
|
-
- The [benchmarks](../benchmarks.md) are development measurements.
|
|
249
|
+
- 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.
|
|
250
|
+
- The [benchmarks](../benchmarks.md) are development measurements. [Versioning](../versioning.md) states what version 1.0 does not claim.
|
|
252
251
|
|
|
253
252
|
**Why Node.js 24.4 or newer?** The SQLite adapter reads integer columns as `BigInt`. Node.js 24.4.0 is the first release that accepts `readBigInts` on the built-in SQLite module. See [support](../support.md).
|
|
254
253
|
|
package/docs/comparisons.md
CHANGED
|
@@ -15,6 +15,7 @@ runtime code on each page runs in the test suite.
|
|
|
15
15
|
| [DBOS Transact and Solid Objects](compare/dbos.md) | Shopping cart checkout |
|
|
16
16
|
| [RivetKit actors and Solid Objects](compare/rivetkit.md) | Chat rooms |
|
|
17
17
|
| [Graphile Worker named queues and Solid Objects](compare/graphile-worker.md) | Chat rooms |
|
|
18
|
+
| [Durable execution for TypeScript AI agents](compare/ai-agents.md) | AI agent sessions |
|
|
18
19
|
|
|
19
20
|
## Coordination models
|
|
20
21
|
|
package/docs/configuration.md
CHANGED
|
@@ -167,11 +167,30 @@ IDs, while PostgreSQL callers should use `RETURNING` with `get()`.
|
|
|
167
167
|
|
|
168
168
|
### SQLite
|
|
169
169
|
|
|
170
|
-
`sqlite({ path, timeoutMilliseconds = 5_000, lockRetryAttempts = 10 })`
|
|
171
|
-
Node's built-in `node:sqlite`. `lockRetryAttempts` is a positive integer.
|
|
172
|
-
timeout controls SQLite's busy timeout; transaction acquisition retries use
|
|
170
|
+
`sqlite({ path, timeoutMilliseconds = 5_000, lockRetryAttempts = 10, synchronous = "normal" })`
|
|
171
|
+
uses Node's built-in `node:sqlite`. `lockRetryAttempts` is a positive integer.
|
|
172
|
+
The timeout controls SQLite's busy timeout; transaction acquisition retries use
|
|
173
173
|
short capped backoff only when no synchronous deadline is active.
|
|
174
174
|
|
|
175
|
+
A file database uses write-ahead logging (WAL). On its first access, the
|
|
176
|
+
adapter sets `journal_mode = WAL` and the `synchronous` level, with the same
|
|
177
|
+
retries as a transaction. WAL keeps two more files next to the database:
|
|
178
|
+
`<path>-wal` and `<path>-shm`. Committed data can be in the `-wal` file, so a
|
|
179
|
+
copy of the database file alone can miss it. To back up a database that is in
|
|
180
|
+
use, run `VACUUM INTO '<backup path>'` or use the SQLite backup command. Copy
|
|
181
|
+
the files only when no process has the database open. An in-memory database
|
|
182
|
+
(`":memory:"`) keeps its memory journal.
|
|
183
|
+
|
|
184
|
+
`synchronous` is `"normal"` or `"full"`:
|
|
185
|
+
|
|
186
|
+
- `"normal"`, the default, is the level that the Ruby gem gets from Active
|
|
187
|
+
Record. A commit makes almost no `fsync` call. A process crash loses no
|
|
188
|
+
commit. A power loss or an operating system crash can lose the last commits,
|
|
189
|
+
but the database stays consistent.
|
|
190
|
+
- `"full"` flushes each commit to disk before the commit returns. A commit
|
|
191
|
+
costs about one `fsync` call, and `node:sqlite` blocks the event loop while
|
|
192
|
+
it waits for the disk.
|
|
193
|
+
|
|
175
194
|
### PostgreSQL
|
|
176
195
|
|
|
177
196
|
`postgresql(options)` accepts:
|
package/docs/correctness.md
CHANGED
|
@@ -93,13 +93,13 @@
|
|
|
93
93
|
inside-transaction check) read as unset. Durable-state fencing, mailbox
|
|
94
94
|
ordering, and the SQLite WASM deadline enforcement do not depend on those
|
|
95
95
|
guards. The guards are best-effort in the browser and exact in Node.
|
|
96
|
-
- `snapshotWithIncarnation`
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
- `snapshotWithIncarnation` identifies a persisted incarnation by `instanceId`.
|
|
97
|
+
Use exact ID equality, with numeric revision comparison only within that ID.
|
|
98
|
+
`createdAtMs` is millisecond creation metadata; destruction and recreation can
|
|
99
|
+
produce equal timestamps and revisions while their IDs differ. Neither a
|
|
100
|
+
timestamp nor a random UUID provides a total incarnation order. Snapshot
|
|
101
|
+
reads alone do not atomically fence an external write; see
|
|
102
|
+
[Snapshot incarnation identity](api.md#snapshot-incarnation-identity).
|
|
103
103
|
- Large documents, bulk pipelines, globally placed edge state, and global
|
|
104
104
|
counters are outside the intended workload. Prefer an ordinary row
|
|
105
105
|
transaction when it completely enforces the invariant.
|
|
@@ -383,7 +383,7 @@ The seventh test does not inject a late or repeated timer. The turn number check
|
|
|
383
383
|
|
|
384
384
|
Delivery is at least once. Write each operation so that it can run again. One room runs one write at a time. This fits turn-based play, not a high-frequency game loop or fast real-time physics.
|
|
385
385
|
|
|
386
|
-
The application owns the WebSocket server, authentication, and the display of the room. There are no transactions across two rooms. The package requires Node.js 24.4 or newer and ESM only. Version 1.0 promises a stable public API.
|
|
386
|
+
The application owns the WebSocket server, authentication, and the display of the room. There are no transactions across two rooms. The package requires Node.js 24.4 or newer and ESM only. Version 1.0 promises a stable public API. [Versioning](../versioning.md) states the limits of that promise.
|
|
387
387
|
|
|
388
388
|
See [Correctness and delivery semantics](../correctness.md) and [Virtual actors in TypeScript and Node.js](../virtual-actors.md).
|
|
389
389
|
|
|
@@ -355,7 +355,7 @@ There are no transactions across two actor identities. One identity runs one wri
|
|
|
355
355
|
|
|
356
356
|
Each operation adds a message row. The runtime keeps completed messages for 30 days by default through `messageRetentionMilliseconds`. See [Configuration](../configuration.md#retention-and-cleanup) for retention and cleanup controls.
|
|
357
357
|
|
|
358
|
-
The package requires Node.js 24.4 or newer and supports ESM only. Version 1.0 promises a stable public API.
|
|
358
|
+
The package requires Node.js 24.4 or newer and supports ESM only. Version 1.0 promises a stable public API. [Versioning](../versioning.md) states the limits of that promise. See [Correctness and delivery semantics](../correctness.md) and [Virtual actors in TypeScript and Node.js](../virtual-actors.md).
|
|
359
359
|
|
|
360
360
|
## Sources
|
|
361
361
|
|
package/docs/parity.md
CHANGED
|
@@ -22,7 +22,10 @@ Ruby capabilities. Ruby's equivalent primitives
|
|
|
22
22
|
(`SolidObjects::Mailbox#enqueue`, `ActorSnapshot`) are already reachable
|
|
23
23
|
in-process, and they need no dedicated public API. Node's `exports` map enforces
|
|
24
24
|
a package-privacy boundary between a package and its dependents. Ruby has no
|
|
25
|
-
such boundary between a gem and its dependents.
|
|
25
|
+
such boundary between a gem and its dependents. The TypeScript snapshot contract
|
|
26
|
+
uses `instanceId` equality for incarnation identity and numeric revisions within
|
|
27
|
+
that identity; creation timestamps are metadata and may tie. This clarifies the
|
|
28
|
+
existing integration API without changing shared commit fencing or Ruby behavior.
|
|
26
29
|
|
|
27
30
|
## Status vocabulary
|
|
28
31
|
|
|
@@ -101,6 +104,7 @@ Ruby publishes RBS contracts with native Ruby field names; this does not change
|
|
|
101
104
|
| Capability | Status | TypeScript shape or remaining work |
|
|
102
105
|
| --------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
103
106
|
| SQLite | Native | Uses built-in `node:sqlite`, serialized process-local access, bounded transient writer retries, foreign keys, strict tables, database time, and deadline-bounded access and lock waits. Ruby uses a yielding busy handler for background writes so a waiting thread lets the lock holder commit, including on Rails 7.1/7.2; both preserve synchronous deadlines. |
|
|
107
|
+
| SQLite durability settings | Native | File databases use WAL with synchronous NORMAL in both runtimes. Ruby gets them from Active Record; the Node adapter sets them on first access, and `synchronous: "full"` is optional. |
|
|
104
108
|
| PostgreSQL | Native | Optional `pg` 8.23 peer, bounded pooling, 64-bit schema, row-locked sequences, server checks, and deadline-bounded pool, statement, and lock waits. |
|
|
105
109
|
| MySQL | Native | Optional `mysql2` 3.23 peer, bounded pooling, InnoDB schema, row-locked sequences, scoped deadlock retry, and deadline-bounded pool, query, and lock waits. Ruby also tests a second client, `trilogy`; Node has no comparable second MySQL client, so only `mysql2` is tracked here. |
|
|
106
110
|
| Durable polling fallback | Native | Every role progresses without a notification service. Effects, reminders, and broadcasts use canonical ordered polling indexes; PostgreSQL and MySQL lock only the selected row with `FOR UPDATE SKIP LOCKED`. Broadcasts and reminders compare separate available and stale-recovery probes, preserve the oldest-first choice, and retry past candidates locked by another claimant. |
|
|
@@ -216,7 +220,8 @@ next section tracks it as a shared capability. All four milestones are
|
|
|
216
220
|
complete:
|
|
217
221
|
|
|
218
222
|
- M1: the shared modules no longer import Node built-in modules, a
|
|
219
|
-
registered platform factory supplies async context
|
|
223
|
+
registered platform factory supplies Node async context and synchronous-only
|
|
224
|
+
browser context (guards are unset after `await`), and
|
|
220
225
|
`pnpm run check` enforces a Node-free import graph for the browser-safe
|
|
221
226
|
modules.
|
|
222
227
|
- M2: `solid-objects/database/sqlite-wasm` implements the `Database`
|
package/docs/virtual-actors.md
CHANGED
|
@@ -12,8 +12,8 @@ no Cloudflare account, and no new datastore. A process of your application
|
|
|
12
12
|
calls `runtime.run(signal)` to run reminders, effects, and queued messages.
|
|
13
13
|
Redis is optional and only shortens wake-up latency.
|
|
14
14
|
|
|
15
|
-
Solid Objects 1.0 promises a stable public API.
|
|
16
|
-
|
|
15
|
+
Solid Objects 1.0 promises a stable public API. [Versioning](versioning.md)
|
|
16
|
+
states the limits of that promise. Read
|
|
17
17
|
[Compatibility and maturity](#compatibility-and-maturity) before you choose it.
|
|
18
18
|
|
|
19
19
|
## What a virtual actor is
|
|
@@ -246,10 +246,9 @@ These runtimes have different compatibility statements:
|
|
|
246
246
|
| Browser runtime (`solid-objects/browser/host`) | The actor runtime in a browser module worker on SQLite WASM. Tested in Chromium |
|
|
247
247
|
| Cloudflare backend (`solid-objects/cloudflare`) | Experimental. It runs the actor API on Cloudflare Durable Objects, with different capability limits |
|
|
248
248
|
|
|
249
|
-
Version 1.0: the public API follows [semantic versioning](versioning.md)
|
|
250
|
-
|
|
251
|
-
more than 100,000 users runs the
|
|
252
|
-
users, not a measure of load.
|
|
253
|
-
and no production use by other people is known.
|
|
249
|
+
Version 1.0: the public API follows [semantic versioning](versioning.md),
|
|
250
|
+
which also states the limits of that promise. The Cloudflare backend is outside
|
|
251
|
+
that promise. One first-party application with more than 100,000 users runs the
|
|
252
|
+
package in production. That is a count of users, not a measure of load.
|
|
254
253
|
[Supported versions](support.md) lists the CI matrix. For Ruby on Rails, use
|
|
255
254
|
the [solid_objects](https://github.com/cardmagic/solid-objects-ruby) gem.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solid-objects",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Fix race conditions across Node.js processes: ordered operations, expiring holds, and state that survives a restart, in your SQL database. A SQL-backed virtual actor library for TypeScript and Node.js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"deploy:cloudflare": "wrangler deploy --config examples/cloudflare/wrangler.jsonc",
|
|
112
112
|
"check:cloudflare": "node scripts/check-cloudflare-imports.mjs && tsc -p tsconfig.cloudflare-example.json --noEmit && wrangler deploy --dry-run --config examples/cloudflare/wrangler.jsonc",
|
|
113
113
|
"build": "pnpm run clean && tsc -p tsconfig.build.json && tsc -p tsconfig.cloudflare-build.json && tsc -p tsconfig.quickstart-build.json && node scripts/prepare-executable.mjs",
|
|
114
|
-
"check": "pnpm run check:parameters && pnpm run check:documentation && pnpm run check:browser-imports && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.examples.json --noEmit && tsc -p tsconfig.cloudflare.json --noEmit",
|
|
114
|
+
"check": "pnpm run check:parameters && pnpm run check:documentation && pnpm run check:browser-imports && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.examples.json --noEmit && tsc -p tsconfig.cloudflare.json --noEmit && tsc -p tsconfig.benchmarks.json",
|
|
115
115
|
"check:browser-imports": "node scripts/check-browser-imports.mjs",
|
|
116
116
|
"check:documentation": "node scripts/check-documentation.mjs",
|
|
117
117
|
"check:parameters": "node scripts/check-parameter-style.mjs",
|
|
@@ -121,8 +121,8 @@
|
|
|
121
121
|
"test": "vitest run",
|
|
122
122
|
"test:browser": "pnpm run build && playwright test",
|
|
123
123
|
"test:coverage": "vitest run --coverage",
|
|
124
|
-
"test:postgresql": "vitest run test/postgresql.test.ts test/activation-lease.test.ts test/activation-recovery-backoff.test.ts test/caller-lifecycle.test.ts test/effect-recovery.test.ts test/instance-retention.test.ts test/transmit-ordering.test.ts",
|
|
125
|
-
"test:mysql": "vitest run test/mysql.test.ts test/activation-lease.test.ts test/activation-recovery-backoff.test.ts test/caller-lifecycle.test.ts test/effect-recovery.test.ts test/instance-retention.test.ts test/transmit-ordering.test.ts",
|
|
124
|
+
"test:postgresql": "vitest run test/postgresql.test.ts test/activation-lease.test.ts test/activation-recovery-backoff.test.ts test/caller-lifecycle.test.ts test/effect-recovery.test.ts test/instance-retention.test.ts test/transmit-ordering.test.ts test/snapshot-with-incarnation.test.ts",
|
|
125
|
+
"test:mysql": "vitest run test/mysql.test.ts test/activation-lease.test.ts test/activation-recovery-backoff.test.ts test/caller-lifecycle.test.ts test/effect-recovery.test.ts test/instance-retention.test.ts test/transmit-ordering.test.ts test/snapshot-with-incarnation.test.ts",
|
|
126
126
|
"test:package": "node scripts/release-artifact-smoke.mjs",
|
|
127
127
|
"test:recovery": "pnpm run build && node examples/failure-recovery/demo.ts",
|
|
128
128
|
"test:at-least-once": "pnpm run build && node examples/at-least-once/demo.ts",
|
|
@@ -149,6 +149,7 @@
|
|
|
149
149
|
"redis": "^6.2.1",
|
|
150
150
|
"signal-polyfill": "^0.2.2",
|
|
151
151
|
"typescript": "^5.9.0",
|
|
152
|
+
"vite": "^8.3.4",
|
|
152
153
|
"vitest": "^4.1.11",
|
|
153
154
|
"wrangler": "^4.129.0",
|
|
154
155
|
"ws": "^8.21.3"
|