• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats.deno / 9507266808

13 Jun 2024 09:54PM UTC coverage: 86.345% (-0.2%) from 86.495%
9507266808

push

github

web-flow
Merge pull request #704 from nats-io/easier-resolve

[FIX] simpler way to noResolve

1880 of 2244 branches covered (83.78%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 4 files covered. (100.0%)

24 existing lines in 3 files now uncovered.

11203 of 12908 relevant lines covered (86.79%)

871044.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.77
/jetstream/jsbaseclient_api.ts
1
/*
1✔
2
 * Copyright 2021-2023 The NATS Authors
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
53✔
15

16
import { Empty } from "../nats-base-client/encoders.ts";
53✔
17
import { Codec, JSONCodec } from "../nats-base-client/codec.ts";
53✔
18
import { backoff, delay, extend } from "../nats-base-client/util.ts";
53✔
19
import { NatsConnectionImpl } from "../nats-base-client/nats.ts";
20
import { checkJsErrorCode } from "./jsutil.ts";
53✔
21
import {
53✔
22
  ErrorCode,
53✔
23
  JetStreamOptions,
24
  Msg,
25
  NatsConnection,
26
  NatsError,
27
  RequestOptions,
28
} from "../nats-base-client/core.ts";
53✔
29
import { ApiResponse } from "./jsapi_types.ts";
30

31
const defaultPrefix = "$JS.API";
53✔
32
const defaultTimeout = 5000;
53✔
33

34
export function defaultJsOptions(opts?: JetStreamOptions): JetStreamOptions {
53✔
35
  opts = opts || {} as JetStreamOptions;
4,005✔
36
  if (opts.domain) {
4,005✔
37
    opts.apiPrefix = `$JS.${opts.domain}.API`;
4,012✔
38
    delete opts.domain;
4,012✔
39
  }
4,012✔
40
  return extend({ apiPrefix: defaultPrefix, timeout: defaultTimeout }, opts);
16,020✔
41
}
4,005✔
42

43
export interface StreamNames {
44
  streams: string[];
45
}
46

47
export interface StreamNameBySubject {
48
  subject: string;
49
}
50

51
export class BaseApiClient {
53✔
52
  nc: NatsConnectionImpl;
3,996✔
53
  opts: JetStreamOptions;
3,996✔
54
  prefix: string;
3,996✔
55
  timeout: number;
3,996✔
56
  jc: Codec<unknown>;
3,996✔
57

58
  constructor(nc: NatsConnection, opts?: JetStreamOptions) {
3,996✔
59
    this.nc = nc as NatsConnectionImpl;
7,939✔
60
    this.opts = defaultJsOptions(opts);
7,939✔
61
    this._parseOpts();
7,939✔
62
    this.prefix = this.opts.apiPrefix!;
7,939✔
63
    this.timeout = this.opts.timeout!;
7,939✔
64
    this.jc = JSONCodec();
7,939✔
65
  }
7,939✔
66

67
  getOptions(): JetStreamOptions {
3,996✔
68
    return Object.assign({}, this.opts);
4,050✔
69
  }
4,050✔
70

71
  _parseOpts() {
3,996✔
72
    let prefix = this.opts.apiPrefix;
7,939✔
73
    if (!prefix || prefix.length === 0) {
7,939✔
74
      throw new Error("invalid empty prefix");
7,942✔
75
    }
7,942✔
76
    const c = prefix[prefix.length - 1];
11,879✔
77
    if (c === ".") {
7,939✔
78
      prefix = prefix.substr(0, prefix.length - 1);
7,948✔
79
    }
7,948✔
80
    this.opts.apiPrefix = prefix;
11,879✔
81
  }
7,939✔
82

83
  async _request(
3,996✔
84
    subj: string,
3,996✔
85
    data: unknown = null,
3,996✔
86
    opts?: Partial<RequestOptions> & { retries?: number },
3,996✔
87
  ): Promise<unknown> {
3,996✔
88
    opts = opts || {} as RequestOptions;
7,011✔
89
    opts.timeout = this.timeout;
7,011✔
90

91
    let a: Uint8Array = Empty;
7,011✔
92
    if (data) {
7,011✔
93
      a = this.jc.encode(data);
8,754✔
94
    }
8,754✔
95

96
    let { retries } = opts as {
7,011✔
97
      retries: number;
98
    };
99

100
    retries = retries || 1;
7,011✔
101
    retries = retries === -1 ? Number.MAX_SAFE_INTEGER : retries;
7,011✔
102
    const bo = backoff();
7,011✔
103

104
    for (let i = 0; i < retries; i++) {
7,011✔
105
      try {
7,011✔
106
        const m = await this.nc.request(
7,011✔
107
          subj,
7,011✔
108
          a,
7,011✔
109
          opts as RequestOptions,
7,011✔
110
        );
111
        return this.parseJsResponse(m);
10,023✔
112
      } catch (err) {
7,011✔
113
        const ne = err as NatsError;
7,296✔
UNCOV
114
        if (
×
UNCOV
115
          (ne.code === "503" || ne.code === ErrorCode.Timeout) &&
✔
UNCOV
116
          i + 1 < retries
×
UNCOV
117
        ) {
×
UNCOV
118
          await delay(bo.backoff(i));
×
UNCOV
119
        } else {
×
120
          throw err;
7,296✔
121
        }
7,296✔
122
      }
7,296✔
123
    }
7,011!
124
  }
×
125

126
  async findStream(subject: string): Promise<string> {
3,996✔
127
    const q = { subject } as StreamNameBySubject;
12,291✔
128
    const r = await this._request(`${this.prefix}.STREAM.NAMES`, q);
4,097✔
129
    const names = r as StreamNames;
4,097✔
130
    if (!names.streams || names.streams.length !== 1) {
4,097✔
131
      throw new Error("no stream matches subject");
4,100✔
132
    }
4,100✔
133
    return names.streams[0];
4,195✔
134
  }
4,097✔
135

136
  getConnection(): NatsConnection {
×
137
    return this.nc;
×
138
  }
×
139

140
  parseJsResponse(m: Msg): unknown {
3,996✔
141
    const v = this.jc.decode(m.data);
129,843✔
142
    const r = v as ApiResponse;
129,843✔
143
    if (r.error) {
129,843✔
144
      const err = checkJsErrorCode(r.error.code, r.error.description);
130,149✔
145
      if (err !== null) {
130,149✔
146
        err.api_error = r.error;
130,149✔
147
        throw err;
130,149✔
148
      }
130,149✔
149
    }
130,149✔
150
    return v;
255,384✔
151
  }
129,843✔
152
}
3,996✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc