mirror of
https://github.com/hanzomsg/nats.js.git
synced 2026-10-30 20:31:36 +00:00
557 lines
115 KiB
HTML
557 lines
115 KiB
HTML
<!DOCTYPE html><html class="default" lang="en" data-base="./"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>@nats-io/nats-core</title><meta name="description" content="Documentation for @nats-io/nats-core"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script defer src="assets/main.js"></script><script async src="assets/icons.js" id="tsd-icons-script"></script><script async src="assets/search.js" id="tsd-search-script"></script><script async src="assets/navigation.js" id="tsd-nav-script"></script><script async src="assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="index.html" class="title">@nats-io/nats-core</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><h1>@nats-io/nats-core</h1></div><div class="tsd-panel tsd-typography"><p><a href="./LICENSE"><img src="https://img.shields.io/badge/Licence-Apache%202.0-blue.svg" alt="License"></a>
|
|
<img src="https://github.com/nats-io/nats.js/actions/workflows/test.yml/badge.svg" alt="nats-core">
|
|
<a href="https://nats-io.github.io/nats.js/core/index.html"><img src="https://img.shields.io/badge/JSDoc-reference-blue" alt="JSDoc"></a></p>
|
|
<p><a href="https://jsr.io/@nats-io/nats-core"><img src="https://jsr.io/badges/@nats-io/nats-core" alt="JSR"></a>
|
|
<a href="https://jsr.io/@nats-io/nats-core"><img src="https://jsr.io/badges/@nats-io/nats-core/score" alt="JSR"></a></p>
|
|
<p><a href="https://www.npmjs.com/package/@nats-io/nats-core"><img src="https://img.shields.io/npm/v/%40nats-io%2Fnats-core" alt="NPM Version"></a>
|
|
<img src="https://img.shields.io/npm/dt/%40nats-io%2Fnats-core" alt="NPM Downloads">
|
|
<img src="https://img.shields.io/npm/dm/%40nats-io%2Fnats-core" alt="NPM Downloads"></p>
|
|
<h1 id="core" class="tsd-anchor-link">Core<a href="#core" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h1><p>The <em>core</em> module implements the <em>core</em> functionality for JavaScript clients:</p>
|
|
<ul>
|
|
<li>Connection, authentication, connection lifecycle</li>
|
|
<li>NATS protocol handling - messaging functionality (publish, subscribe and
|
|
request reply)</li>
|
|
</ul>
|
|
<p>A native transports (node, deno) modules are a peer module that export a
|
|
<code>connect</code> function which returns a concrete instance of a <code>NatsConnection</code>. The
|
|
transport library re-exports all the functionality in this module, to make it
|
|
the entry point into the NATS JavaScript ecosystem.</p>
|
|
<p>You can use this module as a runtime agnostic dependency and implement
|
|
functionality that uses a NATS client connection without binding your code to a
|
|
particular runtime. For example, the @nats-io/jetstream library depends on
|
|
@nats-io/nats-core to implement all of its JetStream protocol.</p>
|
|
<h2 id="websocket-support" class="tsd-anchor-link">WebSocket Support<a href="#websocket-support" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The <em>core</em> module also offers a for W3C Websocket transport (aka browser, Deno,
|
|
and Node v22) via the exported <code>wsconnect</code> function. This function is
|
|
semantically equivalent to the traditional <code>connect</code>, but returns a
|
|
<code>NatsConnection</code> that is backed by a W3C WebSocket.</p>
|
|
<p>Note that wsconnect assumes <code>wss://</code> connections. If you provide a port, it
|
|
likewise resolve to <code>wss://localhost:443</code>. If you specify a <code>ws://</code> URL, the
|
|
client assumes port 80, which is likely not the port. Check your server
|
|
configuration as the port for WebSocket protocol is NOT 4222.</p>
|
|
<h1 id="installation" class="tsd-anchor-link">Installation<a href="#installation" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h1><p>For a quick overview of the libraries and how to install them, see
|
|
<a href="media/runtimes.md">runtimes.md</a>.</p>
|
|
<p>If you are not implementing a NATS client compatible module, you can use this
|
|
repository to view the documentation of the NATS core functionality. Your NATS
|
|
client instance already uses and re-exports the module implemented here, so
|
|
there's no need for you to directly depend on this library.</p>
|
|
<p>Note that this module is distributed in two different registries:</p>
|
|
<ul>
|
|
<li>npm a node-specific library supporting CJS (<code>require</code>) and ESM (<code>import</code>) for
|
|
node specific projects</li>
|
|
<li>jsr a node and other ESM (<code>import</code>) compatible runtimes (deno, browser, node)</li>
|
|
</ul>
|
|
<p>If your application doesn't use <code>require</code>, you can simply depend on the JSR
|
|
version.</p>
|
|
<h2 id="npm" class="tsd-anchor-link">NPM<a href="#npm" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The NPM registry hosts a node-only compatible version of the library
|
|
<a href="https://www.npmjs.com/package/@nats-io/nats-core">@nats-io/nats-core</a>
|
|
supporting both CJS and ESM:</p>
|
|
<pre><code class="bash"><span class="hl-0">npm</span><span class="hl-1"> </span><span class="hl-2">install</span><span class="hl-1"> </span><span class="hl-2">@nats-io/nats-core</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h2 id="jsr" class="tsd-anchor-link">JSR<a href="#jsr" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The JSR registry hosts the ESM-only
|
|
<a href="https://jsr.io/@nats-io/nats-core">@nats-io/nats-core</a> version of the library.</p>
|
|
<pre><code class="bash"><span class="hl-0">deno</span><span class="hl-1"> </span><span class="hl-2">add</span><span class="hl-1"> </span><span class="hl-2">jsr:@nats-io/nats-core</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<pre><code class="bash"><span class="hl-0">npx</span><span class="hl-1"> </span><span class="hl-2">jsr</span><span class="hl-1"> </span><span class="hl-2">add</span><span class="hl-1"> </span><span class="hl-2">@nats-io/nats-core</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<pre><code class="bash"><span class="hl-0">yarn</span><span class="hl-1"> </span><span class="hl-2">dlx</span><span class="hl-1"> </span><span class="hl-2">jsr</span><span class="hl-1"> </span><span class="hl-2">add</span><span class="hl-1"> </span><span class="hl-2">@nats-io/nats-core</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<pre><code class="bash"><span class="hl-0">bunx</span><span class="hl-1"> </span><span class="hl-2">jsr</span><span class="hl-1"> </span><span class="hl-2">add</span><span class="hl-1"> </span><span class="hl-2">@nats-io/nats-core</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h2 id="referencing-the-library" class="tsd-anchor-link">Referencing the library<a href="#referencing-the-library" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Once you import the library, you can reference in your code as:</p>
|
|
<pre><code class="javascript"><span class="hl-3">import</span><span class="hl-1"> </span><span class="hl-4">*</span><span class="hl-1"> </span><span class="hl-3">as</span><span class="hl-1"> </span><span class="hl-5">nats_core</span><span class="hl-1"> </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/nats-core"</span><span class="hl-1">;</span><br/><span class="hl-6">// or in node (only when using CJS)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nats_core</span><span class="hl-1"> = </span><span class="hl-0">require</span><span class="hl-1">(</span><span class="hl-2">"@nats-io/nats-core"</span><span class="hl-1">);</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<p>The main entry point for this library is the <code>NatsConnection</code>.</p>
|
|
<h2 id="basics" class="tsd-anchor-link">Basics<a href="#basics" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="connecting-to-a-nats-server" class="tsd-anchor-link">Connecting to a nats-server<a href="#connecting-to-a-nats-server" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>To connect to a server you use the <code>connect()</code> exposed by your selected
|
|
transport. The connect function returns a connection which implements the
|
|
<code>NatsConnection</code> that you can use to interact with the server.</p>
|
|
<p>The <code>connect()</code> function will accept a <code>ConnectOptions</code> which customizes some of
|
|
the client behaviors. In general all options apply to all transports where
|
|
possible. Options that are non-sensical on a particular runtime will be
|
|
documented by your transport module.</p>
|
|
<p>By default, <code>connect()</code> will attempt a connection on <code>127.0.0.1:4222</code>. If the
|
|
connection is dropped, the client will attempt to reconnect. You can customize
|
|
the server you want to connect to by specifying <code>port</code> (for local connections),
|
|
or full hostport on the <code>servers</code> option. Note that the <code>servers</code> option can be
|
|
a single hostport (a string) or an array of hostports.</p>
|
|
<p>The example below will attempt to connect to different servers by specifying
|
|
different <code>ConnectionOptions</code>. At least two of them should work if your internet
|
|
is working.</p>
|
|
<pre><code class="typescript"><span class="hl-6">// import the connect function from a transport</span><br/><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">servers</span><span class="hl-1"> = [</span><br/><span class="hl-1"> {},</span><br/><span class="hl-1"> { </span><span class="hl-5">servers:</span><span class="hl-1"> [</span><span class="hl-2">"demo.nats.io:4442"</span><span class="hl-1">, </span><span class="hl-2">"demo.nats.io:4222"</span><span class="hl-1">] },</span><br/><span class="hl-1"> { </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"demo.nats.io:4443"</span><span class="hl-1"> },</span><br/><span class="hl-1"> { </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">4222</span><span class="hl-1"> },</span><br/><span class="hl-1"> { </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"localhost"</span><span class="hl-1"> },</span><br/><span class="hl-1">];</span><br/><span class="hl-5">servers</span><span class="hl-1">.</span><span class="hl-0">forEach</span><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-5">v</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">try</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">(</span><span class="hl-5">v</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`connected to </span><span class="hl-4">${</span><span class="hl-5">nc</span><span class="hl-9">.</span><span class="hl-0">getServer</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-6">// this promise indicates the client closed</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">done</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">closed</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-6">// do something with the connection</span><br/><br/><span class="hl-1"> </span><span class="hl-6">// close the connection</span><br/><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">close</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-6">// check if the close was OK</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">err</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">done</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`error closing:`</span><span class="hl-1">, </span><span class="hl-5">err</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> } </span><span class="hl-3">catch</span><span class="hl-1"> (</span><span class="hl-5">_err</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`error connecting to </span><span class="hl-4">${</span><span class="hl-7">JSON</span><span class="hl-9">.</span><span class="hl-0">stringify</span><span class="hl-9">(</span><span class="hl-5">v</span><span class="hl-9">)</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">});</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<p>To disconnect from the nats-server, call <code>close()</code> on the connection. A
|
|
connection can also be terminated when an unexpected error happens. For example,
|
|
the server returns a run-time error. In those cases, the client will re-initiate
|
|
a connection, it the connection options allow it.</p>
|
|
<p>By default, the client will always attempt to reconnect if the connection is
|
|
disrupted for a reason other than calling <code>close()</code>. To get notified when the
|
|
connection is closed, await the resolution of the Promise returned by
|
|
<code>closed()</code>. If closed resolves to a value, the value is a <code>NatsError</code> indicating
|
|
why the connection closed.</p>
|
|
<h3 id="publish-and-subscribe" class="tsd-anchor-link">Publish and Subscribe<a href="#publish-and-subscribe" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>The basic NATS client operations are <code>publish</code> to send messages and <code>subscribe</code>
|
|
to receive messages.</p>
|
|
<p>Messages are published to a <em>subject</em>. A <em>subject</em> is like a URL with the
|
|
exception that it doesn't specify an actual endpoint. Subjects can be any
|
|
string, but until you learn more about NATS stick to the simple rule that
|
|
subjects that are just simple ASCII printable letters and number characters. All
|
|
recipients that have expressed interest in a subject will receive messages
|
|
addressed to that subject (provided they have access and permissions to get it).
|
|
To express interest in a subject, you create a <code>subscription</code>.</p>
|
|
<p>In JavaScript clients subscriptions work as an async iterator - clients simply
|
|
loop to process messages as they happen.</p>
|
|
<p>NATS messages are payload agnostic. Payloads are <code>Uint8Arrays</code> or <code>string</code>.
|
|
Messages also provide a <code>string()</code> and <code>json()</code> that allows you to convert the
|
|
underlying <code>Uint8Array</code> into a string or parse by using <code>JSON.parse()</code> (which
|
|
can fail to parse if the payload is not the expected format).</p>
|
|
<p>To cancel a subscription and terminate your interest, you call <code>unsubscribe()</code>
|
|
or <code>drain()</code> on a subscription. Unsubscribe will typically terminate regardless
|
|
of whether there are messages in flight for the client. Drain ensures that all
|
|
messages that are inflight are processed before canceling the subscription.
|
|
Connections can also be drained as well. Draining a connection closes it, after
|
|
all subscriptions have been drained and all outbound messages have been sent to
|
|
the server.</p>
|
|
<pre><code class="typescript"><span class="hl-6">// import the connect function from a transport</span><br/><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><br/><span class="hl-6">// to create a connection to a nats-server:</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({ </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"demo.nats.io:4222"</span><span class="hl-1"> });</span><br/><br/><span class="hl-6">// create a simple subscriber and iterate over messages</span><br/><span class="hl-6">// matching the subscription</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"hello"</span><span class="hl-1">);</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">sub</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">]: </span><span class="hl-4">${</span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-0">string</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">"subscription closed"</span><span class="hl-1">);</span><br/><span class="hl-1">})();</span><br/><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">publish</span><span class="hl-1">(</span><span class="hl-2">"hello"</span><span class="hl-1">, </span><span class="hl-2">"world"</span><span class="hl-1">);</span><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">publish</span><span class="hl-1">(</span><span class="hl-2">"hello"</span><span class="hl-1">, </span><span class="hl-2">"again"</span><span class="hl-1">);</span><br/><br/><span class="hl-6">// we want to ensure that messages that are in flight</span><br/><span class="hl-6">// get processed, so we are going to drain the</span><br/><span class="hl-6">// connection. Drain is the same as close, but makes</span><br/><span class="hl-6">// sure that all messages in flight get seen</span><br/><span class="hl-6">// by the iterator. After calling drain,</span><br/><span class="hl-6">// the connection closes.</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">drain</span><span class="hl-1">();</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<pre><code class="typescript"><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-10">Person</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">name</span><span class="hl-1">: </span><span class="hl-10">string</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-6">// create a simple subscriber and iterate over messages</span><br/><span class="hl-6">// matching the subscription</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"people"</span><span class="hl-1">);</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">sub</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-6">// typescript will see this as a Person</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">p</span><span class="hl-1"> = </span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-0">json</span><span class="hl-1"><</span><span class="hl-10">Person</span><span class="hl-1">>();</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">]: </span><span class="hl-4">${</span><span class="hl-5">p</span><span class="hl-9">.</span><span class="hl-5">name</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">})();</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">p</span><span class="hl-1"> = { </span><span class="hl-5">name:</span><span class="hl-1"> </span><span class="hl-2">"Memo"</span><span class="hl-1"> } </span><span class="hl-3">as</span><span class="hl-1"> </span><span class="hl-10">Person</span><span class="hl-1">;</span><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">publish</span><span class="hl-1">(</span><span class="hl-2">"people"</span><span class="hl-1">, </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">stringify</span><span class="hl-1">(</span><span class="hl-5">p</span><span class="hl-1">));</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="wildcard-subscriptions" class="tsd-anchor-link">Wildcard Subscriptions<a href="#wildcard-subscriptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Subjects can be used to organize messages into hierarchies. For example, a
|
|
subject may contain additional information that can be useful in providing a
|
|
context to the message, such as the ID of the client that sent the message, or
|
|
the region where a message originated.</p>
|
|
<p>Instead of subscribing to each specific subject, you can create subscriptions
|
|
that have subjects with wildcards. Wildcards match one or more tokens in a
|
|
subject. A token is a string following a period (<code>.</code>).</p>
|
|
<p>All subscriptions are independent. If two different subscriptions match a
|
|
subject, both will get to process the message:</p>
|
|
<pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><span class="hl-3">import</span><span class="hl-1"> </span><span class="hl-3">type</span><span class="hl-1"> { </span><span class="hl-5">Subscription</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({ </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"demo.nats.io:4222"</span><span class="hl-1"> });</span><br/><br/><span class="hl-6">// subscriptions can have wildcard subjects</span><br/><span class="hl-6">// the '*' matches any string in the specified token position</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">s1</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"help.*.system"</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">s2</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"help.me.*"</span><span class="hl-1">);</span><br/><span class="hl-6">// the '>' matches any tokens in that position or following</span><br/><span class="hl-6">// '>' can only be specified at the end</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">s3</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"help.>"</span><span class="hl-1">);</span><br/><br/><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-0">printMsgs</span><span class="hl-1">(</span><span class="hl-5">s</span><span class="hl-1">: </span><span class="hl-10">Subscription</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">subj</span><span class="hl-1"> = </span><span class="hl-5">s</span><span class="hl-1">.</span><span class="hl-0">getSubject</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`listening for </span><span class="hl-4">${</span><span class="hl-5">subj</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">c</span><span class="hl-1"> = </span><span class="hl-8">13</span><span class="hl-1"> - </span><span class="hl-5">subj</span><span class="hl-1">.</span><span class="hl-5">length</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">pad</span><span class="hl-1"> = </span><span class="hl-2">""</span><span class="hl-1">.</span><span class="hl-0">padEnd</span><span class="hl-1">(</span><span class="hl-5">c</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">s</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">subj</span><span class="hl-4">}</span><span class="hl-2">]</span><span class="hl-4">${</span><span class="hl-5">pad</span><span class="hl-4">}</span><span class="hl-2"> #</span><span class="hl-4">${</span><span class="hl-5">s</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> - </span><span class="hl-4">${</span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-5">subject</span><span class="hl-4">}</span><span class="hl-2"> </span><span class="hl-4">${</span><br/><span class="hl-9"> </span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-5">data</span><span class="hl-9"> </span><span class="hl-1">?</span><span class="hl-9"> </span><span class="hl-2">" "</span><span class="hl-9"> </span><span class="hl-1">+</span><span class="hl-9"> </span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-0">string</span><span class="hl-9">() </span><span class="hl-1">:</span><span class="hl-9"> </span><span class="hl-2">""</span><br/><span class="hl-9"> </span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-0">printMsgs</span><span class="hl-1">(</span><span class="hl-5">s1</span><span class="hl-1">);</span><br/><span class="hl-0">printMsgs</span><span class="hl-1">(</span><span class="hl-5">s2</span><span class="hl-1">);</span><br/><span class="hl-0">printMsgs</span><span class="hl-1">(</span><span class="hl-5">s3</span><span class="hl-1">);</span><br/><br/><span class="hl-6">// don't exit until the client closes</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">closed</span><span class="hl-1">();</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="services-requestreply" class="tsd-anchor-link">Services: Request/Reply<a href="#services-requestreply" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Request/Reply is NATS equivalent to an HTTP request. To make requests you
|
|
publish messages as you did before, but also specify a <code>reply</code> subject. The
|
|
<code>reply</code> subject is where a service will publish (send) your response.</p>
|
|
<p>NATS provides syntactic sugar, for publishing requests. The <code>request()</code> API will
|
|
generate a reply subject and manage the creation of a subscription under the
|
|
covers to receive the reply. It will also start a timer to ensure that if a
|
|
response is not received within your specified time, the request fails. The
|
|
example also illustrates a graceful shutdown.</p>
|
|
<h4 id="services" class="tsd-anchor-link">Services<a href="#services" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4><p>Here's an example of a service. It is a bit more complicated than expected
|
|
simply to illustrate not only how to create responses, but how the subject
|
|
itself is used to dispatch different behaviors.</p>
|
|
<pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1">, </span><span class="hl-5">Subscription</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/nats-deno"</span><span class="hl-1">;</span><br/><br/><span class="hl-6">// create a connection</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({ </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"demo.nats.io"</span><span class="hl-1"> });</span><br/><br/><span class="hl-6">// this subscription listens for `time` requests and returns the current time</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"time"</span><span class="hl-1">);</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-5">sub</span><span class="hl-1">: </span><span class="hl-10">Subscription</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`listening for </span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getSubject</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> requests...`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">sub</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-0">respond</span><span class="hl-1">(</span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">Date</span><span class="hl-1">().</span><span class="hl-0">toISOString</span><span class="hl-1">())) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">info</span><span class="hl-1">(</span><span class="hl-2">`[time] handled #</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-3">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`[time] #</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> ignored - no reply subject`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`subscription </span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getSubject</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> drained.`</span><span class="hl-1">);</span><br/><span class="hl-1">})(</span><span class="hl-5">sub</span><span class="hl-1">);</span><br/><br/><span class="hl-6">// this subscription listens for admin.uptime and admin.stop</span><br/><span class="hl-6">// requests to admin.uptime returns how long the service has been running</span><br/><span class="hl-6">// requests to admin.stop gracefully stop the client by draining</span><br/><span class="hl-6">// the connection</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">started</span><span class="hl-1"> = </span><span class="hl-5">Date</span><span class="hl-1">.</span><span class="hl-0">now</span><span class="hl-1">();</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">msub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"admin.*"</span><span class="hl-1">);</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-5">sub</span><span class="hl-1">: </span><span class="hl-10">Subscription</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`listening for </span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getSubject</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> requests [uptime | stop]`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-6">// it would be very good to verify the origin of the request</span><br/><span class="hl-1"> </span><span class="hl-6">// before implementing something that allows your service to be managed.</span><br/><span class="hl-1"> </span><span class="hl-6">// NATS can limit which client can send or receive on what subjects.</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">sub</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">chunks</span><span class="hl-1"> = </span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-5">subject</span><span class="hl-1">.</span><span class="hl-0">split</span><span class="hl-1">(</span><span class="hl-2">"."</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">info</span><span class="hl-1">(</span><span class="hl-2">`[admin] #</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> handling </span><span class="hl-4">${</span><span class="hl-5">chunks</span><span class="hl-9">[</span><span class="hl-8">1</span><span class="hl-9">]</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">switch</span><span class="hl-1"> (</span><span class="hl-5">chunks</span><span class="hl-1">[</span><span class="hl-8">1</span><span class="hl-1">]) {</span><br/><span class="hl-1"> </span><span class="hl-3">case</span><span class="hl-1"> </span><span class="hl-2">"uptime"</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-6">// send the number of millis since up</span><br/><span class="hl-1"> </span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-0">respond</span><span class="hl-1">(</span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">Date</span><span class="hl-9">.</span><span class="hl-0">now</span><span class="hl-9">() </span><span class="hl-1">-</span><span class="hl-9"> </span><span class="hl-5">started</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">break</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-3">case</span><span class="hl-1"> </span><span class="hl-2">"stop"</span><span class="hl-1">: {</span><br/><span class="hl-1"> </span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-0">respond</span><span class="hl-1">(</span><span class="hl-2">`[admin] #</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> stopping....`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-6">// gracefully shutdown</span><br/><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">drain</span><span class="hl-1">()</span><br/><span class="hl-1"> .</span><span class="hl-0">catch</span><span class="hl-1">((</span><span class="hl-5">err</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">"error draining"</span><span class="hl-1">, </span><span class="hl-5">err</span><span class="hl-1">);</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> </span><span class="hl-3">break</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-3">default</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`[admin] #</span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> ignoring request for </span><span class="hl-4">${</span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-5">subject</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`subscription </span><span class="hl-4">${</span><span class="hl-5">sub</span><span class="hl-9">.</span><span class="hl-0">getSubject</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> drained.`</span><span class="hl-1">);</span><br/><span class="hl-1">})(</span><span class="hl-5">msub</span><span class="hl-1">);</span><br/><br/><span class="hl-6">// wait for the client to close here.</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">closed</span><span class="hl-1">().</span><span class="hl-0">then</span><span class="hl-1">((</span><span class="hl-5">err</span><span class="hl-1">?: </span><span class="hl-10">void</span><span class="hl-1"> | </span><span class="hl-10">Error</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">let</span><span class="hl-1"> </span><span class="hl-5">m</span><span class="hl-1"> = </span><span class="hl-2">`connection to </span><span class="hl-4">${</span><span class="hl-5">nc</span><span class="hl-9">.</span><span class="hl-0">getServer</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> closed`</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">m</span><span class="hl-1"> = </span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">m</span><span class="hl-4">}</span><span class="hl-2"> with an error: </span><span class="hl-4">${</span><span class="hl-5">err</span><span class="hl-9">.</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">m</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h4 id="making-requests" class="tsd-anchor-link">Making Requests<a href="#making-requests" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4><p>Here's a simple example of a client making a simple request from the service
|
|
above:</p>
|
|
<pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1">, </span><span class="hl-5">Empty</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"../../src/types.ts"</span><span class="hl-1">;</span><br/><br/><span class="hl-6">// create a connection</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({ </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"demo.nats.io:4222"</span><span class="hl-1"> });</span><br/><br/><span class="hl-6">// the client makes a request and receives a promise for a message</span><br/><span class="hl-6">// by default the request times out after 1s (1000 millis) and has</span><br/><span class="hl-6">// no payload.</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">request</span><span class="hl-1">(</span><span class="hl-2">"time"</span><span class="hl-1">, </span><span class="hl-5">Empty</span><span class="hl-1">, { </span><span class="hl-5">timeout:</span><span class="hl-1"> </span><span class="hl-8">1000</span><span class="hl-1"> })</span><br/><span class="hl-1"> .</span><span class="hl-0">then</span><span class="hl-1">((</span><span class="hl-5">m</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`got response: </span><span class="hl-4">${</span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-0">string</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> })</span><br/><span class="hl-1"> .</span><span class="hl-0">catch</span><span class="hl-1">((</span><span class="hl-5">err</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`problem with request: </span><span class="hl-4">${</span><span class="hl-5">err</span><span class="hl-9">.</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">close</span><span class="hl-1">();</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<p>Of course you can also use a tool like the nats cli:</p>
|
|
<pre><code class="bash"><span class="hl-1">> nats -s demo.nats.io req </span><span class="hl-4">time</span><span class="hl-1"> </span><span class="hl-2">""</span><br/><span class="hl-0">11:39:59</span><span class="hl-1"> </span><span class="hl-2">Sending</span><span class="hl-1"> </span><span class="hl-2">request</span><span class="hl-1"> </span><span class="hl-2">on</span><span class="hl-1"> </span><span class="hl-2">"time"</span><br/><span class="hl-0">11:39:59</span><span class="hl-1"> </span><span class="hl-2">Received</span><span class="hl-1"> </span><span class="hl-2">with</span><span class="hl-1"> </span><span class="hl-2">rtt</span><span class="hl-1"> </span><span class="hl-2">97.814458ms</span><br/><span class="hl-0">2024-06-26T16:39:59.710Z</span><br/><br/><span class="hl-1">> nats -s demo.nats.io req admin.uptime </span><span class="hl-2">""</span><br/><span class="hl-0">11:38:41</span><span class="hl-1"> </span><span class="hl-2">Sending</span><span class="hl-1"> </span><span class="hl-2">request</span><span class="hl-1"> </span><span class="hl-2">on</span><span class="hl-1"> </span><span class="hl-2">"admin.uptime"</span><br/><span class="hl-0">11:38:41</span><span class="hl-1"> </span><span class="hl-2">Received</span><span class="hl-1"> </span><span class="hl-2">with</span><span class="hl-1"> </span><span class="hl-2">rtt</span><span class="hl-1"> </span><span class="hl-2">99.065458ms</span><br/><span class="hl-0">61688</span><br/><br/><span class="hl-1">>nats -s demo.nats.io req admin.stop </span><span class="hl-2">""</span><br/><span class="hl-0">11:39:08</span><span class="hl-1"> </span><span class="hl-2">Sending</span><span class="hl-1"> </span><span class="hl-2">request</span><span class="hl-1"> </span><span class="hl-2">on</span><span class="hl-1"> </span><span class="hl-2">"admin.stop"</span><br/><span class="hl-0">11:39:08</span><span class="hl-1"> </span><span class="hl-2">Received</span><span class="hl-1"> </span><span class="hl-2">with</span><span class="hl-1"> </span><span class="hl-2">rtt</span><span class="hl-1"> </span><span class="hl-2">100.004959ms</span><br/><span class="hl-1">[admin] </span><span class="hl-6">#5 stopping....</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="queue-groups" class="tsd-anchor-link">Queue Groups<a href="#queue-groups" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Queue groups allow scaling of services horizontally. Subscriptions for members
|
|
of a queue group are treated as a single service. When you send a message to a
|
|
queue group subscription, only a single client in a queue group will receive it.</p>
|
|
<p>There can be any number of queue groups. Each group is treated as its own
|
|
independent unit. Note that non-queue subscriptions are also independent of
|
|
subscriptions in a queue group.</p>
|
|
<pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><span class="hl-3">import</span><span class="hl-1"> </span><span class="hl-3">type</span><span class="hl-1"> { </span><span class="hl-5">NatsConnection</span><span class="hl-1">, </span><span class="hl-5">Subscription</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><br/><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-0">createService</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-5">name</span><span class="hl-1">: </span><span class="hl-10">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">count</span><span class="hl-1"> = </span><span class="hl-8">1</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">queue</span><span class="hl-1"> = </span><span class="hl-2">""</span><span class="hl-1">,</span><br/><span class="hl-1">): </span><span class="hl-10">Promise</span><span class="hl-1"><</span><span class="hl-10">NatsConnection</span><span class="hl-1">[]> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">conns</span><span class="hl-1">: </span><span class="hl-10">NatsConnection</span><span class="hl-1">[] = [];</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> (</span><span class="hl-4">let</span><span class="hl-1"> </span><span class="hl-5">i</span><span class="hl-1"> = </span><span class="hl-8">1</span><span class="hl-1">; </span><span class="hl-5">i</span><span class="hl-1"> <= </span><span class="hl-5">count</span><span class="hl-1">; </span><span class="hl-5">i</span><span class="hl-1">++) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">n</span><span class="hl-1"> = </span><span class="hl-5">queue</span><span class="hl-1"> ? </span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">name</span><span class="hl-4">}</span><span class="hl-2">-</span><span class="hl-4">${</span><span class="hl-5">i</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1"> : </span><span class="hl-5">name</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">(</span><br/><span class="hl-1"> { </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"demo.nats.io:4222"</span><span class="hl-1">, </span><span class="hl-5">name:</span><span class="hl-1"> </span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">n</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1"> },</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">closed</span><span class="hl-1">()</span><br/><span class="hl-1"> .</span><span class="hl-0">then</span><span class="hl-1">((</span><span class="hl-5">err</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">error</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`service </span><span class="hl-4">${</span><span class="hl-5">n</span><span class="hl-4">}</span><span class="hl-2"> exited because of error: </span><span class="hl-4">${</span><span class="hl-5">err</span><span class="hl-9">.</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> </span><span class="hl-6">// create a subscription - note the option for a queue, if set</span><br/><span class="hl-1"> </span><span class="hl-6">// any client with the same queue will be the queue group.</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"echo"</span><span class="hl-1">, { </span><span class="hl-5">queue:</span><span class="hl-1"> </span><span class="hl-5">queue</span><span class="hl-1"> });</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">_</span><span class="hl-1"> = </span><span class="hl-0">handleRequest</span><span class="hl-1">(</span><span class="hl-5">n</span><span class="hl-1">, </span><span class="hl-5">sub</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">n</span><span class="hl-4">}</span><span class="hl-2"> is listening for 'echo' requests...`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">conns</span><span class="hl-1">.</span><span class="hl-0">push</span><span class="hl-1">(</span><span class="hl-5">nc</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-3">return</span><span class="hl-1"> </span><span class="hl-5">conns</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-6">// simple handler for service requests</span><br/><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-0">handleRequest</span><span class="hl-1">(</span><span class="hl-5">name</span><span class="hl-1">: </span><span class="hl-10">string</span><span class="hl-1">, </span><span class="hl-5">s</span><span class="hl-1">: </span><span class="hl-10">Subscription</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">p</span><span class="hl-1"> = </span><span class="hl-8">12</span><span class="hl-1"> - </span><span class="hl-5">name</span><span class="hl-1">.</span><span class="hl-5">length</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">pad</span><span class="hl-1"> = </span><span class="hl-2">""</span><span class="hl-1">.</span><span class="hl-0">padEnd</span><span class="hl-1">(</span><span class="hl-5">p</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">s</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-6">// respond returns true if the message had a reply subject, thus it could respond</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-0">respond</span><span class="hl-1">(</span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-5">data</span><span class="hl-1">)) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">name</span><span class="hl-4">}</span><span class="hl-2">]:</span><span class="hl-4">${</span><span class="hl-5">pad</span><span class="hl-4">}</span><span class="hl-2"> #</span><span class="hl-4">${</span><span class="hl-5">s</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> echoed </span><span class="hl-4">${</span><span class="hl-5">m</span><span class="hl-9">.</span><span class="hl-0">string</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> } </span><span class="hl-3">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">name</span><span class="hl-4">}</span><span class="hl-2">]:</span><span class="hl-4">${</span><span class="hl-5">pad</span><span class="hl-4">}</span><span class="hl-2"> #</span><span class="hl-4">${</span><span class="hl-5">s</span><span class="hl-9">.</span><span class="hl-0">getProcessed</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2"> ignoring request - no reply subject`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-6">// let's create two queue groups and a standalone subscriber</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">conns</span><span class="hl-1">: </span><span class="hl-10">NatsConnection</span><span class="hl-1">[] = [];</span><br/><span class="hl-5">conns</span><span class="hl-1">.</span><span class="hl-0">push</span><span class="hl-1">(...</span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">createService</span><span class="hl-1">(</span><span class="hl-2">"echo"</span><span class="hl-1">, </span><span class="hl-8">3</span><span class="hl-1">, </span><span class="hl-2">"echo"</span><span class="hl-1">));</span><br/><span class="hl-5">conns</span><span class="hl-1">.</span><span class="hl-0">push</span><span class="hl-1">(...</span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">createService</span><span class="hl-1">(</span><span class="hl-2">"other-echo"</span><span class="hl-1">, </span><span class="hl-8">2</span><span class="hl-1">, </span><span class="hl-2">"other-echo"</span><span class="hl-1">));</span><br/><span class="hl-5">conns</span><span class="hl-1">.</span><span class="hl-0">push</span><span class="hl-1">(...</span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">createService</span><span class="hl-1">(</span><span class="hl-2">"standalone"</span><span class="hl-1">));</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">a</span><span class="hl-1">: </span><span class="hl-10">Promise</span><span class="hl-1"><</span><span class="hl-10">void</span><span class="hl-1"> | </span><span class="hl-10">Error</span><span class="hl-1">>[] = [];</span><br/><span class="hl-5">conns</span><span class="hl-1">.</span><span class="hl-0">forEach</span><span class="hl-1">((</span><span class="hl-5">c</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">a</span><span class="hl-1">.</span><span class="hl-0">push</span><span class="hl-1">(</span><span class="hl-5">c</span><span class="hl-1">.</span><span class="hl-0">closed</span><span class="hl-1">());</span><br/><span class="hl-1">});</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-10">Promise</span><span class="hl-1">.</span><span class="hl-0">all</span><span class="hl-1">(</span><span class="hl-5">a</span><span class="hl-1">);</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<p>Run it and publish a request to the subject <code>echo</code> to see what happens.</p>
|
|
<h2 id="advanced-usage" class="tsd-anchor-link">Advanced Usage<a href="#advanced-usage" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="headers" class="tsd-anchor-link">Headers<a href="#headers" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>NATS headers are similar to HTTP headers. Headers are enabled automatically if
|
|
the server supports them. Note that if you publish a message using headers but
|
|
the server doesn't support them, an Error is thrown. Also note that even if you
|
|
are publishing a message with a header, it is possible for the recipient to not
|
|
support them.</p>
|
|
<pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1">, </span><span class="hl-5">createInbox</span><span class="hl-1">, </span><span class="hl-5">Empty</span><span class="hl-1">, </span><span class="hl-5">headers</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"../../src/types.ts"</span><span class="hl-1">;</span><br/><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">nuid</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"../../nats-base-client/nuid.ts"</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">(</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">`demo.nats.io`</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">);</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">subj</span><span class="hl-1"> = </span><span class="hl-0">createInbox</span><span class="hl-1">();</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-5">subj</span><span class="hl-1">);</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">sub</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-5">headers</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> [</span><span class="hl-7">key</span><span class="hl-1">, </span><span class="hl-7">value</span><span class="hl-1">] </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-5">headers</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">key</span><span class="hl-4">}</span><span class="hl-2">=</span><span class="hl-4">${</span><span class="hl-5">value</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-6">// reading a header is not case sensitive</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">"id"</span><span class="hl-1">, </span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-5">headers</span><span class="hl-1">.</span><span class="hl-0">get</span><span class="hl-1">(</span><span class="hl-2">"id"</span><span class="hl-1">));</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">})().</span><span class="hl-0">then</span><span class="hl-1">();</span><br/><br/><span class="hl-6">// header names can be any printable ASCII character with the exception of `:`.</span><br/><span class="hl-6">// header values can be any ASCII character except `\r` or `\n`.</span><br/><span class="hl-6">// see https://www.ietf.org/rfc/rfc822.txt</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">h</span><span class="hl-1"> = </span><span class="hl-0">headers</span><span class="hl-1">();</span><br/><span class="hl-5">h</span><span class="hl-1">.</span><span class="hl-0">append</span><span class="hl-1">(</span><span class="hl-2">"id"</span><span class="hl-1">, </span><span class="hl-5">nuid</span><span class="hl-1">.</span><span class="hl-0">next</span><span class="hl-1">());</span><br/><span class="hl-5">h</span><span class="hl-1">.</span><span class="hl-0">append</span><span class="hl-1">(</span><span class="hl-2">"unix_time"</span><span class="hl-1">, </span><span class="hl-5">Date</span><span class="hl-1">.</span><span class="hl-0">now</span><span class="hl-1">().</span><span class="hl-0">toString</span><span class="hl-1">());</span><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">publish</span><span class="hl-1">(</span><span class="hl-5">subj</span><span class="hl-1">, </span><span class="hl-5">Empty</span><span class="hl-1">, { </span><span class="hl-5">headers:</span><span class="hl-1"> </span><span class="hl-5">h</span><span class="hl-1"> });</span><br/><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">flush</span><span class="hl-1">();</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">close</span><span class="hl-1">();</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="no-responders" class="tsd-anchor-link">No Responders<a href="#no-responders" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Requests can fail for many reasons. A common reason for a failure is the lack of
|
|
interest in the subject. Typically these surface as a timeout error. If the
|
|
server is enabled to use headers, it will also enable a <code>no responders</code> feature.
|
|
If you send a request for which there's no interest, the request will be
|
|
immediately rejected:</p>
|
|
<pre><code class="typescript"><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><span class="hl-3">import</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">NoRespondersError</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">RequestError</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">TimeoutError</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">`demo.nats.io`</span><span class="hl-1">,</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-3">try</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">request</span><span class="hl-1">(</span><span class="hl-2">"hello.world"</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">m</span><span class="hl-1">.</span><span class="hl-5">data</span><span class="hl-1">);</span><br/><span class="hl-1">} </span><span class="hl-3">catch</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1"> </span><span class="hl-4">instanceof</span><span class="hl-1"> </span><span class="hl-10">RequestError</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1">.</span><span class="hl-5">cause</span><span class="hl-1"> </span><span class="hl-4">instanceof</span><span class="hl-1"> </span><span class="hl-10">TimeoutError</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">"someone is listening but didn't respond"</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-3">else</span><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1">.</span><span class="hl-5">cause</span><span class="hl-1"> </span><span class="hl-4">instanceof</span><span class="hl-1"> </span><span class="hl-10">NoRespondersError</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">"no one is listening to 'hello.world'"</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-3">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`failed due to unknown error: </span><span class="hl-4">${</span><span class="hl-9">(</span><span class="hl-5">err</span><span class="hl-9">.</span><span class="hl-5">cause</span><span class="hl-9"> </span><span class="hl-3">as</span><span class="hl-9"> </span><span class="hl-10">Error</span><span class="hl-9">)?.</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> } </span><span class="hl-3">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`request failed: </span><span class="hl-4">${</span><span class="hl-9">(</span><span class="hl-5">err</span><span class="hl-9"> </span><span class="hl-3">as</span><span class="hl-9"> </span><span class="hl-10">Error</span><span class="hl-9">).</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">close</span><span class="hl-1">();</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="authentication" class="tsd-anchor-link">Authentication<a href="#authentication" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>NATS supports many different forms of credentials:</p>
|
|
<ul>
|
|
<li>username/password</li>
|
|
<li>token</li>
|
|
<li>NKEYS</li>
|
|
<li>client certificates</li>
|
|
<li>JWTs</li>
|
|
</ul>
|
|
<p>For user/password and token authentication, you can simply provide them as
|
|
<code>ConnectionOptions</code> - see <code>user</code>, <code>pass</code>, <code>token</code>. Internally these mechanisms
|
|
are implemented as an <code>Authenticator</code>. An <code>Authenticator</code> is simply a function
|
|
that handles the type of authentication specified.</p>
|
|
<p>Setting the <code>user</code>/<code>pass</code> or <code>token</code> options, simply initializes an
|
|
<code>Authenticator</code> and sets the username/password.</p>
|
|
<pre><code class="typescript"><span class="hl-6">// if the connection requires authentication, provide `user` and `pass` or</span><br/><span class="hl-6">// `token` options in the NatsConnectionOptions</span><br/><span class="hl-3">import</span><span class="hl-1"> { </span><span class="hl-5">connect</span><span class="hl-1"> } </span><span class="hl-3">from</span><span class="hl-1"> </span><span class="hl-2">"@nats-io/transport-deno"</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc1</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-5">servers:</span><span class="hl-1"> </span><span class="hl-2">"127.0.0.1:4222"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">user:</span><span class="hl-1"> </span><span class="hl-2">"jenny"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">pass:</span><span class="hl-1"> </span><span class="hl-2">"867-5309"</span><span class="hl-1">,</span><br/><span class="hl-1">});</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc2</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">4222</span><span class="hl-1">, </span><span class="hl-5">token:</span><span class="hl-1"> </span><span class="hl-2">"t0pS3cret!"</span><span class="hl-1"> });</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h4 id="authenticators" class="tsd-anchor-link">Authenticators<a href="#authenticators" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4><p>NKEYs and JWT authentication are more complex, as they cryptographically respond
|
|
to a server challenge.</p>
|
|
<p>Because NKEY and JWT authentication may require reading data from a file or an
|
|
HTTP cookie, these forms of authentication will require a bit more from the
|
|
developer to activate them. The work is related to accessing these resources
|
|
varies depending on the platform.</p>
|
|
<p>After the credential artifacts are read, you can use one of these functions to
|
|
create the authenticator. You then simply assign it to the <code>authenticator</code>
|
|
property of the <code>ConnectionOptions</code>:</p>
|
|
<ul>
|
|
<li><code>nkeyAuthenticator(seed?: Uint8Array | (() => Uint8Array)): Authenticator</code></li>
|
|
<li><code>jwtAuthenticator(jwt: string | (() => string), seed?: Uint8Array | (()=> Uint8Array)): Authenticator</code></li>
|
|
<li><code>credsAuthenticator(creds: Uint8Array | (() => Uint8Array)): Authenticator</code></li>
|
|
</ul>
|
|
<p>Note that the authenticators provide the ability to specify functions that
|
|
return the desired value. This enables dynamic environments such as a browser
|
|
where values accessed by fetching a value from a cookie.</p>
|
|
<p>Here's an example:</p>
|
|
<pre><code class="javascript"><span class="hl-6">// read the creds file as necessary, in the case it</span><br/><span class="hl-6">// is part of the code for illustration purposes (this a partial creds)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">creds</span><span class="hl-1"> = </span><span class="hl-2">`-----BEGIN NATS USER JWT-----</span><br/><span class="hl-2"> eyJ0eXAiOiJqdSDJB....</span><br/><span class="hl-2"> ------END NATS USER JWT------</span><br/><br/><span class="hl-2">************************* IMPORTANT *************************</span><br/><span class="hl-2"> NKEY Seed printed below can be used sign and prove identity.</span><br/><span class="hl-2"> NKEYs are sensitive and should be treated as secrets.</span><br/><br/><span class="hl-2"> -----BEGIN USER NKEY SEED-----</span><br/><span class="hl-2"> SUAIBDPBAUTW....</span><br/><span class="hl-2"> ------END USER NKEY SEED------</span><br/><span class="hl-2">`</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">(</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">4222</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">authenticator:</span><span class="hl-1"> </span><span class="hl-0">credsAuthenticator</span><span class="hl-1">(</span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">TextEncoder</span><span class="hl-1">().</span><span class="hl-0">encode</span><span class="hl-1">(</span><span class="hl-5">creds</span><span class="hl-1">)),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">);</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="flush" class="tsd-anchor-link">Flush<a href="#flush" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Flush sends a <code>PING</code> protocol message to the server. When the server responds
|
|
with <code>PONG</code> you are guaranteed that all pending data was sent and received by
|
|
the server. Note <code>ping()</code> effectively adds a server round-trip. All NATS clients
|
|
handle their buffering optimally, so <code>ping(): Promise<void></code> shouldn't be used
|
|
except in cases where you are writing some sort of test, as you may be degrading
|
|
the performance of the client.</p>
|
|
<pre><code class="javascript"><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">publish</span><span class="hl-1">(</span><span class="hl-2">"foo"</span><span class="hl-1">);</span><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">publish</span><span class="hl-1">(</span><span class="hl-2">"bar"</span><span class="hl-1">);</span><br/><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">flush</span><span class="hl-1">();</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="publishoptions" class="tsd-anchor-link"><code>PublishOptions</code><a href="#publishoptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>When you publish a message you can specify some options:</p>
|
|
<ul>
|
|
<li><code>reply</code> - this is a subject to receive a reply (you must set up a subscription
|
|
on the reply subject) before you publish.</li>
|
|
<li><code>headers</code> - a set of headers to decorate the message.</li>
|
|
</ul>
|
|
<h3 id="subscriptionoptions" class="tsd-anchor-link"><code>SubscriptionOptions</code><a href="#subscriptionoptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>You can specify several options when creating a subscription:</p>
|
|
<ul>
|
|
<li><code>max</code>: maximum number of messages to receive - auto unsubscribe</li>
|
|
<li><code>timeout</code>: how long to wait for the first message</li>
|
|
<li><code>queue</code>: the <a href="#queue-groups">queue group</a> name the subscriber belongs to</li>
|
|
<li><code>callback</code>: a function with the signature
|
|
<code>(err: Error|null, msg: Msg) => void;</code> that should be used for handling the
|
|
message. Subscriptions with callbacks are NOT iterators.</li>
|
|
</ul>
|
|
<h4 id="auto-unsubscribe" class="tsd-anchor-link">Auto Unsubscribe<a href="#auto-unsubscribe" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4><pre><code class="javascript"><span class="hl-6">// subscriptions can auto unsubscribe after a certain number of messages</span><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"foo"</span><span class="hl-1">, { </span><span class="hl-5">max:</span><span class="hl-1"> </span><span class="hl-8">10</span><span class="hl-1"> });</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h4 id="timeout-subscriptions" class="tsd-anchor-link">Timeout Subscriptions<a href="#timeout-subscriptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4><pre><code class="javascript"><span class="hl-6">// create subscription with a timeout, if no message arrives</span><br/><span class="hl-6">// within the timeout, the subscription throws a timeout error</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sub</span><span class="hl-1"> = </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">subscribe</span><span class="hl-1">(</span><span class="hl-2">"hello"</span><span class="hl-1">, { </span><span class="hl-5">timeout:</span><span class="hl-1"> </span><span class="hl-8">1000</span><span class="hl-1"> });</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">_m</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">sub</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-6">// handle the messages</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">})().</span><span class="hl-0">catch</span><span class="hl-1">((</span><span class="hl-5">err</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-3">if</span><span class="hl-1"> (</span><span class="hl-5">err</span><span class="hl-1"> </span><span class="hl-4">instanceof</span><span class="hl-1"> </span><span class="hl-10">TimeoutError</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`sub timed out!`</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-3">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`sub iterator got an error!`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">close</span><span class="hl-1">();</span><br/><span class="hl-1">});</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="requestoptions" class="tsd-anchor-link"><code>RequestOptions</code><a href="#requestoptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>When making a request, there are several options you can pass:</p>
|
|
<ul>
|
|
<li><code>timeout</code>: how long to wait for the response</li>
|
|
<li><code>headers</code>: optional headers to include with the message</li>
|
|
<li><code>noMux</code>: create a new subscription to handle the request. Normally a shared
|
|
subscription is used to receive response messages.</li>
|
|
<li><code>reply</code>: optional subject where the reply should be sent.</li>
|
|
</ul>
|
|
<h4 id="nomux-and-reply" class="tsd-anchor-link"><code>noMux</code> and <code>reply</code><a href="#nomux-and-reply" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4><p>Under the hood, the request API simply uses a wildcard subscription to handle
|
|
all requests you send.</p>
|
|
<p>In some cases, the default subscription strategy doesn't work correctly. For
|
|
example, a client may be constrained by the subjects where it can receive
|
|
replies.</p>
|
|
<p>When <code>noMux</code> is set to <code>true</code>, the client will create a normal subscription for
|
|
receiving the response to a generated inbox subject before the request is
|
|
published. The <code>reply</code> option can be used to override the generated inbox
|
|
subject with an application provided one. Note that setting <code>reply</code> requires
|
|
<code>noMux</code> to be <code>true</code>:</p>
|
|
<pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">m</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">request</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">"q"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">Empty</span><span class="hl-1">,</span><br/><span class="hl-1"> { </span><span class="hl-5">reply:</span><span class="hl-1"> </span><span class="hl-2">"bar"</span><span class="hl-1">, </span><span class="hl-5">noMux:</span><span class="hl-1"> </span><span class="hl-4">true</span><span class="hl-1">, </span><span class="hl-5">timeout:</span><span class="hl-1"> </span><span class="hl-8">1000</span><span class="hl-1"> },</span><br/><span class="hl-1">);</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<h3 id="draining-connections-and-subscriptions" class="tsd-anchor-link">Draining Connections and Subscriptions<a href="#draining-connections-and-subscriptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Draining provides for a graceful way to unsubscribe or close a connection
|
|
without losing messages that have already been dispatched to the client.</p>
|
|
<p>You can drain a subscription or all subscriptions in a connection.</p>
|
|
<p>When you drain a subscription, the client sends an <code>unsubscribe</code> protocol
|
|
message to the server followed by a <code>flush</code>. The subscription handler is only
|
|
removed after the server responds. Thus all pending messages for the
|
|
subscription have been processed.</p>
|
|
<p>Draining a connection, drains all subscriptions. However when you drain the
|
|
connection it becomes impossible to make new subscriptions or send new requests.
|
|
After the last subscription is drained it also becomes impossible to publish a
|
|
message. These restrictions do not exist when just draining a subscription.</p>
|
|
<h3 id="lifecycle-and-informational-events" class="tsd-anchor-link">Lifecycle and Informational Events<a href="#lifecycle-and-informational-events" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Clients can get notification on various event types by calling
|
|
<code>status(): AsyncIterable<Status></code> on the connection, the currently included
|
|
status <code>type</code>s include:</p>
|
|
<ul>
|
|
<li><code>disconnect</code> - the client disconnected from the specified <code>server</code></li>
|
|
<li><code>reconnect</code> - the client reconnected to the specified <code>server</code></li>
|
|
<li><code>reconnecting</code> - the client is in its reconnect loop</li>
|
|
<li><code>update</code> - the cluster configuration has been updated, if servers were added
|
|
the <code>added</code> list will specify them, if servers were deleted servers the
|
|
<code>deleted</code> list will specify them.</li>
|
|
<li><code>ldm</code> - the server has started its lame duck mode and will evict clients</li>
|
|
<li><code>error</code> - an async error (such as a permission violation) was received, the
|
|
error is specified in the <code>error</code> property. Note that permission errors for
|
|
subscriptions are also notified to the subscription.</li>
|
|
<li><code>ping</code> - the server has not received a response for client pings, the number
|
|
of outstanding pings are notified in the <code>pendingPings</code> property. Note that
|
|
this should onlyl be <code>1</code> under normal operations.</li>
|
|
<li><code>staleConnection</code> - the connection is stale (client will reconnect)</li>
|
|
<li><code>forceReconnect</code> - the client has been instructed to reconnect because of
|
|
user-code (<code>reconnect()</code>)</li>
|
|
<li><code>close</code> - the client has closed, no further reconnects will be attempted.</li>
|
|
</ul>
|
|
<pre><code class="javascript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">nc</span><span class="hl-1"> = </span><span class="hl-3">await</span><span class="hl-1"> </span><span class="hl-0">connect</span><span class="hl-1">(</span><span class="hl-5">opts</span><span class="hl-1">);</span><br/><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">info</span><span class="hl-1">(</span><span class="hl-2">`connected </span><span class="hl-4">${</span><span class="hl-5">nc</span><span class="hl-9">.</span><span class="hl-0">getServer</span><span class="hl-9">()</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">for</span><span class="hl-1"> </span><span class="hl-3">await</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">s</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">status</span><span class="hl-1">()) {</span><br/><span class="hl-1"> </span><span class="hl-3">switch</span><span class="hl-1"> (</span><span class="hl-5">s</span><span class="hl-1">.</span><span class="hl-5">type</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-3">case</span><span class="hl-1"> </span><span class="hl-2">"disconnect"</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-3">case</span><span class="hl-1"> </span><span class="hl-2">"reconnect"</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">s</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-3">break</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-3">default</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-6">// ignored</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">})().</span><span class="hl-0">then</span><span class="hl-1">();</span><br/><br/><span class="hl-5">nc</span><span class="hl-1">.</span><span class="hl-0">closed</span><span class="hl-1">()</span><br/><span class="hl-1"> .</span><span class="hl-0">then</span><span class="hl-1">((</span><span class="hl-5">err</span><span class="hl-1">) </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">`connection closed </span><span class="hl-4">${</span><span class="hl-5">err</span><span class="hl-9"> </span><span class="hl-1">?</span><span class="hl-9"> </span><span class="hl-2">" with error: "</span><span class="hl-9"> </span><span class="hl-1">+</span><span class="hl-9"> </span><span class="hl-5">err</span><span class="hl-9">.</span><span class="hl-5">message</span><span class="hl-9"> </span><span class="hl-1">:</span><span class="hl-9"> </span><span class="hl-2">""</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">,</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> });</span>
|
|
</code><button type="button">Copy</button></pre>
|
|
|
|
<p>Be aware that when a client closes, you will need to wait for the <code>closed()</code>
|
|
promise to resolve. When it resolves, the client is done and will not reconnect.</p>
|
|
<h3 id="async-vs-callbacks" class="tsd-anchor-link">Async vs. Callbacks<a href="#async-vs-callbacks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Previous versions of the JavaScript NATS clients specified callbacks for message
|
|
processing. This required complex handling logic when a service required
|
|
coordination of operations. Callbacks are an inversion of control anti-pattern.</p>
|
|
<p>The async APIs trivialize complex coordination and makes your code easier to
|
|
maintain. With that said, there are some implications:</p>
|
|
<ul>
|
|
<li>Async subscriptions buffer inbound messages.</li>
|
|
<li>Subscription processing delays until the runtime executes the promise related
|
|
microtasks at the end of an event loop.</li>
|
|
</ul>
|
|
<p>In a traditional callback-based library, I/O happens after all data yielded by a
|
|
read in the current event loop completes processing. This means that callbacks
|
|
are invoked as part of processing. With async, the processing is queued in a
|
|
microtask queue. At the end of the event loop, the runtime processes the
|
|
microtasks, which in turn resumes your functions. As expected, this increases
|
|
latency, but also provides additional liveliness.</p>
|
|
<p>To reduce async latency, the NATS client allows processing a subscription in the
|
|
same event loop that dispatched the message. Simply specify a <code>callback</code> in the
|
|
subscription options. The signature for a callback is
|
|
<code>(err: (NatsError|null), msg: Msg) => void</code>. When specified, the subscription
|
|
iterator will never yield a message, as the callback will intercept all
|
|
messages.</p>
|
|
<p>Note that <code>callback</code> likely shouldn't even be documented, as likely it is a
|
|
workaround to an underlying application problem where you should be considering
|
|
a different strategy to horizontally scale your application, or reduce pressure
|
|
on the clients, such as using queue workers, or more explicitly targeting
|
|
messages. With that said, there are many situations where using callbacks can be
|
|
more performant or appropriate.</p>
|
|
<h2 id="connection-options" class="tsd-anchor-link">Connection Options<a href="#connection-options" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The following is the list of connection options and default values.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Option</th>
|
|
<th>Default</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>authenticator</code></td>
|
|
<td>none</td>
|
|
<td>Specifies the authenticator function that sets the client credentials.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>debug</code></td>
|
|
<td><code>false</code></td>
|
|
<td>If <code>true</code>, the client prints protocol interactions to the console. Useful for debugging.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>ignoreClusterUpdates</code></td>
|
|
<td><code>false</code></td>
|
|
<td>If <code>true</code> the client will ignore any cluster updates provided by the server.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>ignoreAuthErrorAbort</code></td>
|
|
<td><code>false</code></td>
|
|
<td>Prevents client connection aborts if the client fails more than twice in a row with an authentication error</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>inboxPrefix</code></td>
|
|
<td><code>"_INBOX"</code></td>
|
|
<td>Sets de prefix for automatically created inboxes - <code>createInbox(prefix)</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>maxPingOut</code></td>
|
|
<td><code>2</code></td>
|
|
<td>Max number of pings the client will allow unanswered before raising a stale connection error.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>maxReconnectAttempts</code></td>
|
|
<td><code>10</code></td>
|
|
<td>Sets the maximum number of reconnect attempts. The value of <code>-1</code> specifies no limit.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>name</code></td>
|
|
<td></td>
|
|
<td>Optional client name - recommended to be set to a unique client name.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>noAsyncTraces</code></td>
|
|
<td><code>false</code></td>
|
|
<td>When <code>true</code> the client will not add additional context to errors associated with request operations. Setting this option to <code>true</code> will greatly improve performance of request/reply and JetStream publishers.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>noEcho</code></td>
|
|
<td><code>false</code></td>
|
|
<td>Subscriptions receive messages published by the client. Requires server support (1.2.0). If set to true, and the server does not support the feature, an error with code <code>NO_ECHO_NOT_SUPPORTED</code> is emitted, and the connection is aborted. Note that it is possible for this error to be emitted on reconnect when the server reconnects to a server that does not support the feature.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>noRandomize</code></td>
|
|
<td><code>false</code></td>
|
|
<td>If set, the order of user-specified servers is randomized.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>noResolve</code></td>
|
|
<td>none</td>
|
|
<td>If true, client will not resolve host names.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>pass</code></td>
|
|
<td></td>
|
|
<td>Sets the password for a connection.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>pedantic</code></td>
|
|
<td><code>false</code></td>
|
|
<td>Turns on strict subject format checks.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>pingInterval</code></td>
|
|
<td><code>120000</code></td>
|
|
<td>Number of milliseconds between client-sent pings.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>port</code></td>
|
|
<td><code>4222</code></td>
|
|
<td>Port to connect to (only used if <code>servers</code> is not specified).</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>reconnect</code></td>
|
|
<td><code>true</code></td>
|
|
<td>If false, client will not attempt reconnecting.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>reconnectDelayHandler</code></td>
|
|
<td>Generated function</td>
|
|
<td>A function that returns the number of millis to wait before the next connection to a server it connected to <code>()=>number</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>reconnectJitter</code></td>
|
|
<td><code>100</code></td>
|
|
<td>Number of millis to randomize after <code>reconnectTimeWait</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>reconnectJitterTLS</code></td>
|
|
<td><code>1000</code></td>
|
|
<td>Number of millis to randomize after <code>reconnectTimeWait</code> when TLS options are specified.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>reconnectTimeWait</code></td>
|
|
<td><code>2000</code></td>
|
|
<td>If disconnected, the client will wait the specified number of milliseconds between reconnect attempts.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>servers</code></td>
|
|
<td><code>"localhost:4222"</code></td>
|
|
<td>String or Array of hostport for servers.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>timeout</code></td>
|
|
<td>20000</td>
|
|
<td>Number of milliseconds the client will wait for a connection to be established. If it fails it will emit a <code>connection_timeout</code> event with a NatsError that provides the hostport of the server where the connection was attempted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>tls</code></td>
|
|
<td>TlsOptions</td>
|
|
<td>A configuration object for requiring a TLS connection (not applicable to <a href="http://nats.ws">nats.ws</a>).</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>token</code></td>
|
|
<td></td>
|
|
<td>Sets a authorization token for a connection.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>user</code></td>
|
|
<td></td>
|
|
<td>Sets the username for a connection.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>verbose</code></td>
|
|
<td><code>false</code></td>
|
|
<td>Turns on <code>+OK</code> protocol acknowledgements.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>waitOnFirstConnect</code></td>
|
|
<td><code>false</code></td>
|
|
<td>If <code>true</code> the client will fall back to a reconnect mode if it fails its first connection attempt.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3 id="tlsoptions" class="tsd-anchor-link">TlsOptions<a href="#tlsoptions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
|
|
<thead>
|
|
<tr>
|
|
<th>Option</th>
|
|
<th>Default</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>ca</code></td>
|
|
<td>N/A</td>
|
|
<td>CA certificate</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>caFile</code></td>
|
|
<td></td>
|
|
<td>CA certificate filepath</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>cert</code></td>
|
|
<td>N/A</td>
|
|
<td>Client certificate</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>certFile</code></td>
|
|
<td>N/A</td>
|
|
<td>Client certificate file path</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>key</code></td>
|
|
<td>N/A</td>
|
|
<td>Client key</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>keyFile</code></td>
|
|
<td>N/A</td>
|
|
<td>Client key file path</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>handshakeFirst</code></td>
|
|
<td>false</td>
|
|
<td>Connects to the server directly as TLS rather than upgrade the connection. Note that the server must be configured accordingly.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p>In some Node and Deno clients, having the option set to an empty option,
|
|
requires the client have a secured connection.</p>
|
|
<h3 id="jitter" class="tsd-anchor-link">Jitter<a href="#jitter" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3><p>The settings <code>reconnectTimeWait</code>, <code>reconnectJitter</code>, <code>reconnectJitterTLS</code>,
|
|
<code>reconnectDelayHandler</code> are all related. They control how long before the NATS
|
|
client attempts to reconnect to a server it has previously connected.</p>
|
|
<p>The intention of the settings is to spread out the number of clients attempting
|
|
to reconnect to a server over a period of time, and thus preventing a
|
|
<a href="https://docs.nats.io/developing-with-nats/reconnect/random">"Thundering Herd"</a>.</p>
|
|
<p>The relationship between these is:</p>
|
|
<ul>
|
|
<li>If <code>reconnectDelayHandler</code> is specified, the client will wait the value
|
|
returned by this function. No other value will be taken into account.</li>
|
|
<li>If the client specified TLS options, the client will generate a number between
|
|
0 and <code>reconnectJitterTLS</code> and add it to <code>reconnectTimeWait</code>.</li>
|
|
<li>If the client didn't specify TLS options, the client will generate a number
|
|
between 0 and <code>reconnectJitter</code> and add it to <code>reconnectTimeWait</code>.</li>
|
|
</ul>
|
|
</div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#core"><span>Core</span></a><ul><li><a href="#websocket-support"><span>Web<wbr/>Socket <wbr/>Support</span></a></li></ul><a href="#installation"><span>Installation</span></a><ul><li><a href="#npm"><span>NPM</span></a></li><li><a href="#jsr"><span>JSR</span></a></li><li><a href="#referencing-the-library"><span>Referencing the library</span></a></li><li><a href="#basics"><span>Basics</span></a></li><li><ul><li><a href="#connecting-to-a-nats-server"><span>Connecting to a nats-<wbr/>server</span></a></li><li><a href="#publish-and-subscribe"><span>Publish and <wbr/>Subscribe</span></a></li><li><a href="#wildcard-subscriptions"><span>Wildcard <wbr/>Subscriptions</span></a></li><li><a href="#services-requestreply"><span>Services: <wbr/>Request/<wbr/>Reply</span></a></li><li><ul><li><a href="#services"><span>Services</span></a></li><li><a href="#making-requests"><span>Making <wbr/>Requests</span></a></li></ul></li><li><a href="#queue-groups"><span>Queue <wbr/>Groups</span></a></li></ul></li><li><a href="#advanced-usage"><span>Advanced <wbr/>Usage</span></a></li><li><ul><li><a href="#headers"><span>Headers</span></a></li><li><a href="#no-responders"><span>No <wbr/>Responders</span></a></li><li><a href="#authentication"><span>Authentication</span></a></li><li><ul><li><a href="#authenticators"><span>Authenticators</span></a></li></ul></li><li><a href="#flush"><span>Flush</span></a></li><li><a href="#publishoptions"><span>Publish<wbr/>Options</span></a></li><li><a href="#subscriptionoptions"><span>Subscription<wbr/>Options</span></a></li><li><ul><li><a href="#auto-unsubscribe"><span>Auto <wbr/>Unsubscribe</span></a></li><li><a href="#timeout-subscriptions"><span>Timeout <wbr/>Subscriptions</span></a></li></ul></li><li><a href="#requestoptions"><span>Request<wbr/>Options</span></a></li><li><ul><li><a href="#nomux-and-reply"><span>no<wbr/>Mux and reply</span></a></li></ul></li><li><a href="#draining-connections-and-subscriptions"><span>Draining <wbr/>Connections and <wbr/>Subscriptions</span></a></li><li><a href="#lifecycle-and-informational-events"><span>Lifecycle and <wbr/>Informational <wbr/>Events</span></a></li><li><a href="#async-vs-callbacks"><span>Async vs. <wbr/>Callbacks</span></a></li></ul></li><li><a href="#connection-options"><span>Connection <wbr/>Options</span></a></li><li><ul><li><a href="#tlsoptions"><span>Tls<wbr/>Options</span></a></li><li><a href="#jitter"><span>Jitter</span></a></li></ul></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">@nats-io/nats-core</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
|