solid-objects 0.16.1 → 0.17.0
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 +51 -0
- package/README.md +1 -0
- package/dist/actor-runtime.d.ts +7 -0
- package/dist/actor-runtime.d.ts.map +1 -1
- package/dist/actor.d.ts +1 -0
- package/dist/actor.d.ts.map +1 -1
- package/dist/actor.js +3 -0
- package/dist/actor.js.map +1 -1
- package/dist/cloudflare/engine.d.ts +1 -0
- package/dist/cloudflare/engine.d.ts.map +1 -1
- package/dist/cloudflare/engine.js +118 -15
- package/dist/cloudflare/engine.js.map +1 -1
- package/dist/cloudflare/records.d.ts +2 -0
- package/dist/cloudflare/records.d.ts.map +1 -1
- package/dist/cloudflare/runtime.d.ts +7 -0
- package/dist/cloudflare/runtime.d.ts.map +1 -1
- package/dist/cloudflare/runtime.js +13 -0
- package/dist/cloudflare/runtime.js.map +1 -1
- package/dist/configuration.d.ts +10 -0
- package/dist/configuration.d.ts.map +1 -1
- package/dist/configuration.js.map +1 -1
- package/dist/diagnostics.d.ts +37 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +73 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/doctor.js +1 -1
- package/dist/doctor.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +14 -1
- package/dist/realtime.js.map +1 -1
- package/dist/reference.d.ts +11 -0
- package/dist/reference.d.ts.map +1 -1
- package/dist/reference.js +22 -0
- package/dist/reference.js.map +1 -1
- package/dist/repository.d.ts +1 -1
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +7 -6
- package/dist/repository.js.map +1 -1
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +108 -32
- package/dist/runtime.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +20 -5
- package/dist/schema.js.map +1 -1
- package/dist/serialization.js +3 -5
- package/dist/serialization.js.map +1 -1
- package/dist/telemetry.d.ts +22 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +126 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/transmit.js +2 -2
- package/dist/transmit.js.map +1 -1
- package/dist/turn.js +2 -2
- package/dist/turn.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wake-up-notification.d.ts.map +1 -1
- package/dist/wake-up-notification.js +9 -1
- package/dist/wake-up-notification.js.map +1 -1
- package/docs/api.md +25 -3
- package/docs/authorization.md +6 -0
- package/docs/observability.md +192 -0
- package/docs/parity.md +84 -72
- package/package.json +3 -3
|
@@ -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);
|
package/dist/transmit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transmit.js","sourceRoot":"","sources":["../src/transmit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAI/D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAgBtD,MAAM,OAAO,uBAAwB,SAAQ,iBAAiB;IAC5D,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;IACvC,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgC;IAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,eAAe,CAAA;IACxD,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;QAC3E,qBAAqB,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAA;QAClD,MAAM,WAAW,GAAG,MAAM,2BAA2B,CAAC;YACpD,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU;YACV,OAAO;SACR,CAAC,CAAA;QACF,KAAK,MAAM,QAAQ,IAAI,WAAW;YAAE,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACnE,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAG7C;IACC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAC5B,KAAK,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,CAAU,EAAE,CAAC;QAC/E,IAAI,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxE,MAAM,IAAI,cAAc,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAA;QAC7E,CAAC;IACH,CAAC;IACD,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,
|
|
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
|
|
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.
|
|
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":"AAEA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACpE,OAAO,EAAE,UAAU,EAAiC,MAAM,iBAAiB,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAG1E,MAAM,UAAU,oBAAoB,CAAC,OAKpC;IACC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA;IACvF,MAAM,
|
|
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.
|
|
1
|
+
export declare const VERSION = "0.17.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.
|
|
1
|
+
export const VERSION = "0.17.0";
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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/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).
|
package/docs/authorization.md
CHANGED
|
@@ -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
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Portable observability
|
|
2
|
+
|
|
3
|
+
Configure `instrumentation(event)` to receive structured events. No exporter SDK
|
|
4
|
+
is required. The same JSON envelope is emitted by Ruby, SQLite, PostgreSQL, MySQL,
|
|
5
|
+
and the Durable Objects host. Existing JavaScript `name`, `occurredAt`, and
|
|
6
|
+
`attributes` fields remain available. Ruby's Active Support notifications remain
|
|
7
|
+
available with their existing snake_case payloads.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { configure } from "solid-objects"
|
|
11
|
+
|
|
12
|
+
const runtime = configure({
|
|
13
|
+
...applicationConfiguration,
|
|
14
|
+
instrumentation: (event) => {
|
|
15
|
+
console.info(JSON.stringify(event))
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
JavaScript passes `instrumentation` to `configure()`. Ruby sets
|
|
21
|
+
`configuration.instrumentation` inside `SolidObjects.configure`.
|
|
22
|
+
|
|
23
|
+
## Schema version 1
|
|
24
|
+
|
|
25
|
+
Every event has `schemaVersion`, `name` (prefixed with `solid_objects.`),
|
|
26
|
+
`occurredAt` (UTC ISO 8601), `adapter`, `actorType`, `actorId`, `incarnation`,
|
|
27
|
+
`revision`, `messageId`, `attempt`, `attributes`, and `metrics`.
|
|
28
|
+
Unavailable identifiers are null; `attempt` is zero outside a message attempt.
|
|
29
|
+
Ruby publishes the RBS types `SolidObjects::portable_event`,
|
|
30
|
+
`SolidObjects::actor_diagnostics`, and `SolidObjects::event_observer`. JavaScript
|
|
31
|
+
exports `InstrumentationEvent`, `ActorDiagnostics`, and `EventObserver`.
|
|
32
|
+
An incarnation identifies a persisted actor instance, independently of its lease
|
|
33
|
+
generation. Revisions and IDs are strings. Process-wide events have null actor
|
|
34
|
+
identity. A message ID or revision correlates actor work where applicable.
|
|
35
|
+
|
|
36
|
+
Only known scalar metadata fields enter the portable envelope. Arguments, state,
|
|
37
|
+
results, credentials, backtraces, exception text, nested provider data, and unknown
|
|
38
|
+
attributes are excluded. Actor IDs remain correlation data: applications should
|
|
39
|
+
use opaque actor identifiers and apply their own retention policy to event logs.
|
|
40
|
+
Events and metric samples are immutable. Throwing observers, rejected observer
|
|
41
|
+
promises, and a failing instrumentation error logger cannot change a turn's
|
|
42
|
+
result. When an exporter or observer raises, both runtimes log
|
|
43
|
+
`solid_objects.instrumentation.failed` with the event name and the error class.
|
|
44
|
+
Delivery is best effort and synchronous callbacks should be short;
|
|
45
|
+
JavaScript does not await exporters. Telemetry is not a durable audit trail.
|
|
46
|
+
|
|
47
|
+
| Event | Meaning |
|
|
48
|
+
| ------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
49
|
+
| `activation.started/completed/failed` | Local actor activation hook lifecycle |
|
|
50
|
+
| `message.started/completed/failed/rejected` | One attempt's execution outcome |
|
|
51
|
+
| `message.retry` | Failed attempt durably queued for another attempt |
|
|
52
|
+
| `dead_letter.created` | Message exhausted retries or failed permanently |
|
|
53
|
+
| `commit_action.started/completed/failed` | One registered commit action inside the commit transaction |
|
|
54
|
+
| `mailbox.depth` | On-demand diagnostic sample; `depth` is null when the sample is truncated |
|
|
55
|
+
| `reminder.enqueued` | Due reminder dispatch; lateness is measured from due time |
|
|
56
|
+
| `outbox.age` | Delivery observation; age is time since the item's current availability time |
|
|
57
|
+
| `recovery.reclaimed` | A previously claimed, interrupted message begins another attempt |
|
|
58
|
+
| `recovery.completed/failed` | Durable effect recovery callback commits or enters the dead-letter queue |
|
|
59
|
+
| `snapshot.read` | Authorized snapshot constructed without exposing its contents |
|
|
60
|
+
| `realtime.connected/disconnected` | Actor subscription added or removed |
|
|
61
|
+
| `payload_broadcast.failed` | One personalized payload failed; `payload` names it |
|
|
62
|
+
|
|
63
|
+
Events describe local observations. Concurrent deletion, crashes, and failed
|
|
64
|
+
exporters can omit events. Never infer exactly-once delivery from event counts.
|
|
65
|
+
Additional existing runtime events retain their names.
|
|
66
|
+
|
|
67
|
+
## Event attributes
|
|
68
|
+
|
|
69
|
+
`compatibility/telemetry-events.json` holds the attribute allowlist and the exact
|
|
70
|
+
attribute keys of each core event. Both test suites compare the events of the SQL
|
|
71
|
+
runtimes with this file. Message events carry `operation` and `deliveryMode`.
|
|
72
|
+
`message.failed` also carries a boolean `retryable` and an `outcome` of
|
|
73
|
+
`retrying` or `dead`. Commit action events carry `commitAction` and
|
|
74
|
+
`activationGeneration`. Activation events carry `generation` and `ownerId`.
|
|
75
|
+
|
|
76
|
+
Ruby activates an actor instance before it claims a message, so its activation
|
|
77
|
+
events have no message fields. JavaScript activates an actor in the turn that
|
|
78
|
+
claims a message, so its activation events also carry the `messageId`,
|
|
79
|
+
`requestId`, `sequence`, `attempt`, `operation`, and `deliveryMode` of that
|
|
80
|
+
message. The contract file records these keys as JavaScript-only.
|
|
81
|
+
|
|
82
|
+
The Durable Objects host sends the same envelope, but some of its events carry
|
|
83
|
+
fewer attributes. The contract file does not apply to that host.
|
|
84
|
+
|
|
85
|
+
Portable `polling.interval_changed` events carry `previousIntervalMilliseconds`,
|
|
86
|
+
`currentIntervalMilliseconds`, and a string `reason`. Ruby converts its native
|
|
87
|
+
second-based notification values while preserving the original notification.
|
|
88
|
+
|
|
89
|
+
## Synchronous timeout diagnostics
|
|
90
|
+
|
|
91
|
+
`solid_objects.sync.timeout` includes `waitingOn`, `activationOwnerId`, and
|
|
92
|
+
`activationGeneration` in `attributes`. Generations are decimal strings;
|
|
93
|
+
unavailable activation fields are null. Both runtimes use the same wait reasons:
|
|
94
|
+
`actorPaused`, `activationHeld`, `earlierMessage`, `messageClaimed`,
|
|
95
|
+
`notYetAvailable`, `readyUnclaimed`, `databaseContention`, and `unknown`.
|
|
96
|
+
Ruby's exception attributes and Active Support notifications retain their native
|
|
97
|
+
snake_case names and reason values. The portable instrumentation envelope uses
|
|
98
|
+
the shared camelCase contract. The Durable Objects host does not send
|
|
99
|
+
`sync.timeout`. A `call` timeout there reports `waitingOn: "unknown"`.
|
|
100
|
+
|
|
101
|
+
## Metrics and tracing
|
|
102
|
+
|
|
103
|
+
Metrics are sample descriptions. Exporting them is opt-in: the runtime does not
|
|
104
|
+
register meters, allocate per-actor metric series, or install a vendor SDK.
|
|
105
|
+
|
|
106
|
+
| Name | Kind | Unit | Aggregation |
|
|
107
|
+
| --------------------------------- | --------- | ---- | ------------------------------------------------------ |
|
|
108
|
+
| `solid_objects.events` | counter | `1` | Sum one per event |
|
|
109
|
+
| `solid_objects.duration` | histogram | `ms` | Distribution of observed attempt duration |
|
|
110
|
+
| `solid_objects.reminder.lateness` | histogram | `ms` | Distribution of reminder dispatch delay |
|
|
111
|
+
| `solid_objects.outbox.age` | histogram | `ms` | Distribution of delivery delay since availability |
|
|
112
|
+
| `solid_objects.mailbox.depth` | gauge | `1` | Last exact sampled actor depth; omit truncated samples |
|
|
113
|
+
|
|
114
|
+
Labels contain only event name, adapter family, and declared actor type. Keep the
|
|
115
|
+
actor type registry finite. Never add actor ID, incarnation, message ID, operation
|
|
116
|
+
arguments, request IDs, or error text to metric labels. A gauge without an actor
|
|
117
|
+
label represents the most recently observed actor; it is not total fleet backlog.
|
|
118
|
+
For tracing, correlate start/outcome events using `adapter`, `incarnation`,
|
|
119
|
+
`messageId`, and `attempt`, and close or expire spans when no outcome arrives.
|
|
120
|
+
|
|
121
|
+
## Actor observers and diagnostics
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const cart = ShoppingCart.ref("demo-cart")
|
|
125
|
+
const stop = await cart.observe({
|
|
126
|
+
authorizationContext: operator,
|
|
127
|
+
onEvent: (event) => {
|
|
128
|
+
console.info(JSON.stringify(event))
|
|
129
|
+
},
|
|
130
|
+
})
|
|
131
|
+
const summary = await cart.diagnostics({ authorizationContext: operator, limit: 50 })
|
|
132
|
+
stop()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Ruby uses `reference.observe(authorization_context:) { |event| ... }` and
|
|
136
|
+
`reference.diagnostics(authorization_context:, limit: 50)`. Stop observing by
|
|
137
|
+
calling the returned proc. `on` filters one event name, such as `message.retry`.
|
|
138
|
+
Observers receive only this actor's events in the current runtime/process; they
|
|
139
|
+
are not subscriptions to workers on other hosts. Dispose them when the caller's
|
|
140
|
+
session ends or authorization is revoked. Each runtime or process accepts at most
|
|
141
|
+
1,000 local observers. More observers raise `RangeError` in JavaScript and
|
|
142
|
+
`ArgumentError` in Ruby. An observer needs a callback or a block. JavaScript
|
|
143
|
+
rejects a missing `onEvent` with `TypeError`, and Ruby raises `ArgumentError`
|
|
144
|
+
without a block. Both checks run before authorization.
|
|
145
|
+
|
|
146
|
+
The JavaScript Durable Objects host does not support process-local reference
|
|
147
|
+
observers. On that host, `observe` and `on` raise `UnsupportedCapability`, and
|
|
148
|
+
remote `reference.diagnostics` works. To observe a remote actor, configure
|
|
149
|
+
`instrumentation` on the actor host and filter the events by actor identity.
|
|
150
|
+
Ruby has no Durable Objects host.
|
|
151
|
+
|
|
152
|
+
Both APIs default to denied. Set `authorizeAdministration` / `authorize_administration`
|
|
153
|
+
to allow action `observe` or `inspect`, resource `actor_diagnostics`, and resource ID
|
|
154
|
+
`JSON.stringify([actorType, actorId])`. Ruby receives a symbol action. Authorization
|
|
155
|
+
runs before reading summaries or registering observers; possessing an actor ID
|
|
156
|
+
confers no permission.
|
|
157
|
+
|
|
158
|
+
Diagnostics read at most `limit + 1` rows per queue source, with a hard limit
|
|
159
|
+
of 100 rows. Each category returns `sampled`, `truncated`, and
|
|
160
|
+
`oldestAgeMilliseconds`.
|
|
161
|
+
The limit applies to each combined category: one effect plus one broadcast with
|
|
162
|
+
`limit: 1` returns `sampled: 1, truncated: true`, even when both source queries
|
|
163
|
+
returned all their rows. The extra row proves that the category exceeds its cap.
|
|
164
|
+
The last value measures nonnegative time since availability (or terminal failure
|
|
165
|
+
for recovery callbacks); future reminders have zero age. No payloads or row
|
|
166
|
+
identifiers are returned. Samples are observations across several queries,
|
|
167
|
+
not an atomic fleet snapshot. Large queues can still require database scanning;
|
|
168
|
+
the bound limits materialized rows and response size, not query execution time.
|
|
169
|
+
|
|
170
|
+
Categories are mailbox (ready and claimed), outbox (pending and processing effects
|
|
171
|
+
and broadcasts), reminders (scheduled and paused), retries (failed messages still
|
|
172
|
+
eligible to run), and recoveryFailures (dead internal effect recovery
|
|
173
|
+
callback messages). Durable Objects does not implement process-heartbeat effect recovery;
|
|
174
|
+
its recoveryFailures category is empty. Recovery failures are durable records,
|
|
175
|
+
not a history of transient database or exporter exceptions.
|
|
176
|
+
|
|
177
|
+
## A query that works across adapters
|
|
178
|
+
|
|
179
|
+
Write one envelope per line to `events.jsonl`, using the same instrumentation hook
|
|
180
|
+
with SQLite and PostgreSQL. This query reports completed attempts by adapter:
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
jq -s 'map(select(.name == "solid_objects.message.completed"))
|
|
184
|
+
| group_by(.adapter)
|
|
185
|
+
| map({adapter: .[0].adapter, completed: length,
|
|
186
|
+
mean_ms: (map(.attributes.durationMilliseconds) | add / length)})' events.jsonl
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
A dashboard can chart the event counter by adapter and outcome and the duration,
|
|
190
|
+
reminder lateness, and outbox age distributions using exactly the same fields.
|
|
191
|
+
Compare workloads with the same actor types and sampling policy. Counts measure
|
|
192
|
+
observations and cannot replace a database query for authoritative queue state.
|