blob: 12776f7d6f24d689098400c51c8d378f6133843e [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.
Transport loss clears local authentication but retains the logical session and
its bind proof. Login with the same credentials first tries to bind that session;
a confirmed ended session requires a new registration. Logout forgets the local
session. Transient not-committed responses retry the exact encoded request within
one bounded deadline. A disconnected mutation is never replayed under a new session.
An established session has its own lifetime. Password or PAT changes and PAT
expiry do not end it. Logout, session lease expiry, or user deactivation end the
session and prevent its bind proof from restoring it.
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 wire protocol
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 15 (`BindSession`), 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
```