@qlever-llc/trellis 0.10.11 → 0.10.12
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/esm/errors/TrellisError.d.ts +3 -3
- package/esm/errors/TrellisError.js +3 -3
- package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/esm/server/internal_jobs/job-manager.js +32 -1
- package/esm/server/runtime.d.ts +3 -0
- package/esm/server/runtime.d.ts.map +1 -1
- package/esm/server/service.d.ts +15 -0
- package/esm/server/service.d.ts.map +1 -1
- package/esm/server/service.js +8 -0
- package/esm/server.d.ts.map +1 -1
- package/esm/server.js +54 -6
- package/esm/service/deno.d.ts +1 -1
- package/esm/service/deno.d.ts.map +1 -1
- package/esm/service/mod.d.ts +1 -1
- package/esm/service/mod.d.ts.map +1 -1
- package/esm/service/node.d.ts +1 -1
- package/esm/service/node.d.ts.map +1 -1
- package/esm/service/outbox_inbox.d.ts.map +1 -1
- package/esm/service/outbox_inbox.js +14 -0
- package/esm/telemetry/core.d.ts.map +1 -1
- package/esm/telemetry/core.js +1 -1
- package/esm/telemetry/env.d.ts.map +1 -1
- package/esm/telemetry/env.js +6 -1
- package/esm/telemetry/init.d.ts +3 -0
- package/esm/telemetry/init.d.ts.map +1 -0
- package/esm/telemetry/init.js +7 -0
- package/esm/telemetry/metrics.d.ts +34 -0
- package/esm/telemetry/metrics.d.ts.map +1 -0
- package/esm/telemetry/metrics.js +181 -0
- package/esm/telemetry/mod.d.ts +3 -0
- package/esm/telemetry/mod.d.ts.map +1 -1
- package/esm/telemetry/mod.js +2 -0
- package/esm/telemetry/runtime.d.ts +2 -0
- package/esm/telemetry/runtime.d.ts.map +1 -0
- package/esm/telemetry/runtime.js +134 -0
- package/esm/telemetry.d.ts +3 -0
- package/esm/telemetry.d.ts.map +1 -0
- package/esm/telemetry.js +2 -0
- package/esm/transfer.d.ts.map +1 -1
- package/esm/transfer.js +27 -16
- package/esm/trellis.d.ts.map +1 -1
- package/esm/trellis.js +460 -56
- package/package.json +7 -5
- package/script/errors/TrellisError.d.ts +3 -3
- package/script/errors/TrellisError.js +3 -3
- package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/script/server/internal_jobs/job-manager.js +32 -1
- package/script/server/runtime.d.ts +3 -0
- package/script/server/runtime.d.ts.map +1 -1
- package/script/server/service.d.ts +15 -0
- package/script/server/service.d.ts.map +1 -1
- package/script/server/service.js +8 -0
- package/script/server.d.ts.map +1 -1
- package/script/server.js +54 -6
- package/script/service/deno.d.ts +1 -1
- package/script/service/deno.d.ts.map +1 -1
- package/script/service/mod.d.ts +1 -1
- package/script/service/mod.d.ts.map +1 -1
- package/script/service/node.d.ts +1 -1
- package/script/service/node.d.ts.map +1 -1
- package/script/service/outbox_inbox.d.ts.map +1 -1
- package/script/service/outbox_inbox.js +14 -0
- package/script/telemetry/core.d.ts.map +1 -1
- package/script/telemetry/core.js +1 -1
- package/script/telemetry/env.d.ts.map +1 -1
- package/script/telemetry/env.js +6 -1
- package/script/telemetry/init.d.ts +3 -0
- package/script/telemetry/init.d.ts.map +1 -0
- package/script/telemetry/init.js +10 -0
- package/script/telemetry/metrics.d.ts +34 -0
- package/script/telemetry/metrics.d.ts.map +1 -0
- package/script/telemetry/metrics.js +186 -0
- package/script/telemetry/mod.d.ts +3 -0
- package/script/telemetry/mod.d.ts.map +1 -1
- package/script/telemetry/mod.js +7 -1
- package/script/telemetry/runtime.d.ts +2 -0
- package/script/telemetry/runtime.d.ts.map +1 -0
- package/script/telemetry/runtime.js +137 -0
- package/script/telemetry.d.ts +3 -0
- package/script/telemetry.d.ts.map +1 -0
- package/script/telemetry.js +18 -0
- package/script/transfer.d.ts.map +1 -1
- package/script/transfer.js +28 -17
- package/script/trellis.d.ts.map +1 -1
- package/script/trellis.js +490 -86
- package/src/errors/TrellisError.ts +4 -4
- package/src/server/internal_jobs/job-manager.ts +35 -5
- package/src/server/runtime.ts +4 -0
- package/src/server/service.ts +27 -0
- package/src/server.ts +66 -11
- package/src/service/deno.ts +1 -0
- package/src/service/mod.ts +1 -0
- package/src/service/node.ts +1 -0
- package/src/service/outbox_inbox.ts +14 -0
- package/src/telemetry/core.ts +1 -1
- package/src/telemetry/env.ts +5 -1
- package/src/telemetry/init.ts +8 -0
- package/src/telemetry/metrics.ts +294 -0
- package/src/telemetry/mod.ts +7 -0
- package/src/telemetry/runtime.ts +218 -0
- package/src/telemetry.ts +2 -0
- package/src/transfer.ts +69 -30
- package/src/trellis.ts +487 -88
- package/esm/tracing.d.ts +0 -5
- package/esm/tracing.d.ts.map +0 -1
- package/esm/tracing.js +0 -8
- package/script/tracing.d.ts +0 -5
- package/script/tracing.d.ts.map +0 -1
- package/script/tracing.js +0 -27
- package/src/tracing.ts +0 -28
package/script/trellis.js
CHANGED
|
@@ -29,7 +29,7 @@ const jetstream_1 = require("@nats-io/jetstream");
|
|
|
29
29
|
const nats_core_1 = require("@nats-io/nats-core");
|
|
30
30
|
const mod_js_1 = require("./contract_support/mod.js");
|
|
31
31
|
const result_1 = require("@qlever-llc/result");
|
|
32
|
-
const
|
|
32
|
+
const mod_js_2 = require("./telemetry/mod.js");
|
|
33
33
|
const typebox_1 = require("typebox");
|
|
34
34
|
const value_1 = require("typebox/value");
|
|
35
35
|
const ulid_1 = require("ulid");
|
|
@@ -220,6 +220,12 @@ function annotateHandlerBoundaryError(cause, context) {
|
|
|
220
220
|
error.withTraceId(context.traceId);
|
|
221
221
|
return error;
|
|
222
222
|
}
|
|
223
|
+
function recordRuntimeError(error, attributes) {
|
|
224
|
+
(0, mod_js_2.recordTrellisError)(error, {
|
|
225
|
+
messagingSystem: "nats",
|
|
226
|
+
...attributes,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
223
229
|
const DurableOperationSignalSchema = typebox_1.Type.Object({
|
|
224
230
|
operationId: typebox_1.Type.String(),
|
|
225
231
|
sequence: typebox_1.Type.Number(),
|
|
@@ -950,14 +956,27 @@ class Trellis {
|
|
|
950
956
|
const eventName = event;
|
|
951
957
|
const ctx = this.api["events"][eventName];
|
|
952
958
|
if (!ctx) {
|
|
953
|
-
|
|
959
|
+
const error = new index_js_1.UnexpectedError({
|
|
954
960
|
cause: __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_unknownApiError).call(this, "event", event.toString()),
|
|
955
961
|
context: { event: event.toString() },
|
|
956
|
-
})
|
|
962
|
+
});
|
|
963
|
+
recordRuntimeError(error, {
|
|
964
|
+
surface: "event",
|
|
965
|
+
direction: "publisher",
|
|
966
|
+
operation: event,
|
|
967
|
+
phase: "prepare",
|
|
968
|
+
});
|
|
969
|
+
return (0, result_1.err)(error);
|
|
957
970
|
}
|
|
958
971
|
const subject = this.template(ctx.subject, data).take();
|
|
959
972
|
if ((0, result_1.isErr)(subject)) {
|
|
960
973
|
globals_js_1.logger.error({ err: subject.error }, "Failed to template event.");
|
|
974
|
+
recordRuntimeError(subject.error, {
|
|
975
|
+
surface: "event",
|
|
976
|
+
direction: "publisher",
|
|
977
|
+
operation: event,
|
|
978
|
+
phase: "request_encoding",
|
|
979
|
+
});
|
|
961
980
|
return subject;
|
|
962
981
|
}
|
|
963
982
|
const header = {
|
|
@@ -971,11 +990,18 @@ class Trellis {
|
|
|
971
990
|
const msg = (0, codec_js_1.encodeSchema)(ctx.event, payload).take();
|
|
972
991
|
if ((0, result_1.isErr)(msg)) {
|
|
973
992
|
globals_js_1.logger.error({ err: msg.error }, "Failed to encode event.");
|
|
974
|
-
|
|
993
|
+
const error = new index_js_1.UnexpectedError({ cause: msg.error });
|
|
994
|
+
recordRuntimeError(error, {
|
|
995
|
+
surface: "event",
|
|
996
|
+
direction: "publisher",
|
|
997
|
+
operation: event,
|
|
998
|
+
phase: "request_encoding",
|
|
999
|
+
});
|
|
1000
|
+
return (0, result_1.err)(error);
|
|
975
1001
|
}
|
|
976
1002
|
const headers = (0, nats_core_1.headers)();
|
|
977
1003
|
headers.set("Nats-Msg-Id", header.id);
|
|
978
|
-
(0,
|
|
1004
|
+
(0, mod_js_2.injectTraceContext)((0, mod_js_2.createNatsHeaderCarrier)(headers));
|
|
979
1005
|
const headerRecord = {};
|
|
980
1006
|
for (const [key, value] of headers) {
|
|
981
1007
|
headerRecord[key] = value.join(",");
|
|
@@ -989,7 +1015,17 @@ class Trellis {
|
|
|
989
1015
|
}));
|
|
990
1016
|
}
|
|
991
1017
|
catch (cause) {
|
|
992
|
-
|
|
1018
|
+
const error = new index_js_1.UnexpectedError({
|
|
1019
|
+
cause,
|
|
1020
|
+
context: { event: event.toString() },
|
|
1021
|
+
});
|
|
1022
|
+
recordRuntimeError(error, {
|
|
1023
|
+
surface: "event",
|
|
1024
|
+
direction: "publisher",
|
|
1025
|
+
operation: event,
|
|
1026
|
+
phase: "prepare",
|
|
1027
|
+
});
|
|
1028
|
+
return (0, result_1.err)(error);
|
|
993
1029
|
}
|
|
994
1030
|
}
|
|
995
1031
|
/**
|
|
@@ -1008,7 +1044,17 @@ class Trellis {
|
|
|
1008
1044
|
return (0, result_1.ok)(undefined);
|
|
1009
1045
|
}
|
|
1010
1046
|
catch (cause) {
|
|
1011
|
-
|
|
1047
|
+
const error = new index_js_1.UnexpectedError({
|
|
1048
|
+
cause,
|
|
1049
|
+
context: { event: event.event },
|
|
1050
|
+
});
|
|
1051
|
+
recordRuntimeError(error, {
|
|
1052
|
+
surface: "event",
|
|
1053
|
+
direction: "publisher",
|
|
1054
|
+
operation: event.event,
|
|
1055
|
+
phase: "publish",
|
|
1056
|
+
});
|
|
1057
|
+
return (0, result_1.err)(error);
|
|
1012
1058
|
}
|
|
1013
1059
|
})());
|
|
1014
1060
|
}
|
|
@@ -1245,13 +1291,25 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1245
1291
|
__classPrivateFieldGet(this, _Trellis_log, "f").trace({ method: String(method) }, `Calling ${method.toString()}.`);
|
|
1246
1292
|
const msg = encodeRuntimeSchema(ctx.input, input).take();
|
|
1247
1293
|
if ((0, result_1.isErr)(msg)) {
|
|
1294
|
+
recordRuntimeError(msg.error, {
|
|
1295
|
+
surface: "rpc",
|
|
1296
|
+
direction: "client",
|
|
1297
|
+
operation: method,
|
|
1298
|
+
phase: "request_encoding",
|
|
1299
|
+
});
|
|
1248
1300
|
return msg;
|
|
1249
1301
|
}
|
|
1250
1302
|
const subject = this.template(ctx.subject, input).take();
|
|
1251
1303
|
if ((0, result_1.isErr)(subject)) {
|
|
1304
|
+
recordRuntimeError(subject.error, {
|
|
1305
|
+
surface: "rpc",
|
|
1306
|
+
direction: "client",
|
|
1307
|
+
operation: method,
|
|
1308
|
+
phase: "request_encoding",
|
|
1309
|
+
});
|
|
1252
1310
|
return subject;
|
|
1253
1311
|
}
|
|
1254
|
-
const span = (0,
|
|
1312
|
+
const span = (0, mod_js_2.startClientSpan)(method, subject);
|
|
1255
1313
|
const attempt = async () => {
|
|
1256
1314
|
const authHeaders = await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_createProof).call(this, subject, msg);
|
|
1257
1315
|
const headers = (0, nats_core_1.headers)();
|
|
@@ -1259,7 +1317,7 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1259
1317
|
headers.set("proof", authHeaders.proof);
|
|
1260
1318
|
headers.set("iat", String(authHeaders.iat));
|
|
1261
1319
|
headers.set("request-id", authHeaders.requestId);
|
|
1262
|
-
(0,
|
|
1320
|
+
(0, mod_js_2.injectTraceContext)((0, mod_js_2.createNatsHeaderCarrier)(headers), span);
|
|
1263
1321
|
const msgResult = await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_requestMessageWithRetry).call(this, {
|
|
1264
1322
|
method,
|
|
1265
1323
|
subject,
|
|
@@ -1270,30 +1328,50 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1270
1328
|
});
|
|
1271
1329
|
const response = msgResult.take();
|
|
1272
1330
|
if ((0, result_1.isErr)(response)) {
|
|
1331
|
+
recordRuntimeError(response.error, {
|
|
1332
|
+
surface: "rpc",
|
|
1333
|
+
direction: "client",
|
|
1334
|
+
operation: method,
|
|
1335
|
+
phase: "request_send",
|
|
1336
|
+
});
|
|
1273
1337
|
return response;
|
|
1274
1338
|
}
|
|
1275
1339
|
if (response.headers?.get("status") === "error") {
|
|
1276
1340
|
const json = safeJson(response).take();
|
|
1277
1341
|
if ((0, result_1.isErr)(json)) {
|
|
1278
|
-
|
|
1342
|
+
const error = requestFailedTransportError({
|
|
1279
1343
|
code: "trellis.request.invalid_response",
|
|
1280
1344
|
message: "Trellis returned an invalid response.",
|
|
1281
1345
|
hint: "Retry the request. If it keeps happening, check the Trellis capability handling this request.",
|
|
1282
1346
|
method,
|
|
1283
1347
|
subject,
|
|
1284
1348
|
cause: json.error.cause,
|
|
1285
|
-
})
|
|
1349
|
+
});
|
|
1350
|
+
recordRuntimeError(error, {
|
|
1351
|
+
surface: "rpc",
|
|
1352
|
+
direction: "client",
|
|
1353
|
+
operation: method,
|
|
1354
|
+
phase: "response_decoding",
|
|
1355
|
+
});
|
|
1356
|
+
return (0, result_1.err)(error);
|
|
1286
1357
|
}
|
|
1287
1358
|
const errorData = (0, codec_js_1.parse)(TrellisError_js_1.TrellisErrorDataSchema, json).take();
|
|
1288
1359
|
if ((0, result_1.isErr)(errorData)) {
|
|
1289
|
-
|
|
1360
|
+
const error = requestFailedTransportError({
|
|
1290
1361
|
code: "trellis.request.invalid_response",
|
|
1291
1362
|
message: "Trellis returned an invalid response.",
|
|
1292
1363
|
hint: "Retry the request. If it keeps happening, check the Trellis capability handling this request.",
|
|
1293
1364
|
method,
|
|
1294
1365
|
subject,
|
|
1295
1366
|
cause: errorData.error,
|
|
1296
|
-
})
|
|
1367
|
+
});
|
|
1368
|
+
recordRuntimeError(error, {
|
|
1369
|
+
surface: "rpc",
|
|
1370
|
+
direction: "client",
|
|
1371
|
+
operation: method,
|
|
1372
|
+
phase: "response_decoding",
|
|
1373
|
+
});
|
|
1374
|
+
return (0, result_1.err)(error);
|
|
1297
1375
|
}
|
|
1298
1376
|
const declaredErrorTypes = Array.isArray(ctx.declaredErrorTypes)
|
|
1299
1377
|
? ctx.declaredErrorTypes.filter((value) => typeof value === "string")
|
|
@@ -1304,41 +1382,66 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1304
1382
|
const reconstructed = reconstructDeclaredRpcError(declaredErrorTypes, runtimeErrors, errorData, json);
|
|
1305
1383
|
if (reconstructed) {
|
|
1306
1384
|
await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_handleBrowserAuthRequired).call(this, reconstructed);
|
|
1385
|
+
recordRuntimeError(new RemoteError_js_1.RemoteError({ error: errorData }), {
|
|
1386
|
+
surface: "rpc",
|
|
1387
|
+
direction: "client",
|
|
1388
|
+
operation: method,
|
|
1389
|
+
phase: "remote_error",
|
|
1390
|
+
});
|
|
1307
1391
|
return (0, result_1.err)(reconstructed);
|
|
1308
1392
|
}
|
|
1309
1393
|
const remoteError = new RemoteError_js_1.RemoteError({ error: errorData });
|
|
1310
1394
|
await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_handleBrowserAuthRequired).call(this, remoteError);
|
|
1395
|
+
recordRuntimeError(remoteError, {
|
|
1396
|
+
surface: "rpc",
|
|
1397
|
+
direction: "client",
|
|
1398
|
+
operation: method,
|
|
1399
|
+
phase: "remote_error",
|
|
1400
|
+
});
|
|
1311
1401
|
return (0, result_1.err)(remoteError);
|
|
1312
1402
|
}
|
|
1313
1403
|
const json = safeJson(response).take();
|
|
1314
1404
|
if ((0, result_1.isErr)(json)) {
|
|
1315
|
-
|
|
1405
|
+
const error = requestFailedTransportError({
|
|
1316
1406
|
code: "trellis.request.invalid_response",
|
|
1317
1407
|
message: "Trellis returned an invalid response.",
|
|
1318
1408
|
hint: "Retry the request. If it keeps happening, check the Trellis capability handling this request.",
|
|
1319
1409
|
method,
|
|
1320
1410
|
subject,
|
|
1321
1411
|
cause: json.error.cause,
|
|
1322
|
-
})
|
|
1412
|
+
});
|
|
1413
|
+
recordRuntimeError(error, {
|
|
1414
|
+
surface: "rpc",
|
|
1415
|
+
direction: "client",
|
|
1416
|
+
operation: method,
|
|
1417
|
+
phase: "response_decoding",
|
|
1418
|
+
});
|
|
1419
|
+
return (0, result_1.err)(error);
|
|
1323
1420
|
}
|
|
1324
1421
|
const outputResult = parseRuntimeSchema(ctx.output, json).take();
|
|
1325
1422
|
if ((0, result_1.isErr)(outputResult)) {
|
|
1423
|
+
recordRuntimeError(outputResult.error, {
|
|
1424
|
+
surface: "rpc",
|
|
1425
|
+
direction: "client",
|
|
1426
|
+
operation: method,
|
|
1427
|
+
phase: "response_decoding",
|
|
1428
|
+
});
|
|
1326
1429
|
return (0, result_1.err)(outputResult.error);
|
|
1327
1430
|
}
|
|
1328
1431
|
return (0, result_1.ok)(outputResult);
|
|
1329
1432
|
};
|
|
1330
|
-
return await (0,
|
|
1433
|
+
return await (0, mod_js_2.withSpanAsync)(span, async () => {
|
|
1331
1434
|
try {
|
|
1332
1435
|
const result = await attempt();
|
|
1333
1436
|
const value = result.take();
|
|
1334
1437
|
if ((0, result_1.isErr)(value)) {
|
|
1335
1438
|
span.setStatus({
|
|
1336
|
-
code:
|
|
1439
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1337
1440
|
message: value.error.message,
|
|
1338
1441
|
});
|
|
1339
1442
|
}
|
|
1340
1443
|
else {
|
|
1341
|
-
span.setStatus({ code:
|
|
1444
|
+
span.setStatus({ code: mod_js_2.SpanStatusCode.OK });
|
|
1342
1445
|
}
|
|
1343
1446
|
return result;
|
|
1344
1447
|
}
|
|
@@ -1347,10 +1450,16 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1347
1450
|
? cause
|
|
1348
1451
|
: new index_js_1.UnexpectedError({ cause });
|
|
1349
1452
|
span.setStatus({
|
|
1350
|
-
code:
|
|
1453
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1351
1454
|
message: unexpected.message,
|
|
1352
1455
|
});
|
|
1353
1456
|
span.recordException(unexpected);
|
|
1457
|
+
recordRuntimeError(unexpected, {
|
|
1458
|
+
surface: "rpc",
|
|
1459
|
+
direction: "client",
|
|
1460
|
+
operation: method,
|
|
1461
|
+
phase: "unexpected",
|
|
1462
|
+
});
|
|
1354
1463
|
return (0, result_1.err)(unexpected);
|
|
1355
1464
|
}
|
|
1356
1465
|
finally {
|
|
@@ -1419,18 +1528,32 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1419
1528
|
}, _Trellis_subscribeFeed = function _Trellis_subscribeFeed(feed, descriptor, input, opts) {
|
|
1420
1529
|
return result_1.AsyncResult.from((async () => {
|
|
1421
1530
|
const payload = encodeRuntimeSchema(descriptor.input, input).take();
|
|
1422
|
-
if ((0, result_1.isErr)(payload))
|
|
1531
|
+
if ((0, result_1.isErr)(payload)) {
|
|
1532
|
+
recordRuntimeError(payload.error, {
|
|
1533
|
+
surface: "feed",
|
|
1534
|
+
direction: "client",
|
|
1535
|
+
operation: feed,
|
|
1536
|
+
phase: "request_encoding",
|
|
1537
|
+
});
|
|
1423
1538
|
return payload;
|
|
1539
|
+
}
|
|
1424
1540
|
const subject = this.template(descriptor.subject, input).take();
|
|
1425
|
-
if ((0, result_1.isErr)(subject))
|
|
1541
|
+
if ((0, result_1.isErr)(subject)) {
|
|
1542
|
+
recordRuntimeError(subject.error, {
|
|
1543
|
+
surface: "feed",
|
|
1544
|
+
direction: "client",
|
|
1545
|
+
operation: feed,
|
|
1546
|
+
phase: "request_template",
|
|
1547
|
+
});
|
|
1426
1548
|
return subject;
|
|
1549
|
+
}
|
|
1427
1550
|
const authHeaders = await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_createProof).call(this, subject, payload);
|
|
1428
1551
|
const headers = (0, nats_core_1.headers)();
|
|
1429
1552
|
headers.set("session-key", this.auth.sessionKey);
|
|
1430
1553
|
headers.set("proof", authHeaders.proof);
|
|
1431
1554
|
headers.set("iat", String(authHeaders.iat));
|
|
1432
1555
|
headers.set("request-id", authHeaders.requestId);
|
|
1433
|
-
(0,
|
|
1556
|
+
(0, mod_js_2.injectTraceContext)((0, mod_js_2.createNatsHeaderCarrier)(headers));
|
|
1434
1557
|
const inbox = (0, nats_core_1.createInbox)(`_INBOX.${this.auth.sessionKey.slice(0, 16)}`);
|
|
1435
1558
|
const sub = this.nats.subscribe(inbox);
|
|
1436
1559
|
const iterator = sub[Symbol.asyncIterator]();
|
|
@@ -1443,13 +1566,20 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1443
1566
|
catch (cause) {
|
|
1444
1567
|
opts?.signal?.removeEventListener("abort", abort);
|
|
1445
1568
|
sub.unsubscribe();
|
|
1446
|
-
|
|
1569
|
+
const error = createTransportError({
|
|
1447
1570
|
code: "trellis.feed.subscribe_failed",
|
|
1448
1571
|
message: "Trellis could not subscribe to the feed.",
|
|
1449
1572
|
hint: "Retry the subscription. If it keeps failing, check Trellis runtime health.",
|
|
1450
1573
|
cause,
|
|
1451
1574
|
context: { feed, subject },
|
|
1452
|
-
})
|
|
1575
|
+
});
|
|
1576
|
+
recordRuntimeError(error, {
|
|
1577
|
+
surface: "feed",
|
|
1578
|
+
direction: "client",
|
|
1579
|
+
operation: feed,
|
|
1580
|
+
phase: "request_send",
|
|
1581
|
+
});
|
|
1582
|
+
return (0, result_1.err)(error);
|
|
1453
1583
|
}
|
|
1454
1584
|
let timeoutId;
|
|
1455
1585
|
let abortHandler;
|
|
@@ -1475,7 +1605,7 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1475
1605
|
if (firstFrame === "timeout" || firstFrame === "aborted") {
|
|
1476
1606
|
opts?.signal?.removeEventListener("abort", abort);
|
|
1477
1607
|
sub.unsubscribe();
|
|
1478
|
-
|
|
1608
|
+
const error = createTransportError({
|
|
1479
1609
|
code: firstFrame === "timeout"
|
|
1480
1610
|
? "trellis.feed.subscribe_timeout"
|
|
1481
1611
|
: "trellis.feed.subscribe_aborted",
|
|
@@ -1486,28 +1616,49 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1486
1616
|
? "Check that the target service is running and has the current deployment digest, then retry."
|
|
1487
1617
|
: "Retry the subscription if the feed is still needed.",
|
|
1488
1618
|
context: { feed, subject },
|
|
1489
|
-
})
|
|
1619
|
+
});
|
|
1620
|
+
recordRuntimeError(error, {
|
|
1621
|
+
surface: "feed",
|
|
1622
|
+
direction: "client",
|
|
1623
|
+
operation: feed,
|
|
1624
|
+
phase: "handshake",
|
|
1625
|
+
});
|
|
1626
|
+
return (0, result_1.err)(error);
|
|
1490
1627
|
}
|
|
1491
1628
|
if (firstFrame.done) {
|
|
1492
1629
|
opts?.signal?.removeEventListener("abort", abort);
|
|
1493
1630
|
sub.unsubscribe();
|
|
1494
|
-
|
|
1631
|
+
const error = createTransportError({
|
|
1495
1632
|
code: "trellis.feed.subscribe_closed",
|
|
1496
1633
|
message: "Trellis closed the feed before acknowledging it.",
|
|
1497
1634
|
hint: "Retry the subscription. If it keeps failing, check Trellis runtime health.",
|
|
1498
1635
|
context: { feed, subject },
|
|
1499
|
-
})
|
|
1636
|
+
});
|
|
1637
|
+
recordRuntimeError(error, {
|
|
1638
|
+
surface: "feed",
|
|
1639
|
+
direction: "client",
|
|
1640
|
+
operation: feed,
|
|
1641
|
+
phase: "handshake",
|
|
1642
|
+
});
|
|
1643
|
+
return (0, result_1.err)(error);
|
|
1500
1644
|
}
|
|
1501
1645
|
const firstMessage = firstFrame.value;
|
|
1502
1646
|
if (firstMessage.headers?.get("status") === "error") {
|
|
1503
1647
|
opts?.signal?.removeEventListener("abort", abort);
|
|
1504
1648
|
sub.unsubscribe();
|
|
1505
|
-
|
|
1649
|
+
const error = createTransportError({
|
|
1506
1650
|
code: "trellis.feed.failed",
|
|
1507
1651
|
message: "Trellis rejected the feed subscription.",
|
|
1508
1652
|
hint: "Retry the subscription. If it keeps failing, check Trellis runtime health and permissions.",
|
|
1509
1653
|
context: { feed, subject, frame: firstMessage.string() },
|
|
1510
|
-
})
|
|
1654
|
+
});
|
|
1655
|
+
recordRuntimeError(error, {
|
|
1656
|
+
surface: "feed",
|
|
1657
|
+
direction: "client",
|
|
1658
|
+
operation: feed,
|
|
1659
|
+
phase: "remote_error",
|
|
1660
|
+
});
|
|
1661
|
+
return (0, result_1.err)(error);
|
|
1511
1662
|
}
|
|
1512
1663
|
const firstEvent = firstMessage.headers?.get("feed-status") === "ready"
|
|
1513
1664
|
? undefined
|
|
@@ -1517,19 +1668,40 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1517
1668
|
try {
|
|
1518
1669
|
const parseFeedFrame = (msg) => {
|
|
1519
1670
|
if (msg.headers?.get("status") === "error") {
|
|
1520
|
-
|
|
1671
|
+
const error = createTransportError({
|
|
1521
1672
|
code: "trellis.feed.failed",
|
|
1522
1673
|
message: "Trellis stopped the feed.",
|
|
1523
1674
|
hint: "Retry the subscription. If it keeps failing, check Trellis runtime health.",
|
|
1524
1675
|
context: { feed, subject, frame: msg.string() },
|
|
1525
1676
|
});
|
|
1677
|
+
recordRuntimeError(error, {
|
|
1678
|
+
surface: "feed",
|
|
1679
|
+
direction: "client",
|
|
1680
|
+
operation: feed,
|
|
1681
|
+
phase: "remote_error",
|
|
1682
|
+
});
|
|
1683
|
+
throw error;
|
|
1526
1684
|
}
|
|
1527
1685
|
const json = safeJson(msg).take();
|
|
1528
|
-
if ((0, result_1.isErr)(json))
|
|
1686
|
+
if ((0, result_1.isErr)(json)) {
|
|
1687
|
+
recordRuntimeError(json.error, {
|
|
1688
|
+
surface: "feed",
|
|
1689
|
+
direction: "client",
|
|
1690
|
+
operation: feed,
|
|
1691
|
+
phase: "event_decoding",
|
|
1692
|
+
});
|
|
1529
1693
|
throw json.error;
|
|
1694
|
+
}
|
|
1530
1695
|
const parsed = parseRuntimeSchema(eventSchema, json).take();
|
|
1531
|
-
if ((0, result_1.isErr)(parsed))
|
|
1696
|
+
if ((0, result_1.isErr)(parsed)) {
|
|
1697
|
+
recordRuntimeError(parsed.error, {
|
|
1698
|
+
surface: "feed",
|
|
1699
|
+
direction: "client",
|
|
1700
|
+
operation: feed,
|
|
1701
|
+
phase: "event_validation",
|
|
1702
|
+
});
|
|
1532
1703
|
throw parsed.error;
|
|
1704
|
+
}
|
|
1533
1705
|
return parsed;
|
|
1534
1706
|
};
|
|
1535
1707
|
if (firstEvent)
|
|
@@ -1557,13 +1729,20 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1557
1729
|
await this.nats.flush();
|
|
1558
1730
|
}
|
|
1559
1731
|
catch (cause) {
|
|
1560
|
-
|
|
1732
|
+
const error = createTransportError({
|
|
1561
1733
|
code: "trellis.feed.listen_failed",
|
|
1562
1734
|
message: "Trellis could not listen for feed requests.",
|
|
1563
1735
|
hint: "Check the service deployment digest and runtime permissions, then restart the service.",
|
|
1564
1736
|
cause,
|
|
1565
1737
|
context: { feed, subject },
|
|
1566
1738
|
});
|
|
1739
|
+
recordRuntimeError(error, {
|
|
1740
|
+
surface: "feed",
|
|
1741
|
+
direction: "server",
|
|
1742
|
+
operation: feed,
|
|
1743
|
+
phase: "listen",
|
|
1744
|
+
});
|
|
1745
|
+
throw error;
|
|
1567
1746
|
}
|
|
1568
1747
|
const task = result_1.AsyncResult.try(async () => {
|
|
1569
1748
|
for await (const msg of sub) {
|
|
@@ -1584,6 +1763,12 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1584
1763
|
contractDigest: this.contractDigest,
|
|
1585
1764
|
traceId: traceIdFromTraceparent(msg.headers?.get("traceparent")),
|
|
1586
1765
|
});
|
|
1766
|
+
recordRuntimeError(error, {
|
|
1767
|
+
surface: "feed",
|
|
1768
|
+
direction: "server",
|
|
1769
|
+
operation: feed,
|
|
1770
|
+
phase: "handler_throw",
|
|
1771
|
+
});
|
|
1587
1772
|
__classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_respondWithError).call(this, msg, error);
|
|
1588
1773
|
}
|
|
1589
1774
|
})();
|
|
@@ -1592,11 +1777,25 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1592
1777
|
__classPrivateFieldGet(this, _Trellis_tasks, "f").add(`feed:${feed}`, task);
|
|
1593
1778
|
}, _Trellis_processFeedMessage = async function _Trellis_processFeedMessage(feed, descriptor, msg, handler) {
|
|
1594
1779
|
const json = safeJson(msg).take();
|
|
1595
|
-
if ((0, result_1.isErr)(json))
|
|
1780
|
+
if ((0, result_1.isErr)(json)) {
|
|
1781
|
+
recordRuntimeError(json.error, {
|
|
1782
|
+
surface: "feed",
|
|
1783
|
+
direction: "server",
|
|
1784
|
+
operation: feed,
|
|
1785
|
+
phase: "request_decoding",
|
|
1786
|
+
});
|
|
1596
1787
|
return json;
|
|
1788
|
+
}
|
|
1597
1789
|
const parsed = parseRuntimeSchema(descriptor.input, json).take();
|
|
1598
|
-
if ((0, result_1.isErr)(parsed))
|
|
1790
|
+
if ((0, result_1.isErr)(parsed)) {
|
|
1791
|
+
recordRuntimeError(parsed.error, {
|
|
1792
|
+
surface: "feed",
|
|
1793
|
+
direction: "server",
|
|
1794
|
+
operation: feed,
|
|
1795
|
+
phase: "input_validation",
|
|
1796
|
+
});
|
|
1599
1797
|
return parsed;
|
|
1798
|
+
}
|
|
1600
1799
|
const caller = await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_authenticateFeedRequest).call(this, {
|
|
1601
1800
|
feed,
|
|
1602
1801
|
subject: msg.subject,
|
|
@@ -1605,12 +1804,26 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1605
1804
|
requiredCapabilities: descriptor.subscribeCapabilities,
|
|
1606
1805
|
});
|
|
1607
1806
|
const callerValue = caller.take();
|
|
1608
|
-
if ((0, result_1.isErr)(callerValue))
|
|
1807
|
+
if ((0, result_1.isErr)(callerValue)) {
|
|
1808
|
+
recordRuntimeError(callerValue.error, {
|
|
1809
|
+
surface: "feed",
|
|
1810
|
+
direction: "server",
|
|
1811
|
+
operation: feed,
|
|
1812
|
+
phase: "auth",
|
|
1813
|
+
});
|
|
1609
1814
|
return callerValue;
|
|
1815
|
+
}
|
|
1610
1816
|
if (!msg.reply) {
|
|
1611
|
-
|
|
1817
|
+
const error = new index_js_1.UnexpectedError({
|
|
1612
1818
|
context: { feed, reason: "missing_reply" },
|
|
1613
|
-
})
|
|
1819
|
+
});
|
|
1820
|
+
recordRuntimeError(error, {
|
|
1821
|
+
surface: "feed",
|
|
1822
|
+
direction: "server",
|
|
1823
|
+
operation: feed,
|
|
1824
|
+
phase: "handshake",
|
|
1825
|
+
});
|
|
1826
|
+
return (0, result_1.err)(error);
|
|
1614
1827
|
}
|
|
1615
1828
|
const readyHeaders = (0, nats_core_1.headers)();
|
|
1616
1829
|
readyHeaders.set("feed-status", "ready");
|
|
@@ -1624,15 +1837,44 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1624
1837
|
signal: controller.signal,
|
|
1625
1838
|
emit: (event) => result_1.AsyncResult.from((async () => {
|
|
1626
1839
|
const payload = encodeRuntimeSchema(descriptor.event, event).take();
|
|
1627
|
-
if ((0, result_1.isErr)(payload))
|
|
1840
|
+
if ((0, result_1.isErr)(payload)) {
|
|
1841
|
+
recordRuntimeError(payload.error, {
|
|
1842
|
+
surface: "feed",
|
|
1843
|
+
direction: "server",
|
|
1844
|
+
operation: feed,
|
|
1845
|
+
phase: "event_encoding",
|
|
1846
|
+
});
|
|
1628
1847
|
return payload;
|
|
1848
|
+
}
|
|
1629
1849
|
if (!msg.reply) {
|
|
1630
|
-
|
|
1850
|
+
const error = new index_js_1.UnexpectedError({
|
|
1631
1851
|
context: { feed, reason: "missing_reply" },
|
|
1632
|
-
})
|
|
1852
|
+
});
|
|
1853
|
+
recordRuntimeError(error, {
|
|
1854
|
+
surface: "feed",
|
|
1855
|
+
direction: "server",
|
|
1856
|
+
operation: feed,
|
|
1857
|
+
phase: "event_publish",
|
|
1858
|
+
});
|
|
1859
|
+
return (0, result_1.err)(error);
|
|
1860
|
+
}
|
|
1861
|
+
try {
|
|
1862
|
+
this.nats.publish(msg.reply, payload);
|
|
1863
|
+
await this.nats.flush();
|
|
1864
|
+
}
|
|
1865
|
+
catch (cause) {
|
|
1866
|
+
const error = new index_js_1.UnexpectedError({
|
|
1867
|
+
cause,
|
|
1868
|
+
context: { feed },
|
|
1869
|
+
});
|
|
1870
|
+
recordRuntimeError(error, {
|
|
1871
|
+
surface: "feed",
|
|
1872
|
+
direction: "server",
|
|
1873
|
+
operation: feed,
|
|
1874
|
+
phase: "event_publish",
|
|
1875
|
+
});
|
|
1876
|
+
return (0, result_1.err)(error);
|
|
1633
1877
|
}
|
|
1634
|
-
this.nats.publish(msg.reply, payload);
|
|
1635
|
-
await this.nats.flush();
|
|
1636
1878
|
return (0, result_1.ok)(undefined);
|
|
1637
1879
|
})()),
|
|
1638
1880
|
});
|
|
@@ -1640,14 +1882,21 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1640
1882
|
? handlerResult.take()
|
|
1641
1883
|
: handlerResult;
|
|
1642
1884
|
if ((0, result_1.isErr)(handlerOutcome)) {
|
|
1643
|
-
|
|
1885
|
+
const error = annotateHandlerBoundaryError(handlerOutcome.error, {
|
|
1644
1886
|
feed,
|
|
1645
1887
|
requestId: msg.headers?.get("request-id"),
|
|
1646
1888
|
service: this.name,
|
|
1647
1889
|
contractId: this.contractId,
|
|
1648
1890
|
contractDigest: this.contractDigest,
|
|
1649
1891
|
traceId: traceIdFromTraceparent(msg.headers?.get("traceparent")),
|
|
1650
|
-
})
|
|
1892
|
+
});
|
|
1893
|
+
recordRuntimeError(error, {
|
|
1894
|
+
surface: "feed",
|
|
1895
|
+
direction: "server",
|
|
1896
|
+
operation: feed,
|
|
1897
|
+
phase: "handler_result",
|
|
1898
|
+
});
|
|
1899
|
+
return (0, result_1.err)(error);
|
|
1651
1900
|
}
|
|
1652
1901
|
return (0, result_1.ok)(undefined);
|
|
1653
1902
|
}
|
|
@@ -1699,31 +1948,43 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1699
1948
|
}, _Trellis_processRPCMessage = async function _Trellis_processRPCMessage(method, ctx, msg, fn, handlerTrellis) {
|
|
1700
1949
|
__classPrivateFieldGet(this, _Trellis_log, "f").debug({ method: String(method), subject: msg.subject }, "Processing RPC message");
|
|
1701
1950
|
// Extract trace context from incoming NATS headers
|
|
1702
|
-
const parentContext = (0,
|
|
1951
|
+
const parentContext = (0, mod_js_2.extractTraceContext)((0, mod_js_2.createNatsHeaderCarrier)({
|
|
1703
1952
|
get: (k) => msg.headers?.get(k) ?? undefined,
|
|
1704
1953
|
set: () => { }, // Server doesn't need to set headers on incoming messages
|
|
1705
1954
|
}));
|
|
1706
1955
|
// Start a server span for this RPC handler
|
|
1707
|
-
const span = (0,
|
|
1956
|
+
const span = (0, mod_js_2.startServerSpan)(method, msg.subject, parentContext);
|
|
1708
1957
|
const incomingTraceId = traceIdFromTraceparent(msg.headers?.get("traceparent"));
|
|
1709
1958
|
// Execute the handler within the span's context
|
|
1710
|
-
return (0,
|
|
1959
|
+
return (0, mod_js_2.withSpanAsync)(span, async () => {
|
|
1711
1960
|
const execute = async () => {
|
|
1712
1961
|
const jsonData = safeJson(msg).take();
|
|
1713
1962
|
if ((0, result_1.isErr)(jsonData)) {
|
|
1714
1963
|
__classPrivateFieldGet(this, _Trellis_log, "f").warn({ method, error: jsonData.error.message }, "Failed to parse JSON");
|
|
1715
1964
|
span.setStatus({
|
|
1716
|
-
code:
|
|
1965
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1717
1966
|
message: "Failed to parse JSON",
|
|
1718
1967
|
});
|
|
1968
|
+
recordRuntimeError(jsonData.error, {
|
|
1969
|
+
surface: "rpc",
|
|
1970
|
+
direction: "server",
|
|
1971
|
+
operation: String(method),
|
|
1972
|
+
phase: "parse",
|
|
1973
|
+
});
|
|
1719
1974
|
return jsonData;
|
|
1720
1975
|
}
|
|
1721
1976
|
const parsedInput = parseRuntimeSchema(ctx.input, jsonData).take();
|
|
1722
1977
|
if ((0, result_1.isErr)(parsedInput)) {
|
|
1723
1978
|
span.setStatus({
|
|
1724
|
-
code:
|
|
1979
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1725
1980
|
message: "Input validation failed",
|
|
1726
1981
|
});
|
|
1982
|
+
recordRuntimeError(parsedInput.error, {
|
|
1983
|
+
surface: "rpc",
|
|
1984
|
+
direction: "server",
|
|
1985
|
+
operation: String(method),
|
|
1986
|
+
phase: "input_validation",
|
|
1987
|
+
});
|
|
1727
1988
|
return parsedInput;
|
|
1728
1989
|
}
|
|
1729
1990
|
let caller;
|
|
@@ -1746,22 +2007,43 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1746
2007
|
if (!sessionKey) {
|
|
1747
2008
|
__classPrivateFieldGet(this, _Trellis_log, "f").warn({ method }, "Missing session-key header");
|
|
1748
2009
|
span.setStatus({
|
|
1749
|
-
code:
|
|
2010
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1750
2011
|
message: "Missing session-key",
|
|
1751
2012
|
});
|
|
1752
|
-
|
|
2013
|
+
const error = new index_js_1.AuthError({ reason: "missing_session_key" });
|
|
2014
|
+
recordRuntimeError(error, {
|
|
2015
|
+
surface: "rpc",
|
|
2016
|
+
direction: "server",
|
|
2017
|
+
operation: String(method),
|
|
2018
|
+
phase: "auth",
|
|
2019
|
+
});
|
|
2020
|
+
return (0, result_1.err)(error);
|
|
1753
2021
|
}
|
|
1754
2022
|
if (!proof) {
|
|
1755
2023
|
__classPrivateFieldGet(this, _Trellis_log, "f").warn({ method }, "Missing proof in request");
|
|
1756
2024
|
span.setStatus({
|
|
1757
|
-
code:
|
|
2025
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1758
2026
|
message: "Missing proof",
|
|
1759
2027
|
});
|
|
1760
|
-
|
|
2028
|
+
const error = new index_js_1.AuthError({ reason: "missing_proof" });
|
|
2029
|
+
recordRuntimeError(error, {
|
|
2030
|
+
surface: "rpc",
|
|
2031
|
+
direction: "server",
|
|
2032
|
+
operation: String(method),
|
|
2033
|
+
phase: "auth",
|
|
2034
|
+
});
|
|
2035
|
+
return (0, result_1.err)(error);
|
|
1761
2036
|
}
|
|
1762
2037
|
const iat = Number(iatHeader);
|
|
1763
2038
|
if (!Number.isSafeInteger(iat) || !requestId) {
|
|
1764
|
-
|
|
2039
|
+
const error = new index_js_1.AuthError({ reason: "invalid_signature" });
|
|
2040
|
+
recordRuntimeError(error, {
|
|
2041
|
+
surface: "rpc",
|
|
2042
|
+
direction: "server",
|
|
2043
|
+
operation: String(method),
|
|
2044
|
+
phase: "auth",
|
|
2045
|
+
});
|
|
2046
|
+
return (0, result_1.err)(error);
|
|
1765
2047
|
}
|
|
1766
2048
|
// Verify proof signature locally using the raw request bytes we received.
|
|
1767
2049
|
const payloadBytes = msg.data ?? new Uint8Array();
|
|
@@ -1777,13 +2059,20 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1777
2059
|
verifyResult.take() === true;
|
|
1778
2060
|
if (!signatureOk) {
|
|
1779
2061
|
span.setStatus({
|
|
1780
|
-
code:
|
|
2062
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1781
2063
|
message: "Invalid signature",
|
|
1782
2064
|
});
|
|
1783
|
-
|
|
2065
|
+
const error = new index_js_1.AuthError({
|
|
1784
2066
|
reason: "invalid_signature",
|
|
1785
2067
|
context: { sessionKey },
|
|
1786
|
-
})
|
|
2068
|
+
});
|
|
2069
|
+
recordRuntimeError(error, {
|
|
2070
|
+
surface: "rpc",
|
|
2071
|
+
direction: "server",
|
|
2072
|
+
operation: String(method),
|
|
2073
|
+
phase: "auth",
|
|
2074
|
+
});
|
|
2075
|
+
return (0, result_1.err)(error);
|
|
1787
2076
|
}
|
|
1788
2077
|
let auth;
|
|
1789
2078
|
for (let attempt = 0; attempt < DEFAULT_AUTH_VALIDATE_SESSION_RETRY_ATTEMPTS; attempt++) {
|
|
@@ -1809,9 +2098,16 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1809
2098
|
await sleep(DEFAULT_AUTH_VALIDATE_SESSION_RETRY_MS * (attempt + 1));
|
|
1810
2099
|
}
|
|
1811
2100
|
if (!auth) {
|
|
1812
|
-
|
|
2101
|
+
const error = new index_js_1.UnexpectedError({
|
|
1813
2102
|
context: { reason: "missing_auth_validate_result" },
|
|
1814
|
-
})
|
|
2103
|
+
});
|
|
2104
|
+
recordRuntimeError(error, {
|
|
2105
|
+
surface: "rpc",
|
|
2106
|
+
direction: "server",
|
|
2107
|
+
operation: String(method),
|
|
2108
|
+
phase: "auth",
|
|
2109
|
+
});
|
|
2110
|
+
return (0, result_1.err)(error);
|
|
1815
2111
|
}
|
|
1816
2112
|
if (auth instanceof Error) {
|
|
1817
2113
|
__classPrivateFieldGet(this, _Trellis_log, "f").warn({
|
|
@@ -1823,37 +2119,64 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1823
2119
|
: undefined,
|
|
1824
2120
|
}, "Auth.Requests.Validate failed");
|
|
1825
2121
|
span.setStatus({
|
|
1826
|
-
code:
|
|
2122
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1827
2123
|
message: "Auth.Requests.Validate failed",
|
|
1828
2124
|
});
|
|
1829
2125
|
if (auth instanceof result_1.BaseError) {
|
|
2126
|
+
recordRuntimeError(auth, {
|
|
2127
|
+
surface: "rpc",
|
|
2128
|
+
direction: "server",
|
|
2129
|
+
operation: String(method),
|
|
2130
|
+
phase: "auth",
|
|
2131
|
+
});
|
|
1830
2132
|
return (0, result_1.err)(auth);
|
|
1831
2133
|
}
|
|
1832
|
-
|
|
2134
|
+
const error = new index_js_1.UnexpectedError({ cause: auth });
|
|
2135
|
+
recordRuntimeError(error, {
|
|
2136
|
+
surface: "rpc",
|
|
2137
|
+
direction: "server",
|
|
2138
|
+
operation: String(method),
|
|
2139
|
+
phase: "auth",
|
|
2140
|
+
});
|
|
2141
|
+
return (0, result_1.err)(error);
|
|
1833
2142
|
}
|
|
1834
2143
|
if (!auth.allowed) {
|
|
1835
2144
|
span.setStatus({
|
|
1836
|
-
code:
|
|
2145
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1837
2146
|
message: "Insufficient permissions",
|
|
1838
2147
|
});
|
|
1839
|
-
|
|
2148
|
+
const error = new index_js_1.AuthError({
|
|
1840
2149
|
reason: "insufficient_permissions",
|
|
1841
2150
|
context: {
|
|
1842
2151
|
requiredCapabilities: ctx.callerCapabilities,
|
|
1843
2152
|
userCapabilities: auth.caller.capabilities,
|
|
1844
2153
|
},
|
|
1845
|
-
})
|
|
2154
|
+
});
|
|
2155
|
+
recordRuntimeError(error, {
|
|
2156
|
+
surface: "rpc",
|
|
2157
|
+
direction: "server",
|
|
2158
|
+
operation: String(method),
|
|
2159
|
+
phase: "auth",
|
|
2160
|
+
});
|
|
2161
|
+
return (0, result_1.err)(error);
|
|
1846
2162
|
}
|
|
1847
2163
|
if (typeof msg.reply !== "string" ||
|
|
1848
2164
|
!msg.reply.startsWith(`${auth.inboxPrefix}.`)) {
|
|
1849
2165
|
span.setStatus({
|
|
1850
|
-
code:
|
|
2166
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1851
2167
|
message: "Reply subject mismatch",
|
|
1852
2168
|
});
|
|
1853
|
-
|
|
2169
|
+
const error = new index_js_1.AuthError({
|
|
1854
2170
|
reason: "reply_subject_mismatch",
|
|
1855
2171
|
context: { expected: auth.inboxPrefix, actual: msg.reply },
|
|
1856
|
-
})
|
|
2172
|
+
});
|
|
2173
|
+
recordRuntimeError(error, {
|
|
2174
|
+
surface: "rpc",
|
|
2175
|
+
direction: "server",
|
|
2176
|
+
operation: String(method),
|
|
2177
|
+
phase: "auth",
|
|
2178
|
+
});
|
|
2179
|
+
return (0, result_1.err)(error);
|
|
1857
2180
|
}
|
|
1858
2181
|
caller = auth.caller;
|
|
1859
2182
|
}
|
|
@@ -1897,10 +2220,16 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1897
2220
|
: error.cause,
|
|
1898
2221
|
}, "Handler threw unexpectedly.");
|
|
1899
2222
|
span.setStatus({
|
|
1900
|
-
code:
|
|
2223
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1901
2224
|
message: error.message,
|
|
1902
2225
|
});
|
|
1903
2226
|
span.recordException(error);
|
|
2227
|
+
recordRuntimeError(error, {
|
|
2228
|
+
surface: "rpc",
|
|
2229
|
+
direction: "server",
|
|
2230
|
+
operation: String(method),
|
|
2231
|
+
phase: "handler_throw",
|
|
2232
|
+
});
|
|
1904
2233
|
return (0, result_1.err)(error);
|
|
1905
2234
|
}
|
|
1906
2235
|
const handlerResult = handlerResultWrapped.take();
|
|
@@ -1923,20 +2252,32 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
1923
2252
|
: error.cause,
|
|
1924
2253
|
}, "Handler returned error.");
|
|
1925
2254
|
span.setStatus({
|
|
1926
|
-
code:
|
|
2255
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1927
2256
|
message: error.message,
|
|
1928
2257
|
});
|
|
2258
|
+
recordRuntimeError(error, {
|
|
2259
|
+
surface: "rpc",
|
|
2260
|
+
direction: "server",
|
|
2261
|
+
operation: String(method),
|
|
2262
|
+
phase: "handler_result",
|
|
2263
|
+
});
|
|
1929
2264
|
return (0, result_1.err)(error);
|
|
1930
2265
|
}
|
|
1931
2266
|
const encoded = (0, codec_js_1.encodeSchema)(ctx.output, handlerOutcome).take();
|
|
1932
2267
|
if ((0, result_1.isErr)(encoded)) {
|
|
1933
2268
|
span.setStatus({
|
|
1934
|
-
code:
|
|
2269
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
1935
2270
|
message: "Output encoding failed",
|
|
1936
2271
|
});
|
|
2272
|
+
recordRuntimeError(encoded.error, {
|
|
2273
|
+
surface: "rpc",
|
|
2274
|
+
direction: "server",
|
|
2275
|
+
operation: String(method),
|
|
2276
|
+
phase: "output_encoding",
|
|
2277
|
+
});
|
|
1937
2278
|
return encoded;
|
|
1938
2279
|
}
|
|
1939
|
-
span.setStatus({ code:
|
|
2280
|
+
span.setStatus({ code: mod_js_2.SpanStatusCode.OK });
|
|
1940
2281
|
return (0, result_1.ok)(encoded);
|
|
1941
2282
|
};
|
|
1942
2283
|
const result = await execute();
|
|
@@ -2010,6 +2351,12 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2010
2351
|
const m = parsedEvent.take();
|
|
2011
2352
|
if ((0, result_1.isErr)(m)) {
|
|
2012
2353
|
__classPrivateFieldGet(this, _Trellis_log, "f").error({ error: m.error }, "Event validation failed");
|
|
2354
|
+
recordRuntimeError(m.error, {
|
|
2355
|
+
surface: "event",
|
|
2356
|
+
direction: "consumer",
|
|
2357
|
+
operation: String(event),
|
|
2358
|
+
phase: "input_validation",
|
|
2359
|
+
});
|
|
2013
2360
|
continue;
|
|
2014
2361
|
}
|
|
2015
2362
|
const handlerResult = await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_invokeEventHandler).call(this, {
|
|
@@ -2021,6 +2368,12 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2021
2368
|
});
|
|
2022
2369
|
const handlerValue = handlerResult.take();
|
|
2023
2370
|
if ((0, result_1.isErr)(handlerValue)) {
|
|
2371
|
+
recordRuntimeError(handlerValue.error, {
|
|
2372
|
+
surface: "event",
|
|
2373
|
+
direction: "consumer",
|
|
2374
|
+
operation: String(event),
|
|
2375
|
+
phase: "handler_result",
|
|
2376
|
+
});
|
|
2024
2377
|
__classPrivateFieldGet(this, _Trellis_log, "f").error({
|
|
2025
2378
|
error: handlerValue.error.toSerializable(),
|
|
2026
2379
|
event,
|
|
@@ -2220,6 +2573,12 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2220
2573
|
const eventPayload = parsedEvent.take();
|
|
2221
2574
|
if ((0, result_1.isErr)(eventPayload)) {
|
|
2222
2575
|
__classPrivateFieldGet(this, _Trellis_log, "f").error({ error: eventPayload.error }, "Event validation failed");
|
|
2576
|
+
recordRuntimeError(eventPayload.error, {
|
|
2577
|
+
surface: "event",
|
|
2578
|
+
direction: "consumer",
|
|
2579
|
+
operation: String(registration.event),
|
|
2580
|
+
phase: "input_validation",
|
|
2581
|
+
});
|
|
2223
2582
|
msg.term();
|
|
2224
2583
|
failed = true;
|
|
2225
2584
|
break;
|
|
@@ -2234,6 +2593,12 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2234
2593
|
});
|
|
2235
2594
|
const handlerValue = handlerResult.take();
|
|
2236
2595
|
if ((0, result_1.isErr)(handlerValue)) {
|
|
2596
|
+
recordRuntimeError(handlerValue.error, {
|
|
2597
|
+
surface: "event",
|
|
2598
|
+
direction: "consumer",
|
|
2599
|
+
operation: String(registration.event),
|
|
2600
|
+
phase: "handler_result",
|
|
2601
|
+
});
|
|
2237
2602
|
__classPrivateFieldGet(this, _Trellis_log, "f").error({
|
|
2238
2603
|
error: handlerValue.error.toSerializable(),
|
|
2239
2604
|
event: registration.event,
|
|
@@ -2309,8 +2674,8 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2309
2674
|
}));
|
|
2310
2675
|
}, _Trellis_requestJson = function _Trellis_requestJson(subject, body) {
|
|
2311
2676
|
return result_1.AsyncResult.from((async () => {
|
|
2312
|
-
const span = (0,
|
|
2313
|
-
return await (0,
|
|
2677
|
+
const span = (0, mod_js_2.startClientSpan)(subject, subject);
|
|
2678
|
+
return await (0, mod_js_2.withSpanAsync)(span, async () => {
|
|
2314
2679
|
try {
|
|
2315
2680
|
const payload = JSON.stringify(body);
|
|
2316
2681
|
const authHeaders = await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_createProof).call(this, subject, payload);
|
|
@@ -2319,7 +2684,7 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2319
2684
|
headers.set("proof", authHeaders.proof);
|
|
2320
2685
|
headers.set("iat", String(authHeaders.iat));
|
|
2321
2686
|
headers.set("request-id", authHeaders.requestId);
|
|
2322
|
-
(0,
|
|
2687
|
+
(0, mod_js_2.injectTraceContext)((0, mod_js_2.createNatsHeaderCarrier)(headers), span);
|
|
2323
2688
|
const response = (await __classPrivateFieldGet(this, _Trellis_instances, "m", _Trellis_requestMessageWithRetry).call(this, {
|
|
2324
2689
|
subject,
|
|
2325
2690
|
payload,
|
|
@@ -2328,9 +2693,15 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2328
2693
|
})).take();
|
|
2329
2694
|
if ((0, result_1.isErr)(response)) {
|
|
2330
2695
|
span.setStatus({
|
|
2331
|
-
code:
|
|
2696
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
2332
2697
|
message: response.error.message,
|
|
2333
2698
|
});
|
|
2699
|
+
recordRuntimeError(response.error, {
|
|
2700
|
+
surface: "operation",
|
|
2701
|
+
direction: "client",
|
|
2702
|
+
operation: "requestJson",
|
|
2703
|
+
phase: "request_send",
|
|
2704
|
+
});
|
|
2334
2705
|
return response;
|
|
2335
2706
|
}
|
|
2336
2707
|
const json = safeJson(response).take();
|
|
@@ -2343,21 +2714,33 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2343
2714
|
context: { subject },
|
|
2344
2715
|
});
|
|
2345
2716
|
span.setStatus({
|
|
2346
|
-
code:
|
|
2717
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
2347
2718
|
message: error.message,
|
|
2348
2719
|
});
|
|
2720
|
+
recordRuntimeError(error, {
|
|
2721
|
+
surface: "operation",
|
|
2722
|
+
direction: "client",
|
|
2723
|
+
operation: "requestJson",
|
|
2724
|
+
phase: "response_decoding",
|
|
2725
|
+
});
|
|
2349
2726
|
return (0, result_1.err)(error);
|
|
2350
2727
|
}
|
|
2351
|
-
span.setStatus({ code:
|
|
2728
|
+
span.setStatus({ code: mod_js_2.SpanStatusCode.OK });
|
|
2352
2729
|
return (0, result_1.ok)(json);
|
|
2353
2730
|
}
|
|
2354
2731
|
catch (cause) {
|
|
2355
2732
|
const error = new index_js_1.UnexpectedError({ cause });
|
|
2356
2733
|
span.setStatus({
|
|
2357
|
-
code:
|
|
2734
|
+
code: mod_js_2.SpanStatusCode.ERROR,
|
|
2358
2735
|
message: error.message,
|
|
2359
2736
|
});
|
|
2360
2737
|
span.recordException(error);
|
|
2738
|
+
recordRuntimeError(error, {
|
|
2739
|
+
surface: "operation",
|
|
2740
|
+
direction: "client",
|
|
2741
|
+
operation: "requestJson",
|
|
2742
|
+
phase: "unexpected",
|
|
2743
|
+
});
|
|
2361
2744
|
return (0, result_1.err)(error);
|
|
2362
2745
|
}
|
|
2363
2746
|
finally {
|
|
@@ -2385,35 +2768,56 @@ _Trellis_log = new WeakMap(), _Trellis_tasks = new WeakMap(), _Trellis_hasExplic
|
|
|
2385
2768
|
}
|
|
2386
2769
|
catch (cause) {
|
|
2387
2770
|
sub.unsubscribe();
|
|
2388
|
-
|
|
2771
|
+
const error = createTransportError({
|
|
2389
2772
|
code: "trellis.watch.failed",
|
|
2390
2773
|
message: "Trellis could not start the operation watch.",
|
|
2391
2774
|
hint: "Retry watching the operation. If it keeps failing, reconnect to Trellis and try again.",
|
|
2392
2775
|
cause,
|
|
2393
2776
|
context: { subject },
|
|
2394
|
-
})
|
|
2777
|
+
});
|
|
2778
|
+
recordRuntimeError(error, {
|
|
2779
|
+
surface: "operation",
|
|
2780
|
+
direction: "client",
|
|
2781
|
+
operation: "watchJson",
|
|
2782
|
+
phase: "request_send",
|
|
2783
|
+
});
|
|
2784
|
+
return (0, result_1.err)(error);
|
|
2395
2785
|
}
|
|
2396
2786
|
return (0, result_1.ok)((async function* () {
|
|
2397
2787
|
try {
|
|
2398
2788
|
for await (const msg of sub) {
|
|
2399
2789
|
if (msg.headers?.get("status") === "error") {
|
|
2400
|
-
|
|
2790
|
+
const error = createTransportError({
|
|
2401
2791
|
code: "trellis.watch.failed",
|
|
2402
2792
|
message: "Trellis stopped the operation watch.",
|
|
2403
2793
|
hint: "Retry watching the operation. If it keeps happening, reconnect to Trellis and try again.",
|
|
2404
2794
|
context: { subject, frame: msg.string() },
|
|
2405
|
-
})
|
|
2795
|
+
});
|
|
2796
|
+
recordRuntimeError(error, {
|
|
2797
|
+
surface: "operation",
|
|
2798
|
+
direction: "client",
|
|
2799
|
+
operation: "watchJson",
|
|
2800
|
+
phase: "remote_error",
|
|
2801
|
+
});
|
|
2802
|
+
yield (0, result_1.err)(error);
|
|
2406
2803
|
continue;
|
|
2407
2804
|
}
|
|
2408
2805
|
const json = safeJson(msg).take();
|
|
2409
2806
|
if ((0, result_1.isErr)(json)) {
|
|
2410
|
-
|
|
2807
|
+
const error = createTransportError({
|
|
2411
2808
|
code: "trellis.watch.invalid_response",
|
|
2412
2809
|
message: "Trellis returned an invalid watch update.",
|
|
2413
2810
|
hint: "Retry watching the operation. If it keeps happening, reconnect to Trellis and try again.",
|
|
2414
2811
|
cause: json.error.cause,
|
|
2415
2812
|
context: { subject },
|
|
2416
|
-
})
|
|
2813
|
+
});
|
|
2814
|
+
recordRuntimeError(error, {
|
|
2815
|
+
surface: "operation",
|
|
2816
|
+
direction: "client",
|
|
2817
|
+
operation: "watchJson",
|
|
2818
|
+
phase: "response_decoding",
|
|
2819
|
+
});
|
|
2820
|
+
yield (0, result_1.err)(error);
|
|
2417
2821
|
continue;
|
|
2418
2822
|
}
|
|
2419
2823
|
yield (0, result_1.ok)(json);
|