service-bridge 1.8.1-dev.36 → 1.8.2-dev.39
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/README.md +20 -34
- package/dist/index.js +28 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ const sb = servicebridge(
|
|
|
99
99
|
process.env.SERVICEBRIDGE_SERVICE_KEY!,
|
|
100
100
|
);
|
|
101
101
|
|
|
102
|
-
sb.handleRpc("charge", async (payload: { orderId: string; amount: number }) => {
|
|
102
|
+
sb.handleRpc("payment.charge", async (payload: { orderId: string; amount: number }) => {
|
|
103
103
|
return { ok: true, txId: `tx_${Date.now()}`, orderId: payload.orderId };
|
|
104
104
|
});
|
|
105
105
|
|
|
@@ -116,7 +116,7 @@ const sb = servicebridge(
|
|
|
116
116
|
process.env.SERVICEBRIDGE_SERVICE_KEY!,
|
|
117
117
|
);
|
|
118
118
|
|
|
119
|
-
const result = await sb.rpc<{ ok: boolean; txId: string }>("payments
|
|
119
|
+
const result = await sb.rpc<{ ok: boolean; txId: string }>("payments", "payment.charge", {
|
|
120
120
|
orderId: "ord_42",
|
|
121
121
|
amount: 4990,
|
|
122
122
|
});
|
|
@@ -153,7 +153,7 @@ import { servicebridge } from "service-bridge";
|
|
|
153
153
|
|
|
154
154
|
const payments = servicebridge("localhost:14445", process.env.SERVICEBRIDGE_SERVICE_KEY!);
|
|
155
155
|
|
|
156
|
-
payments.handleRpc("charge", async (payload: { orderId: string; amount: number }, ctx) => {
|
|
156
|
+
payments.handleRpc("payment.charge", async (payload: { orderId: string; amount: number }, ctx) => {
|
|
157
157
|
await ctx?.stream.write({ status: "charging", orderId: payload.orderId }, "progress");
|
|
158
158
|
|
|
159
159
|
// ... charge logic ...
|
|
@@ -171,7 +171,7 @@ await payments.serve({ host: "localhost" });
|
|
|
171
171
|
const orders = servicebridge("localhost:14445", process.env.SERVICEBRIDGE_SERVICE_KEY!);
|
|
172
172
|
|
|
173
173
|
// Call payments, then publish event
|
|
174
|
-
const charge = await orders.rpc<{ ok: boolean; txId: string }>("payments
|
|
174
|
+
const charge = await orders.rpc<{ ok: boolean; txId: string }>("payments", "payment.charge", {
|
|
175
175
|
orderId: "ord_42",
|
|
176
176
|
amount: 4990,
|
|
177
177
|
});
|
|
@@ -203,8 +203,8 @@ await notifications.serve({ host: "localhost" });
|
|
|
203
203
|
// --- Orchestrate as a workflow ---
|
|
204
204
|
|
|
205
205
|
await orders.workflow("order.fulfillment", [
|
|
206
|
-
{ id: "reserve", type: "rpc", ref: "inventory/reserve" },
|
|
207
|
-
{ id: "charge", type: "rpc", ref: "payments/charge", deps: ["reserve"] },
|
|
206
|
+
{ id: "reserve", type: "rpc", ref: "inventory/inventory.reserve" },
|
|
207
|
+
{ id: "charge", type: "rpc", ref: "payments/payment.charge", deps: ["reserve"] },
|
|
208
208
|
{ id: "wait_dlv", type: "event_wait", ref: "shipping.delivered", deps: ["charge"] },
|
|
209
209
|
{ id: "notify", type: "event", ref: "orders.fulfilled", deps: ["wait_dlv"] },
|
|
210
210
|
]);
|
|
@@ -277,13 +277,12 @@ across all three SDKs. Parity differences are naming-only (language idioms):
|
|
|
277
277
|
function servicebridge(
|
|
278
278
|
url: string,
|
|
279
279
|
serviceKey: string,
|
|
280
|
-
|
|
281
|
-
maybeGlobalOpts?: ServiceBridgeOpts,
|
|
280
|
+
opts?: ServiceBridgeOpts,
|
|
282
281
|
): ServiceBridgeService
|
|
283
282
|
```
|
|
284
283
|
|
|
285
284
|
Creates an SDK client instance.
|
|
286
|
-
Service identity is resolved by the runtime from `serviceKey
|
|
285
|
+
Service identity is resolved by the runtime from `serviceKey`.
|
|
287
286
|
|
|
288
287
|
`ServiceBridgeOpts`:
|
|
289
288
|
|
|
@@ -318,22 +317,15 @@ type WorkerTLSOpts = {
|
|
|
318
317
|
|
|
319
318
|
---
|
|
320
319
|
|
|
321
|
-
### `rpc(fn, payload?, opts?)`
|
|
320
|
+
### `rpc(service, fn, payload?, opts?)`
|
|
322
321
|
|
|
323
322
|
```ts
|
|
324
|
-
rpc<T = unknown>(fn: string, payload?: unknown, opts?: RpcOpts): Promise<T>
|
|
323
|
+
rpc<T = unknown>(service: string, fn: string, payload?: unknown, opts?: RpcOpts): Promise<T>
|
|
325
324
|
```
|
|
326
325
|
|
|
327
326
|
Calls a registered RPC handler on another service. Direct gRPC path, no proxy.
|
|
328
327
|
|
|
329
|
-
**
|
|
330
|
-
|
|
331
|
-
| Format | Example | When to use |
|
|
332
|
-
|---|---|---|
|
|
333
|
-
| Plain name | `"charge"` | Function name is globally unique across all services. Resolved automatically via service discovery. |
|
|
334
|
-
| Canonical name | `"payments/charge"` | Multiple services expose a function with the same plain name, or you want to be explicit about the target service. |
|
|
335
|
-
|
|
336
|
-
Both formats are interchangeable when the name is unique globally. Canonical format is recommended in production for clarity and to avoid ambiguity as your service count grows.
|
|
328
|
+
**Arguments** — `service` is the callee’s logical name; `fn` is the name used in `handleRpc` (e.g. `payment.charge`). Use **dot notation** in `fn` to group methods. Do not put `/` in `fn`.
|
|
337
329
|
|
|
338
330
|
`RpcOpts`:
|
|
339
331
|
|
|
@@ -347,11 +339,7 @@ Both formats are interchangeable when the name is unique globally. Canonical for
|
|
|
347
339
|
| `mode` | `"direct" \| "proxy"` | Transport mode. `"direct"` (default) connects directly to the worker. `"proxy"` routes through the control plane when direct connection is unavailable. |
|
|
348
340
|
|
|
349
341
|
```ts
|
|
350
|
-
|
|
351
|
-
const user = await sb.rpc<{ id: string; name: string }>("get", { id: "u_1" });
|
|
352
|
-
|
|
353
|
-
// canonical name — explicit service target, always unambiguous
|
|
354
|
-
const user = await sb.rpc<{ id: string; name: string }>("users/get", { id: "u_1" }, {
|
|
342
|
+
const user = await sb.rpc<{ id: string; name: string }>("users", "user.get", { id: "u_1" }, {
|
|
355
343
|
timeout: 5000,
|
|
356
344
|
retries: 2,
|
|
357
345
|
});
|
|
@@ -421,7 +409,7 @@ Registers a scheduled or delayed job.
|
|
|
421
409
|
| `retryPolicyJson` | `string` | Retry policy JSON string. |
|
|
422
410
|
|
|
423
411
|
```ts
|
|
424
|
-
await sb.job("billing/collect", {
|
|
412
|
+
await sb.job("billing/billing.collect", {
|
|
425
413
|
cron: "0 * * * *",
|
|
426
414
|
timezone: "UTC",
|
|
427
415
|
via: "rpc",
|
|
@@ -466,8 +454,8 @@ interface WorkflowOpts {
|
|
|
466
454
|
|
|
467
455
|
```ts
|
|
468
456
|
await sb.workflow("order.fulfillment", [
|
|
469
|
-
{ id: "reserve", type: "rpc", ref: "inventory/reserve" },
|
|
470
|
-
{ id: "charge", type: "rpc", ref: "payments/charge", deps: ["reserve"] },
|
|
457
|
+
{ id: "reserve", type: "rpc", ref: "inventory/inventory.reserve" },
|
|
458
|
+
{ id: "charge", type: "rpc", ref: "payments/payment.charge", deps: ["reserve"] },
|
|
471
459
|
{ id: "wait_5m", type: "sleep", durationMs: 300_000, deps: ["charge"] },
|
|
472
460
|
{ id: "notify", type: "event", ref: "orders.fulfilled", deps: ["wait_5m"] },
|
|
473
461
|
]);
|
|
@@ -554,7 +542,7 @@ Registers an RPC handler. Chainable.
|
|
|
554
542
|
| `allowedCallers` | `string[]` | Allow-list of caller service names. |
|
|
555
543
|
|
|
556
544
|
```ts
|
|
557
|
-
sb.handleRpc("ai
|
|
545
|
+
sb.handleRpc("ai.generate", async (payload: { prompt: string }, ctx) => {
|
|
558
546
|
await ctx?.stream.write({ token: "Hello" }, "output");
|
|
559
547
|
await ctx?.stream.write({ token: " world" }, "output");
|
|
560
548
|
return { text: "Hello world" };
|
|
@@ -586,13 +574,12 @@ Registers an event consumer handler. Chainable.
|
|
|
586
574
|
|
|
587
575
|
| Option | Type | Description |
|
|
588
576
|
|---|---|---|
|
|
589
|
-
| `groupName` | `string` | Consumer group name. Default: `<service-key-id>.<pattern>`. |
|
|
590
577
|
| `concurrency` | `number` | Advisory concurrency hint (currently not hard-enforced). |
|
|
591
578
|
| `prefetch` | `number` | Advisory prefetch hint (currently not hard-enforced). |
|
|
592
579
|
| `retryPolicyJson` | `string` | Retry policy JSON string. |
|
|
593
580
|
| `filterExpr` | `string` | Server-side filter expression. |
|
|
594
581
|
|
|
595
|
-
Duplicate
|
|
582
|
+
Duplicate pattern registration within the same service throws an error.
|
|
596
583
|
|
|
597
584
|
**Delivery guarantee**: once a message is accepted by the runtime, delivery to each consumer group
|
|
598
585
|
is guaranteed. If the consumer is offline, the message waits in the server-side queue and is
|
|
@@ -830,7 +817,7 @@ app.use(servicebridgeMiddleware({
|
|
|
830
817
|
}));
|
|
831
818
|
|
|
832
819
|
app.get("/users/:id", async (req, res) => {
|
|
833
|
-
const user = await req.servicebridge.rpc("users
|
|
820
|
+
const user = await req.servicebridge.rpc("users", "user.get", { id: req.params.id });
|
|
834
821
|
res.json(user);
|
|
835
822
|
});
|
|
836
823
|
```
|
|
@@ -886,7 +873,7 @@ await app.register(servicebridgePlugin, {
|
|
|
886
873
|
});
|
|
887
874
|
|
|
888
875
|
app.get("/users/:id", wrapHandler(async (request, reply) => {
|
|
889
|
-
const user = await request.servicebridge.rpc("users
|
|
876
|
+
const user = await request.servicebridge.rpc("users", "user.get", {
|
|
890
877
|
id: (request.params as any).id,
|
|
891
878
|
});
|
|
892
879
|
return reply.send(user);
|
|
@@ -983,7 +970,7 @@ const sb = servicebridge(
|
|
|
983
970
|
import { servicebridge, ServiceBridgeError } from "service-bridge";
|
|
984
971
|
|
|
985
972
|
try {
|
|
986
|
-
await sb.rpc("payments
|
|
973
|
+
await sb.rpc("payments", "payment.charge", { orderId: "ord_1" });
|
|
987
974
|
} catch (e) {
|
|
988
975
|
if (e instanceof ServiceBridgeError) {
|
|
989
976
|
console.error(e.component, e.operation, e.severity, e.retryable, e.code);
|
|
@@ -1055,7 +1042,6 @@ import { V2SessionClient, validateV2Config } from 'service-bridge';
|
|
|
1055
1042
|
|
|
1056
1043
|
const cfg = {
|
|
1057
1044
|
serverAddress: 'localhost:9090',
|
|
1058
|
-
serviceName: 'my-worker',
|
|
1059
1045
|
instanceId: 'worker-1',
|
|
1060
1046
|
zone: 'us-east-1a',
|
|
1061
1047
|
transportMode: 'direct' as const,
|
package/dist/index.js
CHANGED
|
@@ -177,7 +177,6 @@ class V2SessionClient {
|
|
|
177
177
|
constructor(config) {
|
|
178
178
|
this.config = {
|
|
179
179
|
serverAddress: config.serverAddress,
|
|
180
|
-
serviceName: config.serviceName,
|
|
181
180
|
instanceId: config.instanceId,
|
|
182
181
|
zone: config.zone ?? "",
|
|
183
182
|
transportMode: config.transportMode ?? "direct",
|
|
@@ -209,7 +208,6 @@ class V2SessionClient {
|
|
|
209
208
|
const rs = this.position.getResumeState(this.resumeToken, this.epoch);
|
|
210
209
|
return {
|
|
211
210
|
identity: {
|
|
212
|
-
serviceName: this.config.serviceName,
|
|
213
211
|
instanceId: this.config.instanceId,
|
|
214
212
|
transport: this.config.transportMode
|
|
215
213
|
},
|
|
@@ -309,8 +307,6 @@ class V2SessionClient {
|
|
|
309
307
|
function validateV2Config(cfg) {
|
|
310
308
|
if (!cfg.serverAddress)
|
|
311
309
|
throw new Error("servicebridge: serverAddress is required");
|
|
312
|
-
if (!cfg.serviceName)
|
|
313
|
-
throw new Error("servicebridge: serviceName is required");
|
|
314
310
|
if (!cfg.instanceId)
|
|
315
311
|
throw new Error("servicebridge: instanceId is required");
|
|
316
312
|
if (cfg.transportMode && cfg.transportMode !== "direct" && cfg.transportMode !== "proxy") {
|
|
@@ -632,7 +628,7 @@ function reportSDKError(operation, err, component = "sdk") {
|
|
|
632
628
|
}
|
|
633
629
|
return normalized;
|
|
634
630
|
}
|
|
635
|
-
function
|
|
631
|
+
function parseRegistryCanonicalName(target) {
|
|
636
632
|
const canonicalName = target.trim();
|
|
637
633
|
if (!canonicalName)
|
|
638
634
|
return null;
|
|
@@ -863,7 +859,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
863
859
|
const service = typeof serviceOrOpts === "string" ? serviceOrOpts.trim() : "";
|
|
864
860
|
const globalOpts = typeof serviceOrOpts === "string" ? maybeGlobalOpts : serviceOrOpts ?? {};
|
|
865
861
|
const parsedServiceKey = parseServiceKeyV2(serviceKey);
|
|
866
|
-
const defaultConsumerPrefix =
|
|
862
|
+
const defaultConsumerPrefix = parsedServiceKey.keyId || "consumer";
|
|
867
863
|
const meta = new grpc.Metadata;
|
|
868
864
|
meta.add("x-service-key", serviceKey);
|
|
869
865
|
const rawUrl = url.trim();
|
|
@@ -1065,7 +1061,6 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
1065
1061
|
function pushLog(level, msg, attrs) {
|
|
1066
1062
|
const tc = traceStorage.getStore();
|
|
1067
1063
|
const entry = {
|
|
1068
|
-
service_name: service,
|
|
1069
1064
|
level,
|
|
1070
1065
|
message: msg,
|
|
1071
1066
|
timestamp_ns: String(Date.now() * 1e6),
|
|
@@ -1147,7 +1142,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
1147
1142
|
const endpoints = parseEndpointsFromWire(res.endpoints);
|
|
1148
1143
|
const isNewFunction = !functionMeta.has(canonicalName);
|
|
1149
1144
|
if (isNewFunction) {
|
|
1150
|
-
const parsed =
|
|
1145
|
+
const parsed = parseRegistryCanonicalName(canonicalName);
|
|
1151
1146
|
if (parsed) {
|
|
1152
1147
|
functionMeta.set(canonicalName, {
|
|
1153
1148
|
canonicalName,
|
|
@@ -1401,7 +1396,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
1401
1396
|
headers: toWireStringMap(op.opts?.headers),
|
|
1402
1397
|
trace_id: op.opts?.traceId ?? "",
|
|
1403
1398
|
parent_span_id: op.opts?.parentSpanId ?? "",
|
|
1404
|
-
producer_service:
|
|
1399
|
+
producer_service: defaultConsumerPrefix,
|
|
1405
1400
|
idempotency_key: op.opts?.idempotencyKey ?? ""
|
|
1406
1401
|
}, meta, unaryDeadlineOptions(), (err) => err ? rej(err) : res());
|
|
1407
1402
|
});
|
|
@@ -1533,7 +1528,6 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
1533
1528
|
await new Promise((resolve, reject) => {
|
|
1534
1529
|
stub.Reconcile({
|
|
1535
1530
|
identity: {
|
|
1536
|
-
service_name: service,
|
|
1537
1531
|
instance_id: state.instanceId,
|
|
1538
1532
|
endpoint: state.endpoint,
|
|
1539
1533
|
transport: state.transport
|
|
@@ -1991,7 +1985,6 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
1991
1985
|
if (!v2Session) {
|
|
1992
1986
|
v2Session = new V2SessionClient({
|
|
1993
1987
|
serverAddress: target,
|
|
1994
|
-
serviceName: service,
|
|
1995
1988
|
instanceId: serveState.instanceId,
|
|
1996
1989
|
transportMode: "direct",
|
|
1997
1990
|
maxInflight: serveState.maxInFlight,
|
|
@@ -2004,7 +1997,6 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2004
1997
|
stream.write({
|
|
2005
1998
|
hello: {
|
|
2006
1999
|
identity: {
|
|
2007
|
-
service_name: hf.identity.serviceName,
|
|
2008
2000
|
instance_id: hf.identity.instanceId,
|
|
2009
2001
|
endpoint: serveState.endpoint,
|
|
2010
2002
|
transport: serveState.transport
|
|
@@ -2120,35 +2112,40 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2120
2112
|
}
|
|
2121
2113
|
}
|
|
2122
2114
|
const svc = {
|
|
2123
|
-
async rpc(fn, payload, opts) {
|
|
2115
|
+
async rpc(targetService, fn, payload, opts) {
|
|
2124
2116
|
try {
|
|
2125
2117
|
await _controlReady;
|
|
2126
2118
|
} catch (err) {
|
|
2127
2119
|
throw normalizeServiceError(err, "control-plane");
|
|
2128
2120
|
}
|
|
2121
|
+
const svcName = targetService.trim();
|
|
2122
|
+
const fname = fn.trim();
|
|
2123
|
+
if (!svcName || !fname) {
|
|
2124
|
+
throw new Error("rpc: service and fn are required");
|
|
2125
|
+
}
|
|
2126
|
+
const lookupKey = `${svcName}/${fname}`;
|
|
2129
2127
|
const tc = traceStorage.getStore();
|
|
2130
2128
|
const traceId = opts?.traceId ?? tc?.traceId ?? crypto.randomUUID();
|
|
2131
2129
|
const maxRetries = normalizeNonNegativeInt(opts?.retries ?? globalOpts.retries ?? 3, 3);
|
|
2132
2130
|
const baseDelay = normalizePositiveInt(opts?.retryDelay ?? globalOpts.retryDelay ?? 300, 300);
|
|
2133
2131
|
const timeout = normalizePositiveInt(opts?.timeout ?? globalOpts.timeout ?? 30000, 30000);
|
|
2134
|
-
let canonical = resolveCanonical(
|
|
2132
|
+
let canonical = resolveCanonical(lookupKey);
|
|
2135
2133
|
if (!canonical) {
|
|
2136
|
-
await doLookupFunction(
|
|
2137
|
-
canonical = resolveCanonical(
|
|
2134
|
+
await doLookupFunction(lookupKey);
|
|
2135
|
+
canonical = resolveCanonical(lookupKey);
|
|
2138
2136
|
}
|
|
2139
2137
|
if (!canonical)
|
|
2140
|
-
throw normalizeServiceError(new Error(`No endpoints available for RPC: ${
|
|
2138
|
+
throw normalizeServiceError(new Error(`No endpoints available for RPC: ${lookupKey}`), lookupKey, "worker");
|
|
2141
2139
|
const fmeta = functionMeta.get(canonical);
|
|
2142
2140
|
if (fmeta && !containsOrAll(fmeta.allowedCallers, service)) {
|
|
2143
|
-
throw new Error(`Service "${service}" is not allowed to call "${
|
|
2141
|
+
throw new Error(`Service "${service}" is not allowed to call "${lookupKey}". ` + `Permitted callers: ${fmeta.allowedCallers.join(", ")}`);
|
|
2144
2142
|
}
|
|
2145
2143
|
const inputSchema = fmeta?.inputSchema;
|
|
2146
2144
|
const outputSchema = fmeta?.outputSchema;
|
|
2147
2145
|
const inputBuf = inputSchema ? encodeWithSchema(inputSchema, payload) : toJsonBuffer(payload);
|
|
2148
2146
|
const telemetryInputBuf = toJsonBuffer(payload);
|
|
2149
|
-
const
|
|
2150
|
-
const
|
|
2151
|
-
const rpcServiceName = _parsedCanonical?.serviceName ?? "";
|
|
2147
|
+
const rpcFnName = fname;
|
|
2148
|
+
const rpcServiceName = svcName;
|
|
2152
2149
|
const rootSpanId = crypto.randomUUID();
|
|
2153
2150
|
const parentSpanId = opts?.parentSpanId ?? tc?.spanId ?? "";
|
|
2154
2151
|
const rootStartedAt = Date.now();
|
|
@@ -2166,12 +2163,12 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2166
2163
|
}, meta, { deadline: new Date(Date.now() + timeout) }, (err, res) => {
|
|
2167
2164
|
if (err) {
|
|
2168
2165
|
reportCallAsync(traceId, rootSpanId, rpcFnName, rootStartedAt, telemetryInputBuf, false, 1, undefined, String(err), "rpc", parentSpanId, rpcServiceName);
|
|
2169
|
-
return reject(normalizeServiceError(err,
|
|
2166
|
+
return reject(normalizeServiceError(err, lookupKey, "control-plane"));
|
|
2170
2167
|
}
|
|
2171
2168
|
if (!res?.success) {
|
|
2172
2169
|
const errMsg = res?.error ?? "proxy call failed";
|
|
2173
2170
|
reportCallAsync(traceId, rootSpanId, rpcFnName, rootStartedAt, telemetryInputBuf, false, 1, undefined, errMsg, "rpc", parentSpanId, rpcServiceName);
|
|
2174
|
-
return reject(normalizeServiceError(new Error(errMsg),
|
|
2171
|
+
return reject(normalizeServiceError(new Error(errMsg), lookupKey, "worker"));
|
|
2175
2172
|
}
|
|
2176
2173
|
reportCallAsync(traceId, rootSpanId, rpcFnName, rootStartedAt, telemetryInputBuf, true, 1, res.output, "", "rpc", parentSpanId, rpcServiceName);
|
|
2177
2174
|
try {
|
|
@@ -2197,8 +2194,8 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2197
2194
|
try {
|
|
2198
2195
|
const attemptTimeoutMs = timeout;
|
|
2199
2196
|
const deadline = new Date(Date.now() + attemptTimeoutMs);
|
|
2200
|
-
const
|
|
2201
|
-
if (!
|
|
2197
|
+
const workerFnName = fmeta?.fnName ?? fname;
|
|
2198
|
+
if (!workerFnName)
|
|
2202
2199
|
throw new Error("unreachable");
|
|
2203
2200
|
const res = await new Promise((resolve, reject) => {
|
|
2204
2201
|
let settled = false;
|
|
@@ -2225,7 +2222,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2225
2222
|
};
|
|
2226
2223
|
try {
|
|
2227
2224
|
unaryCall = workerClient.Handle({
|
|
2228
|
-
function_name:
|
|
2225
|
+
function_name: workerFnName,
|
|
2229
2226
|
payload: inputBuf,
|
|
2230
2227
|
trace_id: traceId,
|
|
2231
2228
|
span_id: attemptSpanId,
|
|
@@ -2263,7 +2260,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2263
2260
|
}
|
|
2264
2261
|
}
|
|
2265
2262
|
}
|
|
2266
|
-
throw normalizeServiceError(lastError,
|
|
2263
|
+
throw normalizeServiceError(lastError, lookupKey, "worker");
|
|
2267
2264
|
});
|
|
2268
2265
|
},
|
|
2269
2266
|
event(topic, payload, opts) {
|
|
@@ -2279,7 +2276,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2279
2276
|
headers: toWireStringMap(opts?.headers),
|
|
2280
2277
|
trace_id: opts?.traceId ?? tc?.traceId ?? "",
|
|
2281
2278
|
parent_span_id: opts?.parentSpanId ?? tc?.spanId ?? "",
|
|
2282
|
-
producer_service:
|
|
2279
|
+
producer_service: defaultConsumerPrefix,
|
|
2283
2280
|
idempotency_key: opts?.idempotencyKey ?? ""
|
|
2284
2281
|
}, meta, unaryDeadlineOptions(), (err, res) => err ? reject(normalizeServiceError(err, `publish:${topic}`)) : resolve(res?.message_id ?? ""));
|
|
2285
2282
|
});
|
|
@@ -2320,9 +2317,9 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2320
2317
|
},
|
|
2321
2318
|
handleEvent(pattern, handler, opts) {
|
|
2322
2319
|
const normalizedOpts = opts ?? {};
|
|
2323
|
-
const groupName =
|
|
2320
|
+
const groupName = `${defaultConsumerPrefix}.${pattern}`;
|
|
2324
2321
|
if (eventHandlers.has(groupName)) {
|
|
2325
|
-
throw new Error(`Duplicate event consumer group "${groupName}". ` + "Use a
|
|
2322
|
+
throw new Error(`Duplicate event consumer group "${groupName}". ` + "Use handleEvent() with a unique topic pattern per handler.");
|
|
2326
2323
|
}
|
|
2327
2324
|
eventHandlers.set(groupName, {
|
|
2328
2325
|
groupName,
|
|
@@ -2474,8 +2471,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
|
|
|
2474
2471
|
return new Promise((resolve, reject) => {
|
|
2475
2472
|
stub.ExecuteWorkflow({
|
|
2476
2473
|
workflow_name: name,
|
|
2477
|
-
input: payload
|
|
2478
|
-
service_name: service
|
|
2474
|
+
input: payload
|
|
2479
2475
|
}, meta, unaryDeadlineOptions(), (err, res) => {
|
|
2480
2476
|
if (err) {
|
|
2481
2477
|
reject(normalizeServiceError(err, "execute-workflow"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "service-bridge",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2-dev.39",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ServiceBridge SDK for Node.js — one self-hosted runtime for RPC, events, workflows, and jobs without a service mesh or sidecars. Direct gRPC between workers; durable events, jobs, tracing, auto mTLS. One Go runtime + PostgreSQL.",
|
|
6
6
|
"keywords": [
|