solid-objects 0.16.1 → 0.17.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +11 -2
  3. package/dist/actor-runtime.d.ts +7 -0
  4. package/dist/actor-runtime.d.ts.map +1 -1
  5. package/dist/actor.d.ts +1 -0
  6. package/dist/actor.d.ts.map +1 -1
  7. package/dist/actor.js +3 -0
  8. package/dist/actor.js.map +1 -1
  9. package/dist/cloudflare/engine.d.ts +1 -0
  10. package/dist/cloudflare/engine.d.ts.map +1 -1
  11. package/dist/cloudflare/engine.js +118 -15
  12. package/dist/cloudflare/engine.js.map +1 -1
  13. package/dist/cloudflare/records.d.ts +2 -0
  14. package/dist/cloudflare/records.d.ts.map +1 -1
  15. package/dist/cloudflare/runtime.d.ts +7 -0
  16. package/dist/cloudflare/runtime.d.ts.map +1 -1
  17. package/dist/cloudflare/runtime.js +13 -0
  18. package/dist/cloudflare/runtime.js.map +1 -1
  19. package/dist/configuration.d.ts +10 -0
  20. package/dist/configuration.d.ts.map +1 -1
  21. package/dist/configuration.js.map +1 -1
  22. package/dist/diagnostics.d.ts +37 -0
  23. package/dist/diagnostics.d.ts.map +1 -0
  24. package/dist/diagnostics.js +73 -0
  25. package/dist/diagnostics.js.map +1 -0
  26. package/dist/doctor.js +1 -1
  27. package/dist/doctor.js.map +1 -1
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/realtime.d.ts.map +1 -1
  31. package/dist/realtime.js +14 -1
  32. package/dist/realtime.js.map +1 -1
  33. package/dist/reference.d.ts +11 -0
  34. package/dist/reference.d.ts.map +1 -1
  35. package/dist/reference.js +22 -0
  36. package/dist/reference.js.map +1 -1
  37. package/dist/repository.d.ts +1 -1
  38. package/dist/repository.d.ts.map +1 -1
  39. package/dist/repository.js +7 -6
  40. package/dist/repository.js.map +1 -1
  41. package/dist/runtime.d.ts +8 -0
  42. package/dist/runtime.d.ts.map +1 -1
  43. package/dist/runtime.js +108 -32
  44. package/dist/runtime.js.map +1 -1
  45. package/dist/schema.d.ts.map +1 -1
  46. package/dist/schema.js +20 -5
  47. package/dist/schema.js.map +1 -1
  48. package/dist/serialization.js +3 -5
  49. package/dist/serialization.js.map +1 -1
  50. package/dist/telemetry.d.ts +22 -0
  51. package/dist/telemetry.d.ts.map +1 -0
  52. package/dist/telemetry.js +126 -0
  53. package/dist/telemetry.js.map +1 -0
  54. package/dist/transmit.js +2 -2
  55. package/dist/transmit.js.map +1 -1
  56. package/dist/turn.js +2 -2
  57. package/dist/turn.js.map +1 -1
  58. package/dist/version.d.ts +1 -1
  59. package/dist/version.js +1 -1
  60. package/dist/wake-up-notification.d.ts.map +1 -1
  61. package/dist/wake-up-notification.js +9 -1
  62. package/dist/wake-up-notification.js.map +1 -1
  63. package/docs/agents.md +300 -0
  64. package/docs/api.md +25 -3
  65. package/docs/authorization.md +6 -0
  66. package/docs/comparisons.md +36 -0
  67. package/docs/observability.md +192 -0
  68. package/docs/parity.md +85 -72
  69. package/docs/releasing.md +12 -2
  70. package/docs/virtual-actors.md +242 -0
  71. package/examples/ticket-sale.ts +57 -0
  72. package/package.json +8 -5
@@ -0,0 +1,126 @@
1
+ import { readonlyCopy } from "./serialization.js";
2
+ export const portableAttributes = new Set([
3
+ "failureCount",
4
+ "phase",
5
+ "activationOwnerId",
6
+ "activationGeneration",
7
+ "pollingIntervalMilliseconds",
8
+ "idlePollingIntervalMilliseconds",
9
+ "currentIntervalMilliseconds",
10
+ "component",
11
+ "workers",
12
+ "effectWorkers",
13
+ "broadcastWorkers",
14
+ "reminderSchedulers",
15
+ "actorType",
16
+ "actorId",
17
+ "instanceId",
18
+ "incarnation",
19
+ "revision",
20
+ "messageId",
21
+ "requestId",
22
+ "attempt",
23
+ "sequence",
24
+ "operation",
25
+ "deliveryMode",
26
+ "generation",
27
+ "durationMilliseconds",
28
+ "latenessMilliseconds",
29
+ "ageMilliseconds",
30
+ "depth",
31
+ "count",
32
+ "errorName",
33
+ "outcome",
34
+ "retryable",
35
+ "status",
36
+ "effectId",
37
+ "effectName",
38
+ "reminderId",
39
+ "occurrence",
40
+ "broadcastId",
41
+ "code",
42
+ "role",
43
+ "reason",
44
+ "processId",
45
+ "processKind",
46
+ "ownerId",
47
+ "componentCount",
48
+ "byteCount",
49
+ "thresholdBytes",
50
+ "previousRunAt",
51
+ "nextRunAt",
52
+ "name",
53
+ "commitAction",
54
+ "outboxKind",
55
+ "truncated",
56
+ "payload",
57
+ "waitingOn",
58
+ "timeoutMilliseconds",
59
+ "intervalMilliseconds",
60
+ "previousIntervalMilliseconds",
61
+ ]);
62
+ export function telemetryEvent(options) {
63
+ const attributes = {};
64
+ for (const [key, value] of Object.entries(options.attributes)) {
65
+ if (portableAttributes.has(key) &&
66
+ (value === null || ["string", "number", "boolean"].includes(typeof value))) {
67
+ attributes[key] = value;
68
+ }
69
+ }
70
+ const name = `solid_objects.${options.name}`;
71
+ const labels = Object.freeze({
72
+ event: name,
73
+ adapter: options.adapter,
74
+ actorType: String(attributes.actorType ?? ""),
75
+ });
76
+ const metrics = [
77
+ { name: "solid_objects.events", kind: "counter", unit: "1", value: 1, labels },
78
+ ];
79
+ for (const [field, metric, kind, unit] of [
80
+ ["durationMilliseconds", "solid_objects.duration", "histogram", "ms"],
81
+ ["latenessMilliseconds", "solid_objects.reminder.lateness", "histogram", "ms"],
82
+ ["ageMilliseconds", "solid_objects.outbox.age", "histogram", "ms"],
83
+ ["depth", "solid_objects.mailbox.depth", "gauge", "1"],
84
+ ]) {
85
+ const value = attributes[field];
86
+ if (typeof value === "number" && Number.isFinite(value))
87
+ metrics.push({ name: metric, kind, unit, value: Math.max(0, value), labels });
88
+ }
89
+ return Object.freeze({
90
+ schemaVersion: 1,
91
+ name,
92
+ occurredAt: new Date().toISOString(),
93
+ adapter: options.adapter,
94
+ actorType: identifier(attributes.actorType),
95
+ actorId: identifier(attributes.actorId),
96
+ incarnation: identifier(attributes.incarnation ?? attributes.instanceId),
97
+ revision: identifier(attributes.revision),
98
+ messageId: identifier(attributes.messageId),
99
+ attempt: typeof attributes.attempt === "number" ? attributes.attempt : 0,
100
+ attributes: readonlyCopy(attributes),
101
+ metrics: Object.freeze(metrics.map((sample) => Object.freeze(sample))),
102
+ });
103
+ }
104
+ export function deliverTelemetry(options) {
105
+ const failed = (error) => {
106
+ try {
107
+ const result = options.logger.error({
108
+ event: "solid_objects.instrumentation.failed",
109
+ instrumentationEvent: options.event.name,
110
+ errorName: error instanceof Error ? error.name : "Error",
111
+ });
112
+ void Promise.resolve(result).catch(() => { });
113
+ }
114
+ catch { }
115
+ };
116
+ try {
117
+ void Promise.resolve(options.observer(options.event)).catch(failed);
118
+ }
119
+ catch (error) {
120
+ failed(error);
121
+ }
122
+ }
123
+ function identifier(value) {
124
+ return typeof value === "string" || typeof value === "number" ? String(value) : null;
125
+ }
126
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
package/dist/transmit.js CHANGED
@@ -28,7 +28,7 @@ export async function receiveTransmitEnvelope(options) {
28
28
  throw new InvalidPayload(`transmit envelope requires a non-empty ${field}`);
29
29
  }
30
30
  }
31
- const argumentsValue = envelope.arguments ?? {};
31
+ const argumentsValue = envelope.arguments === undefined ? {} : envelope.arguments;
32
32
  if (!isJsonObject(argumentsValue)) {
33
33
  throw new InvalidPayload("transmit envelope arguments must be a JSON object");
34
34
  }
@@ -80,7 +80,7 @@ async function undeliveredEnvelopesThrough(input) {
80
80
  AND messages.actor_type = ?
81
81
  AND messages.actor_id = ?
82
82
  AND messages.sequence <= (SELECT sequence FROM ${messages} WHERE id = ?)
83
- ORDER BY messages.sequence, effects.id`, [effectName, context.actorType, context.actorId, context.sourceMessageId]));
83
+ ORDER BY messages.sequence, effects.position, effects.id`, [effectName, context.actorType, context.actorId, context.sourceMessageId]));
84
84
  const envelopes = [];
85
85
  for (const row of rows) {
86
86
  const argumentsValue = JSON.parse(row.arguments);
@@ -1 +1 @@
1
- {"version":3,"file":"transmit.js","sourceRoot":"","sources":["../src/transmit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transmit.js","sourceRoot":"","sources":["../src/transmit.ts"],"names":[],"mappings":"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"}
package/dist/turn.js CHANGED
@@ -5,10 +5,10 @@ import { jsonObject, normalizeJson, stableJson } from "./serialization.js";
5
5
  export function readActorObservables(options) {
6
6
  const { actor, definition, runtime } = options;
7
7
  const before = options.stateJson ?? stableJson(actorState(actor, definition.stateKeys));
8
- const intentCount = actor.intentCount();
8
+ const intentsBefore = actor.intentSnapshot();
9
9
  const projection = withActorProjection({ actor, runtime }, () => actor.observableValues());
10
10
  if (stableJson(actorState(actor, definition.stateKeys)) !== before ||
11
- actor.intentCount() !== intentCount) {
11
+ actor.intentSnapshot() !== intentsBefore) {
12
12
  throw new QueryMutatedState("observables must not mutate actor state or stage durable work");
13
13
  }
14
14
  return projection;
package/dist/turn.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"turn.js","sourceRoot":"","sources":["../src/turn.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"turn.js","sourceRoot":"","sources":["../src/turn.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.16.1";
1
+ export declare const VERSION = "0.17.1";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "0.16.1";
1
+ export const VERSION = "0.17.1";
2
2
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wake-up-notification.d.ts","sourceRoot":"","sources":["../src/wake-up-notification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE7D,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACpC,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,UAAU,CAAA;CACjB,GAAG,IAAI,CAWP"}
1
+ {"version":3,"file":"wake-up-notification.d.ts","sourceRoot":"","sources":["../src/wake-up-notification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE7D,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACpC,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,UAAU,CAAA;CACjB,GAAG,IAAI,CAkBP"}
@@ -1,6 +1,14 @@
1
1
  export function notifyWakeUp(options) {
2
2
  const logFailure = (errorName) => {
3
- options.logger.error({ event: "solid_objects.wake_up.failed", role: options.role, errorName });
3
+ try {
4
+ const result = options.logger.error({
5
+ event: "solid_objects.wake_up.failed",
6
+ role: options.role,
7
+ errorName,
8
+ });
9
+ void Promise.resolve(result).catch(() => { });
10
+ }
11
+ catch { }
4
12
  };
5
13
  try {
6
14
  Promise.resolve(options.adapter.notify(options.role)).catch((error) => logFailure(error instanceof Error ? error.name : "Error"));
@@ -1 +1 @@
1
- {"version":3,"file":"wake-up-notification.js","sourceRoot":"","sources":["../src/wake-up-notification.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,YAAY,CAAC,OAI5B;IACC,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAQ,EAAE;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;IAChG,CAAC,CAAA;IACD,IAAI,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACpE,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAC1D,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"wake-up-notification.js","sourceRoot":"","sources":["../src/wake-up-notification.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,YAAY,CAAC,OAI5B;IACC,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAQ,EAAE;QAC7C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;gBAClC,KAAK,EAAE,8BAA8B;gBACrC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,SAAS;aACV,CAAC,CAAA;YACF,KAAK,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC,CAAA;IACD,IAAI,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACpE,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAC1D,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
package/docs/agents.md ADDED
@@ -0,0 +1,300 @@
1
+ # Solid Objects for coding agents (TypeScript and Node.js)
2
+
3
+ This guide is for a coding agent that evaluates or adds Solid Objects in a
4
+ TypeScript or Node.js application. It gives the facts and steps in a fixed
5
+ order. Each step links to the maintained documentation for more detail.
6
+
7
+ ## 1. Check the fit first
8
+
9
+ Use Solid Objects only if you can answer yes to most of these questions:
10
+
11
+ 1. Does one identity, such as a room, cart, account, device, or document, own
12
+ the state?
13
+ 2. Must writes for that identity happen one at a time across requests and
14
+ processes?
15
+ 3. Must some work happen later or continue after a process exits?
16
+ 4. Is the state a bounded JSON document, not a large relational dataset?
17
+ 5. Can the application run `runtime.run(signal)` in at least one process for
18
+ reminders, effects, and realtime delivery?
19
+
20
+ Select a simpler tool in these cases:
21
+
22
+ | Requirement | Use instead |
23
+ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
24
+ | The invariant fits in one request | A transaction, a constraint, or `SELECT ... FOR UPDATE` |
25
+ | CPU-intensive or parallel work | `worker_threads` or a worker pool. An actor serializes work |
26
+ | Thousands of writes for each second to one key | A counter column or a cache. Solid Objects Pro covers this case for Rails; its Node build is in development |
27
+ | One atomic change across two actor identities | One SQL transaction on normal tables |
28
+ | Exactly-once calls to an external API | Not available from any actor library. Use provider idempotency keys |
29
+ | Replay of named workflow steps from a step log | A durable execution engine, such as DBOS or Temporal |
30
+
31
+ The full list is in [Choosing Solid Objects](fit.md). The category guide is
32
+ [Virtual actors in TypeScript and Node.js](virtual-actors.md).
33
+
34
+ ## 2. Package identity
35
+
36
+ | Item | Value |
37
+ | ------------------ | ----------------------------------------------------------------------------------------------------- |
38
+ | npm package | `solid-objects` |
39
+ | Repository | <https://github.com/cardmagic/solid-objects-js> |
40
+ | Website | <https://solidobjects.dev/js> |
41
+ | Ruby on Rails gem | `solid_objects`, a separate implementation of the same model |
42
+ | Commercial package | `@solidobjects/pro`, a separate paid package in development. The open-source package does not need it |
43
+
44
+ Solid Objects is not SolidJS and has no relation to it. It is not affiliated
45
+ with Cloudflare.
46
+
47
+ ## 3. Requirements
48
+
49
+ - Node.js 24.4 or newer. Prefer 24.15 or newer, where `node:sqlite` is no
50
+ longer experimental.
51
+ - The package is ESM only. TypeScript applications need TypeScript 5.9 or
52
+ newer.
53
+ - SQLite through the `node:sqlite` module, PostgreSQL 14 or newer with the
54
+ `pg` package, or MySQL 8.0 or newer with InnoDB and the `mysql2` package.
55
+ - Redis is optional. It only shortens wake-up latency and holds no durable
56
+ state.
57
+
58
+ [Supported versions](support.md) lists the CI matrix.
59
+
60
+ ## 4. Install
61
+
62
+ ```bash
63
+ npm install solid-objects
64
+ npx solid-objects quickstart --yes
65
+ ```
66
+
67
+ The quickstart runs 25 concurrent calls against one identity on a temporary
68
+ SQLite database. It proves that no update is lost. Add `pg` or `mysql2` when
69
+ you use PostgreSQL or MySQL.
70
+
71
+ Create the runtime and its tables at startup:
72
+
73
+ ```typescript
74
+ import { configure } from "solid-objects"
75
+ import { sqlite } from "solid-objects/database/sqlite"
76
+
77
+ const runtime = configure({
78
+ database: sqlite({ path: "app.sqlite3" }),
79
+ })
80
+
81
+ await runtime.install()
82
+ ```
83
+
84
+ [Configuration](configuration.md) lists each option and database adapter.
85
+
86
+ ## 5. Authorize
87
+
88
+ All authorization callbacks deny by default. A new runtime answers no actor
89
+ call until you write a policy. Do not remove this behavior.
90
+
91
+ For a local demonstration only, grant messages and queries:
92
+
93
+ ```typescript
94
+ const runtime = configure({
95
+ database: sqlite({ path: "app.sqlite3" }),
96
+ authorizeMessage: () => true,
97
+ authorizeQuery: () => true,
98
+ })
99
+ ```
100
+
101
+ Keep `authorizeDestroy`, `authorizeSubscription`, and
102
+ `authorizeAdministration` denied in a demonstration.
103
+
104
+ A production policy must bind the actor type and ID to the authenticated user
105
+ or tenant. An actor ID is not a permission:
106
+
107
+ ```typescript
108
+ const ownsCart = ({
109
+ actorType,
110
+ actorId,
111
+ authorizationContext,
112
+ }: {
113
+ actorType: string
114
+ actorId: string
115
+ authorizationContext: unknown
116
+ }) => {
117
+ if (actorType !== "ShoppingCart") return false
118
+ if (typeof authorizationContext !== "object" || authorizationContext === null) return false
119
+ if (!("userId" in authorizationContext)) return false
120
+ return typeof authorizationContext.userId === "string" && actorId === authorizationContext.userId
121
+ }
122
+
123
+ const runtime = configure({
124
+ database: sqlite({ path: "app.sqlite3" }),
125
+ authorizeMessage: ownsCart,
126
+ authorizeQuery: ownsCart,
127
+ })
128
+ ```
129
+
130
+ Pass the context on each call:
131
+
132
+ ```typescript
133
+ await ShoppingCart.ref(subject.userId)
134
+ .with({ authorizationContext: subject })
135
+ .addItem({ productId: "shirt-123" })
136
+ ```
137
+
138
+ [Authorization](authorization.md) covers each entry point.
139
+
140
+ ## 6. Define an actor
141
+
142
+ This actor is the example from the [virtual actor guide](virtual-actors.md):
143
+
144
+ ```typescript
145
+ import { Actor } from "solid-objects"
146
+
147
+ const HOLD_MILLISECONDS = 10 * 60 * 1000
148
+
149
+ export class TicketSale extends Actor {
150
+ static override readonly actorType = "TicketSale"
151
+
152
+ available = 1
153
+ holds: Record<string, number> = {}
154
+
155
+ hold({ buyer }: { buyer: string }): { held: boolean; available: number } {
156
+ if (this.available === 0 || Object.hasOwn(this.holds, buyer)) {
157
+ return { held: false, available: this.available }
158
+ }
159
+
160
+ this.available -= 1
161
+ this.holds = { ...this.holds, [buyer]: Date.now() }
162
+ this.schedule({ at: new Date(Date.now() + HOLD_MILLISECONDS), key: buyer }).expire({ buyer })
163
+ return { held: true, available: this.available }
164
+ }
165
+
166
+ expire({ buyer }: { buyer: string }): number {
167
+ if (!Object.hasOwn(this.holds, buyer)) return this.available
168
+
169
+ const remainingHolds = { ...this.holds }
170
+ delete remainingHolds[buyer]
171
+ this.holds = remainingHolds
172
+ this.available += 1
173
+ return this.available
174
+ }
175
+ }
176
+ ```
177
+
178
+ Obey these rules in actor code:
179
+
180
+ - Give each actor class a stable `static actorType`. The database stores it.
181
+ - Enumerable public fields are the durable state. They must be
182
+ JSON-compatible.
183
+ - Public methods are ordered operations. Each one takes no argument or one
184
+ object argument.
185
+ - Use `this.schedule({ at, key })` for delayed work. A new `schedule` with the
186
+ same key moves the alarm.
187
+ - Use `this.reject(code, message)` for a business rule failure that must not
188
+ retry.
189
+ - Do not write application tables directly from an operation. Use
190
+ `this.commitAction()` for a short write in the same database.
191
+ - Do not call an external API in an operation. Use `this.emit()` and an effect
192
+ handler.
193
+ - Write each operation so that it can run again. Delivery is at least once.
194
+
195
+ [State and lifecycle](state-and-lifecycle.md) and the
196
+ [public API](api.md) give the full rules.
197
+
198
+ ## 7. Run the background roles
199
+
200
+ A direct call, such as `TicketSale.ref("event-42").hold({ buyer: "ada" })`,
201
+ runs in the caller. These features need a process that calls
202
+ `runtime.run(signal)`:
203
+
204
+ - Reminders from `schedule()`.
205
+ - Effects from `emit()` and their callbacks.
206
+ - Messages to other actors.
207
+ - Realtime broadcasts.
208
+
209
+ ```typescript
210
+ const controller = new AbortController()
211
+ process.once("SIGTERM", () => controller.abort())
212
+ await runtime.run(controller.signal)
213
+ await runtime.close()
214
+ ```
215
+
216
+ The packaged `solid-objects start` command does the same for a runtime that
217
+ `solid-objects.config.js` exports. When no process runs, committed work waits
218
+ in SQL and runs later. [Operations](operations.md) covers roles and shutdown.
219
+
220
+ ## 8. Make external effects idempotent
221
+
222
+ Register an effect handler at startup. Use `context.id` as the provider
223
+ idempotency key:
224
+
225
+ ```typescript
226
+ runtime.registerEffect("charge_payment", async (argumentsValue, context) => {
227
+ return payments.charge({
228
+ idempotencyKey: context.id,
229
+ paymentId: argumentsValue.paymentId,
230
+ })
231
+ })
232
+ ```
233
+
234
+ Stage it from an operation:
235
+
236
+ ```typescript
237
+ this.emit("charge_payment", {
238
+ arguments: { paymentId: this.paymentId },
239
+ onSuccess: "charged",
240
+ })
241
+ ```
242
+
243
+ The effect can run more than once after a crash. The `context.id` value is the
244
+ same each time. [Effect recovery](effect-recovery.md) explains how to retire
245
+ abandoned work.
246
+
247
+ ## 9. Verify the implementation
248
+
249
+ Do these checks before you report that the work is complete:
250
+
251
+ 1. Call `await runtime.doctor.run()`. The report must contain no failed check.
252
+ 2. Send concurrent calls to one identity with `Promise.all`, and from two
253
+ processes if the application runs more than one. Assert the final state.
254
+ 3. Test delayed work without sleeps. `runDueReminders({ now })` enqueues the
255
+ reminders that are due at the `Date` you pass. `drain()` then runs the
256
+ enqueued actor work:
257
+
258
+ ```typescript
259
+ await runtime.testing.runDueReminders({ now: new Date(Date.now() + HOLD_MILLISECONDS) })
260
+ await runtime.testing.drain({ roles: ["actors"] })
261
+ ```
262
+
263
+ 4. Start a process that calls `runtime.run(signal)`, schedule a short
264
+ reminder, and stop the process. Start it again after the deadline and
265
+ confirm that the reminder ran.
266
+ 5. Confirm that each effect handler deduplicates with `context.id`.
267
+ 6. Confirm that production policies do not grant access to every caller.
268
+
269
+ The repository runs the same proofs. `pnpm run test:recovery` stops a worker
270
+ process and recovers its work. `pnpm run test:at-least-once` shows a repeated
271
+ effect and its deduplication.
272
+
273
+ ## 10. Troubleshooting
274
+
275
+ | Symptom | Cause and fix |
276
+ | --------------------------------------- | ------------------------------------------------------------------------------------ |
277
+ | `Unauthorized` | A policy denied the call. Write the policy, and pass `authorizationContext` |
278
+ | A reminder or effect does not run | No process calls `runtime.run(signal)`. Start one |
279
+ | `SyncInsideTransaction` | The call ran inside an open transaction. Call the actor outside the transaction |
280
+ | `SyncTimeout` | The call did not finish in time. The message is still durable. Wait on its reference |
281
+ | `ApplicationWriteForbidden` | An operation wrote an application table. Use `commitAction()` or `emit()` |
282
+ | `Rejected` | The actor called `reject()`. This is a business result, not a retry |
283
+ | Wrong integer values or SQLite warnings | Node.js is older than 24.4, or older than 24.15 for the warning. Upgrade Node.js |
284
+ | `ERR_REQUIRE_ESM` or import errors | The package is ESM only. Use `import` and an ES module file |
285
+
286
+ ## 11. Guarantees to state correctly
287
+
288
+ When you explain Solid Objects to a user, state these limits:
289
+
290
+ - Delivery is at least once, not exactly once.
291
+ - Calls for one identity are ordered. Different identities run concurrently.
292
+ - There are no transactions across actor identities.
293
+ - Fencing stops a stale activation from a commit, but its code can continue to
294
+ run.
295
+ - The package is pre-1.0. It has no measured scale and no known third-party
296
+ production use.
297
+ - The browser client is not the SQL runtime. The Cloudflare backend is
298
+ experimental.
299
+
300
+ The [correctness contract](correctness.md) is the source for each guarantee.
package/docs/api.md CHANGED
@@ -105,7 +105,7 @@ envelope. The envelope carries its name in `invalidations`. A component registry
105
105
  can then refresh a reauthorized endpoint, and the value stays private.
106
106
 
107
107
  `MessageReference` does not retain an invocation's authorization context.
108
- Supply `authorizationContext` to each `status()`, `result()`, and `wait()` call;
108
+ Supply `authorizationContext` to each `status()`, `result()`, `outcome()`, and `wait()` call;
109
109
  the runtime reauthorizes the persisted operation every time. Durable results
110
110
  are JSON, so an operation that returns `undefined` or is declared `void`
111
111
  resolves as `null`.
@@ -130,6 +130,10 @@ function playerForSession<PlayerType extends { sessionId: string }>(options: {
130
130
 
131
131
  ### Reminders
132
132
 
133
+ Keyed reminder names combine the operation, a colon, and the key. JavaScript
134
+ limits the combined name to 255 UTF-16 code units; Ruby limits it to 191
135
+ characters. Use at most 191 ASCII characters for names shared across runtimes.
136
+
133
137
  A reminder is one alarm per actor and name. If you schedule a name that is
134
138
  already armed, the runtime **moves the existing alarm**. It does not add a
135
139
  second one. A reminder is therefore safe to re-arm from a handler that can run
@@ -904,6 +908,11 @@ open SAH pool otherwise blocks the next candidate until the worker dies.
904
908
 
905
909
  ## `solid-objects/transmit`
906
910
 
911
+ Schema migration 14 persists an effect's staging position within its source message.
912
+ Run `runtime.install()` before upgraded workers start. New effects preserve staging
913
+ order even when two transmits originate in one turn. Legacy rows use position zero
914
+ and their existing ID tie-break; their original order cannot be recovered.
915
+
907
916
  The transactional outbox bridge between a local runtime and a server
908
917
  runtime. An actor stages a transmit intent with `this.transmit()`
909
918
  in the same transaction as its state change. The effect worker drains the
@@ -923,10 +932,10 @@ outbox with at-least-once delivery, per-actor order, and retry backoff.
923
932
  `deliver` while offline and the effect retries with backoff. Give a
924
933
  browser runtime a generous `maxAttempts`; an effect that exhausts its
925
934
  attempts during a long offline period lands in dead letters, and
926
- `runtime.deadLetters.retry` re-queues it.
935
+ `runtime.deadLetters.effects.retry(id)` re-queues it.
927
936
  - `receiveTransmitEnvelope(options)`: idempotent server ingest. `arguments`
928
937
  is optional in the envelope and defaults to an empty object, matching the
929
- staging side and the Ruby ingest. It enqueues an
938
+ staging side and the Ruby ingest. Explicit `null` and arrays are invalid. It enqueues an
930
939
  internal message with `transmit:<effectId>` as the idempotency key, so a
931
940
  replayed envelope applies once. The host must authenticate the sender
932
941
  before this call; internal delivery skips `authorizeMessage`. The call
@@ -1057,3 +1066,16 @@ Behavior:
1057
1066
 
1058
1067
  Mounting, authorization actions, CSRF behavior, pages, and extensions are in
1059
1068
  [Operator dashboard](dashboard.md).
1069
+
1070
+ ### Portable telemetry and diagnostics
1071
+
1072
+ `InstrumentationEvent` includes the versioned envelope and immutable `MetricSample`
1073
+ values. `EventObserver` is a provider-free event callback. An actor reference offers
1074
+ `observe({ onEvent, authorizationContext })`, `on(name, { onEvent, authorizationContext })`,
1075
+ and `diagnostics(options)`. Both observer methods resolve to an unsubscribe function.
1076
+ They reject a missing `onEvent` with `TypeError` before authorization. A runtime
1077
+ accepts at most 1,000 local observers; the next one rejects with `RangeError`.
1078
+ `close()` removes every local observer.
1079
+ `DiagnosticOptions` accepts `authorizationContext` and a `limit` from 1 to 100.
1080
+ `ActorDiagnostics` holds five bounded `DiagnosticSummary` values, with `sampled`,
1081
+ `truncated`, and `oldestAgeMilliseconds`. See [observability](observability.md).
@@ -10,6 +10,12 @@ resource, optional resource ID, and the caller's authorization context. Retry
10
10
  authorization happens before lookup so a denied caller cannot use record IDs as
11
11
  an existence oracle.
12
12
 
13
+ Actor diagnostics and actor observers call `authorizeAdministration` with the
14
+ resource `actor_diagnostics` and the resource ID
15
+ `JSON.stringify([actorType, actorId])`. `diagnostics()` uses the action
16
+ `inspect`. `observe()` and `on()` use the action `observe`. The check runs before
17
+ any queue read or observer registration.
18
+
13
19
  `runtime.realtime` is transport-neutral. The host application authenticates its
14
20
  WebSocket or stream connection, passes that fresh server-side subject as the
15
21
  session's `authorizationContext`, and forwards incoming protocol messages to