Skip to content

Commit

Permalink
wip errors
Browse files Browse the repository at this point in the history
Signed-off-by: Alberto Ricart <[email protected]>
  • Loading branch information
aricart committed Oct 31, 2024
1 parent c12d5cd commit a4cdc52
Show file tree
Hide file tree
Showing 51 changed files with 428 additions and 364 deletions.
2 changes: 1 addition & 1 deletion core/deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nats-io/nats-core",
"version": "3.0.0-32",
"version": "3.0.0-34",
"exports": {
".": "./src/mod.ts",
"./internal": "./src/internal_mod.ts"
Expand Down
2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nats-io/nats-core",
"version": "3.0.0-32",
"version": "3.0.0-34",
"files": [
"lib/",
"LICENSE",
Expand Down
10 changes: 4 additions & 6 deletions core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/

import { nuid } from "./nuid.ts";
import { errors, InvalidArgumentError } from "./errors.ts";
import { InvalidArgumentError } from "./errors.ts";

/**
* Events reported by the {@link NatsConnection#status} iterator.
Expand Down Expand Up @@ -663,11 +663,9 @@ export function createInbox(prefix = ""): string {
prefix.split(".")
.forEach((v) => {
if (v === "*" || v === ">") {
throw new errors.InvalidArgumentError(
InvalidArgumentError.format(
"prefix",
`cannot have wildcards ('${prefix}')`,
),
throw InvalidArgumentError.format(
"prefix",
`cannot have wildcards ('${prefix}')`,
);
}
});
Expand Down
26 changes: 19 additions & 7 deletions core/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,21 @@ export class InvalidArgumentError extends Error {
this.name = "InvalidArgumentError";
}

static format(name: string, message: string): string {
return `'${name}' ${message}`;
}

static formatMultiple(names: string[], message: string): string {
names = names.map((n) => `'${n}'`);
return `${names.join(",")} ${message}`;
static format(
property: string | string[],
message: string,
options?: ErrorOptions,
): InvalidArgumentError {
if (Array.isArray(message) && message.length > 1) {
message = message[0];
}
if (Array.isArray(property)) {
property = property.map((n) => `'${n}'`);
property = property.join(",");
} else {
property = `'${property}'`;
}
return new InvalidArgumentError(`${property} ${message}`, options);
}
}

Expand Down Expand Up @@ -186,6 +194,10 @@ export class RequestError extends Error {
super(message, options);
this.name = "RequestError";
}

isNoResponders(): boolean {
return this.cause instanceof NoRespondersError;
}
}

/**
Expand Down
25 changes: 8 additions & 17 deletions core/src/headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import { TD, TE } from "./encoders.ts";
import type { MsgHdrs } from "./core.ts";
import { Match } from "./core.ts";
import { errors } from "./errors.ts";
import { InvalidArgumentError } from "./errors.ts";

// https://www.ietf.org/rfc/rfc822.txt
// 3.1.2. STRUCTURE OF HEADER FIELDS
Expand Down Expand Up @@ -48,11 +48,9 @@ export function canonicalMIMEHeaderKey(k: string): string {
for (let i = 0; i < k.length; i++) {
let c = k.charCodeAt(i);
if (c === colon || c < start || c > end) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(
"header",
`'${k[i]}' is not a valid character in a header name`,
),
throw InvalidArgumentError.format(
"header",
`'${k[i]}' is not a valid character in a header name`,
);
}
if (upper && a <= c && c <= z) {
Expand All @@ -68,12 +66,7 @@ export function canonicalMIMEHeaderKey(k: string): string {

export function headers(code = 0, description = ""): MsgHdrs {
if ((code === 0 && description !== "") || (code > 0 && description === "")) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(
"description",
"is required",
),
);
throw InvalidArgumentError.format("description", "is required");
}
return new MsgHdrsImpl(code, description);
}
Expand Down Expand Up @@ -178,11 +171,9 @@ export class MsgHdrsImpl implements MsgHdrs {
static validHeaderValue(k: string): string {
const inv = /[\r\n]/;
if (inv.test(k)) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(
"header",
"values cannot contain \\r or \\n",
),
throw InvalidArgumentError.format(
"header",
"values cannot contain \\r or \\n",
);
}
return k.trim();
Expand Down
17 changes: 16 additions & 1 deletion core/src/internal_mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,19 @@ export { SHA256 } from "./sha256.ts";

export { wsconnect, wsUrlParseFn } from "./ws_transport.ts";

export { errors } from "./errors.ts";
export {
AuthorizationError,
ClosedConnectionError,
ConnectionError,
DrainingConnectionError,
errors,
InvalidArgumentError,
InvalidOperationError,
InvalidSubjectError,
NoRespondersError,
PermissionViolationError,
ProtocolError,
RequestError,
TimeoutError,
UserAuthenticationExpiredError,
} from "./errors.ts";
13 changes: 13 additions & 0 deletions core/src/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,27 @@
*/

export {
AuthorizationError,
backoff,
Bench,
buildAuthenticator,
canonicalMIMEHeaderKey,
ClosedConnectionError,
ConnectionError,
createInbox,
credsAuthenticator,
deadline,
DebugEvents,
deferred,
delay,
DrainingConnectionError,
Empty,
errors,
Events,
headers,
InvalidArgumentError,
InvalidOperationError,
InvalidSubjectError,
jwtAuthenticator,
Match,
Metric,
Expand All @@ -36,11 +43,17 @@ export {
nanos,
nkeyAuthenticator,
nkeys,
NoRespondersError,
Nuid,
nuid,
PermissionViolationError,
ProtocolError,
RequestError,
RequestStrategy,
syncIterator,
TimeoutError,
tokenAuthenticator,
UserAuthenticationExpiredError,
usernamePasswordAuthenticator,
wsconnect,
} from "./internal_mod.ts";
Expand Down
48 changes: 22 additions & 26 deletions core/src/nats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@ import { parseSemVer } from "./semver.ts";

import { parseOptions } from "./options.ts";
import { QueuedIteratorImpl } from "./queued_iterator.ts";
import { RequestMany, RequestOne } from "./request.ts";

import type { RequestManyOptionsInternal } from "./request.ts";

import { createInbox, RequestStrategy } from "./core.ts";
import type { Dispatcher } from "./core.ts";
import { RequestMany, RequestOne } from "./request.ts";

import type {
ConnectionOptions,
Context,
Dispatcher,
Msg,
NatsConnection,
Payload,
Expand All @@ -45,7 +42,8 @@ import type {
Subscription,
SubscriptionOptions,
} from "./core.ts";
import { errors, InvalidArgumentError } from "./errors.ts";
import { createInbox, RequestStrategy } from "./core.ts";
import { errors, InvalidArgumentError, TimeoutError } from "./errors.ts";

export class NatsConnectionImpl implements NatsConnection {
options: ConnectionOptions;
Expand Down Expand Up @@ -110,6 +108,9 @@ export class NatsConnectionImpl implements NatsConnection {
options?: PublishOptions,
): void {
this._check(subject, false, true);
if (options?.reply) {
this._check(options.reply, false, true);
}
this.protocol.publish(subject, data, options);
}

Expand Down Expand Up @@ -185,10 +186,7 @@ export class NatsConnectionImpl implements NatsConnection {
opts.maxWait = opts.maxWait || 1000;
if (opts.maxWait < 1) {
return Promise.reject(
new errors.InvalidArgumentError(InvalidArgumentError.format(
"timeout",
"must be greater than 0",
)),
InvalidArgumentError.format("timeout", "must be greater than 0"),
);
}

Expand Down Expand Up @@ -353,18 +351,14 @@ export class NatsConnectionImpl implements NatsConnection {
opts.timeout = opts.timeout || 1000;
if (opts.timeout < 1) {
return Promise.reject(
new errors.InvalidArgumentError(
InvalidArgumentError.format("timeout", `must be greater than 0`),
),
InvalidArgumentError.format("timeout", `must be greater than 0`),
);
}
if (!opts.noMux && opts.reply) {
return Promise.reject(
new errors.InvalidArgumentError(
InvalidArgumentError.formatMultiple(
["reply", "noMux"],
"are mutually exclusive",
),
InvalidArgumentError.format(
["reply", "noMux"],
"are mutually exclusive",
),
);
}
Expand All @@ -381,18 +375,20 @@ export class NatsConnectionImpl implements NatsConnection {
max: 1,
timeout: opts.timeout,
callback: (err, msg) => {
// check for no responders
// check for no responders status
if (msg && msg.data?.length === 0 && msg.headers?.code === 503) {
err = new errors.NoRespondersError(subject);
}
if (err) {
// if we have a context, use that as the wrapper
if (errCtx) {
errCtx.message = err.message;
errCtx.cause = err;
err = errCtx;
} else {
err = new errors.RequestError(err.message, { cause: err });
// we have a proper stack on timeout
if (!(err instanceof TimeoutError)) {
if (errCtx) {
errCtx.message = err.message;
errCtx.cause = err;
err = errCtx;
} else {
err = new errors.RequestError(err.message, { cause: err });
}
}
d.reject(err);
sub.unsubscribe();
Expand Down
22 changes: 8 additions & 14 deletions core/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
tokenAuthenticator,
usernamePasswordAuthenticator,
} from "./authenticator.ts";
import { errors } from "./errors.ts";
import { errors, InvalidArgumentError } from "./errors.ts";

export const DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
export const DEFAULT_JITTER = 100;
Expand Down Expand Up @@ -84,11 +84,9 @@ export function parseOptions(opts?: ConnectionOptions): ConnectionOptions {
}

if (opts.servers.length > 0 && opts.port) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.formatMultiple(
["servers", "port"],
"are mutually exclusive",
),
throw InvalidArgumentError.format(
["servers", "port"],
"are mutually exclusive",
);
}

Expand Down Expand Up @@ -133,11 +131,9 @@ export function parseOptions(opts?: ConnectionOptions): ConnectionOptions {

if (options.resolve) {
if (typeof getResolveFn() !== "function") {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(
"resolve",
"is not supported in the current runtime",
),
throw InvalidArgumentError.format(
"resolve",
"is not supported in the current runtime",
);
}
}
Expand All @@ -159,8 +155,6 @@ export function checkOptions(info: ServerInfo, options: ConnectionOptions) {

export function checkUnsupportedOption(prop: string, v?: unknown) {
if (v) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(prop, "is not supported"),
);
throw InvalidArgumentError.format(prop, "is not supported");
}
}
18 changes: 6 additions & 12 deletions core/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ import {
DEFAULT_PING_INTERVAL,
DEFAULT_RECONNECT_TIME_WAIT,
} from "./options.ts";
import { errors, InvalidArgumentError } from "./errors.ts";

import type {
AuthorizationError,
PermissionViolationError,
UserAuthenticationExpiredError,
} from "./errors.ts";
import { errors } from "./errors.ts";

const FLUSH_THRESHOLD = 1024 * 32;

Expand Down Expand Up @@ -870,11 +871,9 @@ export class ProtocolHandler implements Dispatcher<ParserEvent> {
let hlen = 0;
if (options.headers) {
if (this.info && !this.info.headers) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(
"headers",
"are not available on this server",
),
InvalidArgumentError.format(
"headers",
"are not available on this server",
);
}
const hdrs = options.headers as MsgHdrsImpl;
Expand All @@ -884,12 +883,7 @@ export class ProtocolHandler implements Dispatcher<ParserEvent> {
}

if (this.info && len > this.info.max_payload) {
throw new errors.InvalidArgumentError(
errors.InvalidArgumentError.format(
"payload",
"max_payload size exceeded",
),
);
throw InvalidArgumentError.format("payload", "max_payload size exceeded");
}
this.outBytes += len;
this.outMsgs++;
Expand Down
Loading

0 comments on commit a4cdc52

Please sign in to comment.