Skip to content

Commit e929b06

Browse files
authored
[FEAT] surface JS errors as per ADR-7 (#227)
* [FEAT] surface JS errors as per ADR-7 The modification enhances NatsError by adding: `isJetStreamError(): boolean` `jsError(): ApiError|null` This enables clients to test if there's more info to the underlying error FIX #226
1 parent dee6071 commit e929b06

File tree

6 files changed

+46
-4
lines changed

6 files changed

+46
-4
lines changed

nats-base-client/error.ts

+12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* limitations under the License.
1414
*/
1515

16+
import { ApiError } from "./types.ts";
17+
1618
export enum ErrorCode {
1719
// emitted by the client
1820
ApiError = "BAD API",
@@ -93,6 +95,8 @@ export class NatsError extends Error {
9395
message: string;
9496
code: string;
9597
chainedError?: Error;
98+
// these are for supporting jetstream
99+
api_error?: ApiError;
96100

97101
/**
98102
* @param {String} message
@@ -127,4 +131,12 @@ export class NatsError extends Error {
127131
isProtocolError(): boolean {
128132
return this.code === ErrorCode.ProtocolError;
129133
}
134+
135+
isJetStreamError(): boolean {
136+
return this.api_error !== undefined;
137+
}
138+
139+
jsError(): ApiError | null {
140+
return this.api_error ? this.api_error : null;
141+
}
130142
}

nats-base-client/jsbaseclient_api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export class BaseApiClient {
105105
if (r.error) {
106106
const err = checkJsErrorCode(r.error.code, r.error.description);
107107
if (err !== null) {
108+
err.api_error = r.error;
108109
throw err;
109110
}
110111
}

nats-base-client/nats.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ export class NatsConnectionImpl implements NatsConnection {
289289
try {
290290
await adm.getAccountInfo();
291291
} catch (err) {
292-
const ne = err as NatsError;
292+
let ne = err as NatsError;
293293
if (ne.code === ErrorCode.NoResponders) {
294-
throw NatsError.errorForCode(ErrorCode.JetStreamNotEnabled);
294+
ne.code = ErrorCode.JetStreamNotEnabled;
295295
}
296296
throw ne;
297297
}

nats-base-client/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ export type Nanos = number;
504504
export interface ApiError {
505505
code: number;
506506
description: string;
507+
err_code?: number;
507508
}
508509

509510
export interface ApiResponse {

tests/jetstream_test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2211,7 +2211,8 @@ Deno.test("jetstream - redelivery property works", async () => {
22112211

22122212
assert(sub.getProcessed() > 0);
22132213
assert(sub2.getProcessed() > 0);
2214-
assertEquals(sub.getProcessed() + sub2.getProcessed(), 100 + r);
2214+
assert(r > 0);
2215+
assert(sub.getProcessed() + sub2.getProcessed() > 100);
22152216

22162217
const jsm = await nc.jetstreamManager();
22172218
const ci = await jsm.consumers.info(stream, "n");

tests/jsm_test.ts

+28-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
ErrorCode,
2828
headers,
2929
JSONCodec,
30+
NatsError,
3031
nuid,
3132
StreamConfig,
3233
StreamInfo,
@@ -40,7 +41,7 @@ import {
4041
setup,
4142
} from "./jstest_util.ts";
4243
import { connect } from "../src/mod.ts";
43-
import { assertThrowsAsyncErrorCode } from "./helpers/mod.ts";
44+
import { assertThrowsAsyncErrorCode, NatsServer } from "./helpers/mod.ts";
4445
import { validateName } from "../nats-base-client/jsutil.ts";
4546

4647
const StreamNameRequired = "stream name required";
@@ -885,3 +886,29 @@ Deno.test("jsm - cross account consumers", async () => {
885886

886887
await cleanup(ns, nc, admin);
887888
});
889+
890+
Deno.test("jsm - jetstream error info", async () => {
891+
const { ns, nc } = await setup(jetstreamServerConf({}, true));
892+
let jsm = await nc.jetstreamManager();
893+
try {
894+
await jsm.streams.add({
895+
name: "a",
896+
num_replicas: 3,
897+
subjects: ["a.>"],
898+
});
899+
fail("should have failed");
900+
} catch (err) {
901+
const ne = err as NatsError;
902+
assert(ne.isJetStreamError());
903+
const jerr = ne.jsError();
904+
console.log(jerr);
905+
assert(jerr);
906+
assertEquals(jerr.code, 500);
907+
assertEquals(jerr.err_code, 10074);
908+
assertEquals(
909+
jerr.description,
910+
"replicas > 1 not supported in non-clustered mode",
911+
);
912+
}
913+
await cleanup(ns, nc);
914+
});

0 commit comments

Comments
 (0)