Skip to content

Version Packages - #2

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main
Open

Version Packages#2
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

Copy link
Copy Markdown

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@ydbjs/api@7.0.0

Major Changes

  • #638 5d0cc28 Thanks @polRk! - Regenerate the protobuf types with the bridge / multi-pile (2-DC) API: EndpointInfo.bridge_pile_name, ListEndpointsResult.pile_states, NodeLocation.bridge_pile_name, and a new @ydbjs/api/bridge export exposing PileState / PileState_State. Also pick up newer upstream fields in discovery / query / topic / monitoring.

    Breaking: codegen moves to protoc-gen-es 2.12.x (aligned with the @bufbuild/protobuf 2.12 runtime), which honours exactOptionalPropertyTypes: optional message fields are now typed T | undefined instead of T. Consumers compiled with exactOptionalPropertyTypes that mirror generated optional fields into their own optional-typed fields must accept undefined (a type-level break, no behavioural change).

@ydbjs/core@7.0.0

Major Changes

  • #638 807010c Thanks @polRk! - Rebuild Driver's connection layer on a new, internal endpoints engine (a pure @ydbjs/fsm state machine for discovery/routing/health plus an EndpointPool facade with a synchronous, allocation-light acquire() that reads an atomically-swapped immutable RoutingSnapshot), replacing the legacy ConnectionPool. The engine is an implementation detail — consumers only ever hold a Driver — so it is not exported from the package root.

    Driver's public shape is preserved (ready, close, token, database, identity, Disposable/AsyncDisposable, kRegisterLibrary), and createClient gains direct-IO routing:

    • createClient(service) — balanced across all healthy nodes.
    • createClient(service, nodeId) — soft affinity to a node (node-bound query sessions).
    • createClient(service, { nodeId, endpoint?, hard? }) — direct-IO for topic direct read/write: hard: true routes every RPC to nodeId or fails (never substitutes); endpoint pins a server-named node (reachable before the next discovery round, e.g. a topic PartitionLocation). The returned client is Disposable and unpins on dispose.

    Behavioural changes vs the old pool:

    • Balancing is uniform-random within a locality tier (opt-in via 'ydb.sdk.locality_enabled', default off) instead of modulo round-robin, with O(1) node affinity.
    • Pessimization has no fixed timer: a node is pessimized on UNAVAILABLE/DEADLINE_EXCEEDED and recovers on the next successful RPC or discovery round. The ydb:driver.connection.pessimized payload no longer carries until. 'ydb.sdk.connection_pessimization_timeout_ms' is now ignored.
    • Rediscovery adds degradation-triggered forced rounds and single-flight/backoff; each round is bounded by 'ydb.sdk.discovery_timeout_ms' (a timed-out round is retryable, so a hung listEndpoints no longer wedges rediscovery). A retryable initial failure keeps retrying (only a non-retryable error is terminal and emits ydb:driver.failed); a round returning zero endpoints is rejected as a retryable failure in every state — never applied to routing, so a one-round LB glitch cannot wipe the endpoint set.
    • Connections are dialed lazily and a node dropped from discovery is drained rather than torn down (a brief flap no longer forces a reconnect). 'ydb.sdk.connection_idle_timeout_ms' now bounds the grace a retired channel is kept before reaping (no separate idle-active teardown). A graceful shutdown (await using driver / [Symbol.asyncDispose]) drains in-flight streams and returns as soon as they finish, capped by an internal close deadline; the synchronous close() tears everything down immediately.
    • Bridge (2DC) piles: on a bridge cluster, routing is restricted to endpoints whose pile is PRIMARY, PROMOTED, or SYNCHRONIZED (other pile states are kept out of the balancing tiers, used only as a last resort when every pile is unusable). Opt-in 'ydb.sdk.prefer_primary_pile' (default false) additionally keeps traffic on the PRIMARY/PROMOTED pile, falling back to SYNCHRONIZED only when the primary has no available node. It is soft (fallback preserved), a no-op on a non-bridge cluster, and takes precedence over 'ydb.sdk.locality_enabled' in bridge mode (a pile already maps to a datacenter, so the two are not combined).
    • Bridge/pool observability: every ydb:driver.connection.* event now carries the endpoint's pile ('' on a non-bridge cluster), and DriverHooks' EndpointInfo gains a pile field. ydb:driver.discovery.completed additionally carries selfLocation, the pile roster (piles: { name, status }[]), and primaryPile. New channels: ydb:driver.connection.pool.opened (one-shot config snapshot), ydb:driver.connection.pool.stats (aggregate tier/pile counts on every routable-set change), ydb:driver.pile.changed (pile roster/primary change, inside the discovery span), and ydb:driver.pile.fallback (edge-triggered when preferPrimaryPile serves from the SYNCHRONIZED tier).
    • New options: 'ydb.sdk.locality_enabled' (default false), 'ydb.sdk.prefer_primary_pile' (default false), and 'ydb.sdk.discovery_degraded_threshold' (0..1, default 0.5, validated).

    The ConnectionPool class and the POOL_*_FOR_TESTING symbols are removed. All diagnostics_channel channel names and identity-stamped payloads are preserved (minus the until field on connection.pessimized); the round-derived events are published inside the tracing:ydb:driver.discovery span so @ydbjs/telemetry attaches them to traces. EndpointsUnavailableError and the Driver* option/connection-string error classes are re-exported from the package root.

Patch Changes

  • #635 65ba0fd Thanks @polRk! - Fix process crash when a background rediscovery round fails. The periodic discovery loop scheduled its rounds as floating promises, so a terminally failed round (e.g. the discovery endpoint dropping mid-round until the per-round timeout aborted the retries) escalated to an unhandledRejection and killed the process. Failed background rounds are now caught and logged; the connection pool keeps serving last-known endpoints and the next interval tick retries.
  • Updated dependencies [5d0cc28, 6c3dee3]:
    • @ydbjs/api@7.0.0
    • @ydbjs/fsm@7.0.0
    • @ydbjs/auth@6.3.2
    • @ydbjs/error@6.0.7
    • @ydbjs/retry@6.3.1

@ydbjs/fsm@7.0.0

Major Changes

  • #637 6c3dee3 Thanks @YandalfRed! - Rework the runtime around a declarative lifecycle and surface faults to consumers.

    Breaking changes:

    • EffectRuntime no longer exposes close(), destroy(), or ingest() — it is now identical to TransitionRuntime (state, signal, emit, dispatch). Transitions and effect handlers run inside the event-drain loop, so awaiting the machine's own closure from there was a structural promise-cycle deadlock, and closing it mid-drain silently dropped queued outputs.
    • A transition declares termination by returning final: { reason } in its TransitionResult: the machine stops accepting new events immediately, runs that transition's effects (cleanup), drains events already queued, then seals the output stream; reason lands on signal.reason. An effect that hits an unrecoverable error throws — the machine is destroyed and the output iterator rethrows the error.
    • AbstractAsyncQueue.dispose() (from @ydbjs/fsm/queue) is removed — it was a pure alias of destroy(); call destroy() or rely on using ([Symbol.dispose] now calls destroy() directly).

    Fixes and additions:

    • Internal machine faults now reach output consumers. When a transition, effect, or ingest source throws, the runtime still tears the machine down, but its output async-iterator rethrows the stop reason after draining instead of ending silently — so a consumer iterating the machine observes the failure and runs its terminal handling rather than mistaking a fault for a graceful close. The fault is delivered through the output queue via a new AsyncQueue.fail(error) primitive (seals the queue like close(), but the iterator throws error once the buffer drains). The iterator stays a direct queue passthrough — wrapping it in an async generator would add a per-item microtask that reorders delivery for latency-sensitive consumers.
    • New AsyncQueue.take(signal?): a cancellable single-step dequeue with the iterator's exact contract (pause, drain-then-throw after fail()). Aborting removes the parked waiter atomically inside the queue, so a cancelled take() can never swallow an item — unlike racing iterator.next() with a promise combinator, which leaves the underlying next() pending. Compose a bounded wait at the call site with linkSignals(signal, AbortSignal.timeout(ms)).
    • An event dispatched synchronously from within a transition is now processed after the current transition's state change is applied, instead of being run re-entrantly against the stale (pre-transition) state.
    • close() now waits for an in-flight drain to finish and drains any tail before sealing the output stream, so outputs from events queued during that drain are not dropped.

@ydbjs/topic@7.0.0

Major Changes

  • #637 51d3c1b Thanks @YandalfRed! - Rebuild the topic reader on a deterministic @ydbjs/fsm state machine (transport FSM + reader FSM), mirroring the writer. The public TopicReader / TopicTxReader API (read / commit / close / destroy + callbacks) is unchanged; the behaviour is more reliable:

    • commit() no longer rejects on a transparent reconnect. Pending commits are held per partition and re-sent on the new partition session (verified against a live server — YDB accepts a re-sent commit for offsets not read on that session), so a read() + commit() loop survives reconnects instead of crashing.
    • Transactional read offsets are keyed by the stable partition id and survive a reconnect (previously lost, so the transaction could miss offsets).
    • Byte flow-control is charged once per ReadResponse — a response spanning several partitions no longer over-releases credit.
    • Retention gap-fill (committing past retention-deleted offsets) is preserved.
    • read() accumulates a batch up to limit. With batchWindowMs set it yields at least every window (an empty batch on an idle topic, so a polling consumer never hangs); without it, it blocks until the next delivered chunk. The option was renamed from waitMs, which remains as a deprecated alias.
    • On an unrecoverable terminal error read() now throws (instead of ending like a clean end-of-stream); the reader is already torn down, so it is not reusable and every further read() / commit() throws too.
    • Transparent reconnect is now unbounded by default (waits for the server/topic to come back); the new recoveryWindowMs option re-imposes a finite terminal deadline. The new retryOnSchemeError option (off by default) retries SCHEME_ERROR so a reader started before its topic exists waits until it is created. A running reader whose topic is dropped idles until the server closes the stale read stream (~1 min), then transparently reconnects and resumes automatically if the topic exists again (retryOnSchemeError extends this to a topic recreated later).
    • The new gracefulShutdownTimeoutMs option makes the graceful close() deadline configurable (default 30 s): past it, pending commits are dropped and the reader force-closes.
    • Structured lifecycle events on node:diagnostics_channel under ydb:topic.reader.*, plus a tracing:ydb:topic.reader.commit span.
    • TopicTxReader is now AsyncDisposable / Disposable. A manual commit() on a tx reader now throws — the TopicTxReader type never exposed it, but the runtime object did, and a plain-JS call would commit offsets outside the transaction (they would survive its rollback).
    • TopicPartitionSession.nextCommitStartOffset is removed from the public class. It was commit-machinery state that leaked into the public surface in 6.1.x: user-visible (and mutable), while a corrupted anchor produces malformed commit ranges — which are session-fatal server-side. The gap-fill anchor now lives inside the reader state machine, keyed by the stable partition id, so it also survives reconnects (the session object does not).
    • The default maxBufferBytes (server read credit / client-side buffer cap) is now 8 MiB, up from 4 MiB.
  • #637 8eefff2 Thanks @YandalfRed! - Consolidate the topic writer onto a single deterministic @ydbjs/fsm state machine.

    Breaking changes:

    • write() now returns void instead of a sequence number. Obtain the last acknowledged seqNo via flush() (returns bigint) or the onAck callback.
    • flush() now returns bigint (was bigint | undefined).
    • Removed the experimental @ydbjs/topic/writer2 subpath export.
    • Removed the retryConfig writer option. The writer now reconnects transparently (exponential backoff + jitter) and, by default, indefinitely — waiting for the server/topic to come back; the new recoveryWindowMs option re‑imposes a terminal deadline. In‑flight messages are resent and pending writes are not failed by a transparent reconnect.
    • flushIntervalMs default changed from 10ms to 1000ms.
    • close() now rejects when the graceful drain fails (non‑retryable error, or timeout with undelivered messages) instead of resolving silently — this makes transactional commit hooks fail rather than commit with lost writes.

    Fixes and additions:

    • Non‑RAW codecs (GZIP/ZSTD) are compressed once at write() and the compressed bytes are what the buffer accounts and the wire carries.
    • maxBufferBytes is now enforced as a fail‑fast cap: write() throws synchronously when a message would push the un‑acknowledged buffer past the limit (default 256 MB), bounding writer memory.
    • New options: recoveryWindowMs (finite reconnect deadline; unbounded by default), retryOnSchemeError (retry SCHEME_ERROR to wait for a not‑yet‑created topic; off by default), gracefulShutdownTimeoutMs, partitionId / messageGroupId (mutually exclusive), and producer is auto‑generated when omitted.
    • Structured lifecycle events on node:diagnostics_channel under ydb:topic.writer.*.

Patch Changes

  • #638 5d0cc28 Thanks @polRk! - Widen the reader's internal PartitionReadData timestamp fields (writtenAt, createdAt) to Timestamp | undefined to match the stricter optional-field typing from the regenerated @ydbjs/api. No behavioural change.

  • #637 51d3c1b Thanks @YandalfRed! - The built-in ZSTD codec no longer crashes with a bare TypeError on runtimes where node:zlib has no zstd support (Node.js before 22.15 / 23.8). getCodec(Codec.ZSTD) and ZSTD_CODEC now throw an actionable error naming the required Node.js versions, the default reader codec map registers ZSTD only when the runtime supports it, and a reader that receives ZSTD data on an older runtime fails with the register-it-in-codecMap error instead.

  • Updated dependencies [5d0cc28, 807010c, 65ba0fd, 6c3dee3]:

    • @ydbjs/api@7.0.0
    • @ydbjs/core@7.0.0
    • @ydbjs/fsm@7.0.0
    • @ydbjs/error@6.0.7
    • @ydbjs/retry@6.3.1
    • @ydbjs/value@6.0.9

@ydbjs/auth@6.3.2

Patch Changes

  • Updated dependencies [5d0cc28]:
    • @ydbjs/api@7.0.0
    • @ydbjs/error@6.0.7
    • @ydbjs/retry@6.3.1

@ydbjs/coordination@6.2.2

Patch Changes

  • Updated dependencies [5d0cc28, 807010c, 65ba0fd, 6c3dee3]:
    • @ydbjs/api@7.0.0
    • @ydbjs/core@7.0.0
    • @ydbjs/fsm@7.0.0
    • @ydbjs/error@6.0.7
    • @ydbjs/retry@6.3.1

@ydbjs/error@6.0.7

Patch Changes

  • Updated dependencies [5d0cc28]:
    • @ydbjs/api@7.0.0

@ydbjs/query@6.3.1

Patch Changes

  • Updated dependencies [5d0cc28, 807010c, 65ba0fd]:
    • @ydbjs/api@7.0.0
    • @ydbjs/core@7.0.0
    • @ydbjs/error@6.0.7
    • @ydbjs/retry@6.3.1
    • @ydbjs/value@6.0.9

@ydbjs/retry@6.3.1

Patch Changes

  • Updated dependencies [5d0cc28]:
    • @ydbjs/api@7.0.0
    • @ydbjs/error@6.0.7

@ydbjs/telemetry@6.0.2

Patch Changes

  • #638 d5cdb51 Thanks @polRk! - Drop the pessimization.until span-event attribute from the ydb:driver.connection.pessimized subscriber. The endpoints engine in @ydbjs/core no longer emits until (pessimization has no fixed timer), so the subscriber was writing NaN (undefined / 1000) as the attribute value under an active span. The ATTR_YDB_DRIVER_CONNECTION_PESSIMIZATION_UNTIL semconv constant is kept but deprecated.

    Add the ydb.node.pile (ATTR_YDB_NODE_PILE) span-event attribute to every ydb:driver.connection.* mapping, so bridge (2DC) traces show which pile each node belongs to alongside ydb.node.dc. The attribute is omitted on a non-bridge cluster (empty pile name).

  • Updated dependencies [5d0cc28, 807010c, 65ba0fd]:

    • @ydbjs/api@7.0.0
    • @ydbjs/core@7.0.0
    • @ydbjs/error@6.0.7

@ydbjs/value@6.0.9

Patch Changes

  • Updated dependencies [5d0cc28]:
    • @ydbjs/api@7.0.0

@ydbjs/drizzle-adapter@0.1.2

Patch Changes

  • Updated dependencies [5d0cc28, 807010c, 65ba0fd]:
    • @ydbjs/api@7.0.0
    • @ydbjs/core@7.0.0
    • @ydbjs/query@6.3.1
    • @ydbjs/value@6.0.9

@ydbjs/langchain@0.1.1

Patch Changes

  • Updated dependencies [807010c, 65ba0fd]:
    • @ydbjs/core@7.0.0
    • @ydbjs/query@6.3.1
    • @ydbjs/value@6.0.9

@github-actions
github-actions Bot force-pushed the changeset-release/main branch from a92b462 to f4cea7e Compare August 17, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants