blob: 9d1779968cb220da207bceccb53df8d6d160106a [file] [view]
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apache/iggy/refs/heads/master/assets/logo/SVG/iggy-apache-color-darkbg.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/apache/iggy/refs/heads/master/assets/logo/SVG/iggy-apache-color-lightbg.svg">
<img alt="Apache Iggy" src="https://raw.githubusercontent.com/apache/iggy/refs/heads/master/assets/logo/SVG/iggy-apache-color-lightbg.svg" width="320">
</picture>
</div>
# Apache Iggy Node.js Client
Apache Iggy Node.js client written in typescript, it currently only supports tcp & tls transports.
Disclaimer: although all iggy commands & basic client/stream are implemented this is still a WIP, provided as is, and has still a long way to go to be considered "battle tested".
note: This lib started as _iggy-bin_ ( [github](https://github.com/T1B0/iggy-bin) / [npm](https://www.npmjs.com/package/iggy-bin)) before migrating under iggy-rs org. package iggy-bin@v1.3.4 is equivalent to @iggy.rs/sdk@v1.0.3 and migrating again under apache iggy monorepo ( [github](https://github.com/apache/iggy/tree/master/foreign/node) and is now published on npmjs as apache-iggy
note: previous works on node.js http client has been moved to [iggy-node-http-client](<https://github.com/iggy-rs/iggy-node-http-client>) (moved on 04 July 2024)
## install
```bash
npm i --save apache-iggy@edge
```
Use the `edge` package with server 0.9.0 or `edge`. Stable Node SDK 0.8.0 uses the older wire protocol. For a local server with the example credentials, follow the [example setup](../../examples/node/README.md#running-examples).
## basic usage
### Response frame limit
**Compatibility note:** response frames larger than `maxResponseFrameSize` (default 64 MiB) are rejected and close the connection. Raise the limit in the client configuration when polling very large batches.
### VSR framing
The SDK speaks the VSR wire protocol exclusively and requires an Iggy VSR
server:
```typescript
import { SimpleClient, getRawClient } from "apache-iggy";
const config = {
transport: "TCP" as const,
options: { host: "127.0.0.1", port: 8090 },
credentials: { username: "iggy", password: "iggy" },
};
const client = new SimpleClient(getRawClient(config));
const stats = await client.system.getStats();
```
Codes absent from the SDK command table use `Operation::NonReplicated` and
carry the command code in the request header's reserved field. The server
remains authoritative for classifying or rejecting extension commands.
Sends encode `Partitioning.PartitionId`, `Partitioning.Balanced` or
`Partitioning.MessageKey` in the payload. The server resolves the target
partition at admission.
VSR works over TCP and TLS. It restricts `Client` to one pooled connection because authentication, request sequencing, and consumer-group assignments belong to one consensus session. Configurations requesting more than one pooled connection fail before a socket is opened.
VSR authentication translates the existing password and personal-access-token
login APIs into the register handshake required by the consensus protocol. A
disconnect or eviction invalidates the session, and later work must register a
new session. Transient not-committed responses retry the exact encoded request
within one bounded deadline. A disconnected mutation is never replayed under a
new session.
The client pings every `heartbeatInterval` milliseconds, 5000 by default, which
keeps an idle session alive when the server's `[heartbeat]` eviction is enabled.
`heartbeatInterval` also accepts a duration expression such as `"10s"` or
`"1h 30m"`, like the Rust SDK.
With the default heartbeat settings, a group member becomes eligible for
eviction after 36 s of silence (1.2 x the 30 s interval); the verifier checks
once per interval. Raising the client interval past that window, or setting it
to 0 to disable client heartbeats, exposes an idle consumer-group member to
eviction; a connection holding no group membership is left alone. Any other
unusable value is rejected instead of silently disabling the heartbeat.
`sendBinaryRequest(code, payload)` sends an arbitrary command code. Known replicated commands use their registered operation, while unknown codes reach the server as non-replicated requests and are rejected by servers that do not register them.
```typescript
import { ResponseError } from "apache-iggy";
try {
await client.sendBinaryRequest(60_000, Buffer.from("opaque request"));
} catch (error) {
if (error instanceof ResponseError) {
console.error(error.commandCode, error.errorCode);
}
}
```
The client includes its npm package version and the binary protocol crate
version in VSR registration. An incompatible server rejects registration with
a protocol-version error instead of accepting a mismatched wire contract.
```ts
import { Client } from "apache-iggy";
const credentials = { username: "iggy", password: "iggy" };
const client = new Client({
transport: "TCP",
options: { port: 8090, host: "127.0.0.1" },
credentials,
});
const stats = await client.system.getStats();
```
### Connection strings
Every client constructor (except `SimpleClient` see note) also accepts a
connection string instead of a config object:
```ts
import { Client } from "apache-iggy";
const client = new Client("iggy://iggy:iggy@127.0.0.1:8090");
const stats = await client.system.getStats();
```
Supported schemes are `iggy://` (TCP, default) and `iggy+tcp://`. Credentials
are `username:password` or a single personal access token. Options mirror the
other SDKs: `tls`, `tls_domain`, `tls_ca_file`, `reconnection_retries`,
`reconnection_interval`, `heartbeat_interval` and `nodelay`. `reestablish_after`
is accepted for format compatibility but has no Node equivalent.
note: `SimpleClient` does not accept a connection string: it wraps an existing
`RawClient` instance rather than building one from configuration. Pass the
connection string to `Client`, `SingleClient` or `getRawClient` and hand the
resulting raw client to `SimpleClient` if needed.
### option limits
| option | limit |
| --- | --- |
| `reconnection_retries` | integer up to `4294967295` (u32 max); larger values are rejected like Rust's u32 overflow, and `unlimited` maps to this ceiling. Defaults to unlimited |
| `heartbeat_interval` | duration up to `2147483647ms` (Node's largest timer delay); `0` disables heartbeats |
| `reconnection_interval` | positive duration (`ms`, `s`, `m`, `h`) up to `2147483647ms` (Node's largest timer delay); zero spellings are rejected. Defaults to `1s` |
| port in the authority | decimal up to `65535` |
Durations accept the same expressions as the Rust SDK, for example `500ms`,
`10s`, `1h 30m`, `5d`, `2w`, `1y`; matching is case-insensitive and
`0`, `unlimited`, `disabled` and `none` map to zero. Unit-less numbers such as
`5` are rejected.
## use sources
Cluster auto-commit polling over TCP/TLS keeps group membership on the coordinator
and uses separate connections to partition primaries. It requires server support
for binary commands 14, 103 and 104. Pause binary auto-commit consumers for the
whole upgrade: upgrade every server first, then the SDKs, and restart consumers
so they rejoin their groups. Older SDKs can lose membership when a backup refuses
an offset commit; the new SDK does not fall back to legacy polling.
### Install
```bash
npm ci
```
### build
```bash
npm run build
```
### test
note: use env var `IGGY_TCP_ADDRESS="host:port"` to set the server
address for e2e tests. bdd tests need more variables, see below.
#### unit tests
```bash
npm run test:unit
```
#### e2e tests
e2e test expect an iggy-server at tcp://127.0.0.1:8090
```bash
npm run test:e2e
```
#### bdd tests
the bdd suite has no defaults and fails when `IGGY_TCP_ADDRESS`,
`IGGY_ROOT_USERNAME` or `IGGY_ROOT_PASSWORD` is missing. from the repository
root run
```bash
./scripts/run-bdd-tests.sh node
```
the script starts the server and sets every variable, so none of them have to be
exported by hand. to iterate against a server you started yourself, see
[src/bdd/README.md](./src/bdd/README.md).
#### run all test
`npm run test` runs unit, bdd and e2e tests suite against an iggy-server at
tcp://127.0.0.1:8090, started with the same root credentials
```bash
IGGY_TCP_ADDRESS=127.0.0.1:8090 IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
npm run test
```
### lint
```bash
npm run lint
```