You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+23-3Lines changed: 23 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,28 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
8
8
9
9
- Fix an unbounded connection/heap leak in node discovery when the cluster has a dedicated cluster manager (`cluster_manager` role with no work roles). The node was filtered out of the `allConns` inventory while the router received the unfiltered added/removed diffs, so `findConnectionByURL` never matched it: a new `*Connection` was created every discovery cycle and the stale one was never evicted, accumulating without bound in the round-robin fallback pool whose `checkDead` health checks repopulated a per-connection `poolRegistry` `sync.Map` each cycle (leak rate scaled with discovery frequency). `allConns` is now the full connection inventory so discovery reuses and evicts symmetrically, and dedicated cluster managers are excluded at request-routing selection instead: `RoundRobinPolicy` skips them in its `DiscoveryUpdate` add path and `multiServerPool.Next()` skips them during selection (including the no-router fallback), both gated on `IncludeDedicatedClusterManagers`. Discovery still bootstraps against a dedicated cluster manager seed via the seed-fallback pool ([#1003](https://github.com/opensearch-project/opensearch-go/pull/1003))
10
10
11
+
## [4.7.2]
12
+
13
+
### Fixed
14
+
15
+
- Fix data races on `multiServerPool` lock-guarded fields: `activeListCap`, `warmupRounds`, `warmupSkipCount`, and `healthCheck` were de-facto guarded by `cp.mu` but declared at the top level of the struct, allowing accesses from `snapshot()`, `createOrUpdateMultiNodePoolWithLock`, and `updateConnectionPool` to escape the lock without looking wrong. All four fields are now nested inside the `mu` embedded struct so every access is spelled `cp.mu.<field>` and the guard is structural. `snapshot()` reads `activeListCap` under the read lock; `createOrUpdateMultiNodePoolWithLock` runs fully under `allConnsPool.mu` with per-connection `conn.mu` taken inside the loop; `updateConnectionPool`'s RTT-probe scheduling loop reads `healthCheck` under the read lock. `recalculateWarmupParams`/`getWarmupParams` renamed `*WithLock` to document that all callers now hold the pool lock ([#995](https://github.com/opensearch-project/opensearch-go/pull/995))
16
+
- Fix removed `opensearch.BuildRequest` reference in v4 upgrade guide ([#978](https://github.com/opensearch-project/opensearch-go/pull/978))
17
+
18
+
### Dependencies
19
+
20
+
- Bump `actions/setup-go` to 7.0.0 and `actions/setup-java` to 5.6.0 ([#993](https://github.com/opensearch-project/opensearch-go/pull/993))
21
+
22
+
## [4.7.1]
23
+
24
+
### Changed
25
+
26
+
- Add a first-class container-provider abstraction to the test harness `Makefile`. `CONTAINER_PROVIDER` is auto-detected by CLI presence in the order Colima -> Rancher Desktop (`rdctl`) -> Docker, and overridable with `CONTAINER_PROVIDER=colima|rancher|docker`. Selecting a provider pins the docker context (`colima` / `rancher-desktop`; the Docker provider leaves the active context alone, and a pre-set `DOCKER_CONTEXT` in the environment is respected), resolves the CLI runtime `$(CTR)` (now `docker` by default for every provider, with `CONTAINER_RUNTIME=nerdctl` as an advanced override), ensures the backing VM/daemon is running via the new `cluster.provider.ensure` target (wired into `cluster.start`), and sets `vm.max_map_count` through the provider's VM (`colima ssh` / `rdctl shell`) or a privileged helper container. Previously `$(CTR)` preferred `nerdctl` whenever it was on `PATH`, so a Rancher-installed `nerdctl` could hijack a Colima session. `make cluster.runtime` now reports the detected provider, docker context, and runtime ([#968](https://github.com/opensearch-project/opensearch-go/pull/968))
27
+
28
+
### Fixed
29
+
30
+
- Fix two gaps in the seed-fallback routing path left by [#952](https://github.com/opensearch-project/opensearch-go/pull/952)/[#954](https://github.com/opensearch-project/opensearch-go/pull/954)/[#956](https://github.com/opensearch-project/opensearch-go/pull/956): `RoundRobinPolicy.Eval` went straight to `pool.Next()` without checking its own `psEnabled` bit (unlike `CoordinatorPolicy.Eval` and `RolePolicy.Eval`), so a dead but unverified discovered node was returned as a zombie producing a transport error — not `ErrNoConnections` — and the seed fallback never fired; `PolicyChain.Eval` also did not gate on `IsEnabled()` even though `PolicyChain.Route` did, leaving the nested chain inside `IfEnabledPolicy.Eval` unguarded. Both gaps are now closed: `RoundRobinPolicy.Eval` returns no connection when its enabled bit is clear, and `PolicyChain.Eval` skips not-enabled sub-policies, matching the behavior of every other leaf policy and `Route` ([#966](https://github.com/opensearch-project/opensearch-go/pull/966))
31
+
- Fix node discovery serving unverified discovered nodes as last-resort zombies and bypassing the seed-URL fallback when `publish_address` is unroutable from the client (NAT'd clusters, Kubernetes stack clusters in CI). `multiServerPool.nextFallbackWithLock` previously returned any dead connection unconditionally; a never-health-checked discovered node was handed out and failed with a transport error (`connection reset by peer` / `no route to host`), which is not `ErrNoConnections` so the seed fallback never fired. Introduce `lcViable`, a monotonic lifecycle bit meaning "proven directly reachable at least once" — seeds are born viable; discovered nodes earn it on their first successful health check or request. `availableForRouting()` now gates on `lcViable` so a dead list holding only never-verified discovered nodes yields `ErrNoConnections` and the request cascades to the seed-URL fallback ([#973](https://github.com/opensearch-project/opensearch-go/pull/973))
32
+
11
33
## [4.7.0]
12
34
13
35
### Added
@@ -172,7 +194,6 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
172
194
173
195
### Changed
174
196
175
-
- Add a first-class container-provider abstraction to the test harness `Makefile`. `CONTAINER_PROVIDER` is auto-detected by CLI presence in the order Colima -> Rancher Desktop (`rdctl`) -> Docker, and overridable with `CONTAINER_PROVIDER=colima|rancher|docker`. Selecting a provider pins the docker context (`colima` / `rancher-desktop`; the Docker provider leaves the active context alone, and a pre-set `DOCKER_CONTEXT` in the environment is respected), resolves the CLI runtime `$(CTR)` (now `docker` by default for every provider, with `CONTAINER_RUNTIME=nerdctl` as an advanced override), ensures the backing VM/daemon is running via the new `cluster.provider.ensure` target (wired into `cluster.start`), and sets `vm.max_map_count` through the provider's VM (`colima ssh` / `rdctl shell`) or a privileged helper container. Previously `$(CTR)` preferred `nerdctl` whenever it was on `PATH`, so a Rancher-installed `nerdctl` could hijack a Colima session. `make cluster.runtime` now reports the detected provider, docker context, and runtime
176
197
- Connection dead/overloaded timestamps (`deadSince`/`overloadedAt`) are now lock-free `atomic.Int64` values. `buildConnectionMetric` no longer locks each connection to read them, removing the dominant metrics-snapshot lock contention against the per-request writers. No public API change; `EnableMetrics` behavior is unchanged. ([#892](https://github.com/opensearch-project/opensearch-go/issues/892))
177
198
- Per-request transport metrics (`requests`, `failures`, responses-by-status) are now always collected via lock-free atomics, independent of `EnableMetrics`. `EnableMetrics` now gates only the detailed-metrics snapshot (per-connection, per-policy, and router state returned by `Metrics()`). The responses-by-status counter moved from a mutex-guarded map to a lock-free atomic array. `Metrics()` no longer returns an error when metrics are disabled — it always returns the per-request counters (callers that branched on `if err != nil` for the disabled case should drop that check). ([#891](https://github.com/opensearch-project/opensearch-go/issues/891))
178
199
-**BREAKING**: `opensearch.Request` interface signature changed from `GetRequest() (*http.Request, error)` to `GetRequest(method string) (*http.Request, error)`. The HTTP method is now caller-provided rather than hardcoded per operation, enabling correct method selection for operations that support multiple HTTP methods (e.g. search supports both GET and POST). This only affects code that implements or calls `GetRequest` directly; standard usage through client methods (e.g. `client.Search(ctx, req)`) is unaffected ([#650](https://github.com/opensearch-project/opensearch-go/issues/650))
@@ -221,9 +242,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
221
242
222
243
### Fixed
223
244
224
-
- Fix a data race on the multi-server pool's warmup fields in the node-discovery path: `createOrUpdateMultiNodePoolWithLock` recalculated warmup parameters, partitioned the ready list, and wrote `mu.activeCount` after releasing the pool write lock, touching `mu`-guarded fields (`activeListCap`, `warmupRounds`, `warmupSkipCount`, `activeCount`) that `resurrectWithLock` reads and writes under `pool.mu`. The caller holds the transport lock, which serializes this against `metrics.snapshot()` but not against resurrection. The whole section now runs under `allConnsPool.mu`, with per-connection `conn.mu` taken inside the loop (the `pool.mu` -> `conn.mu` ordering already used by `deferredStandbyPromotion`). `recalculateWarmupParams`/`getWarmupParams` are renamed `*WithLock` to document that every caller now holds the pool lock (the discovery path was the last that did not)
225
245
- Fix node discovery hijacking the request stream with unverified, unreachable discovered nodes and masking the user-supplied seed-URL fallback. When discovered `publish_address` values are unroutable from the client (NAT'd or misconfigured clusters, e.g. a Kubernetes stack cluster in CI), a freshly discovered but never-health-checked node could be served to requests as a zombie -- failing every request with `no route to host` -- instead of returning `ErrNoConnections` and cascading to the reachable seed URL. Connections are now considered available for routing only when they are a user-supplied seed (assumed reachable) or a discovered node confirmed reachable, and every routing policy and pool (round-robin, role, coordinator, index/doc router, single-server, and multi-server pools) consistently honors that gate on both the enabled-bit and connection-selection paths, so the seed fallback serves requests until a discovered node health-checks clean ([#952](https://github.com/opensearch-project/opensearch-go/pull/952), [#954](https://github.com/opensearch-project/opensearch-go/pull/954), [#956](https://github.com/opensearch-project/opensearch-go/pull/956))
226
-
- Fix a data race (reported by the race detector in `TestClientCustomTransport`) between `multiServerPool.snapshot()` and node discovery: `snapshot()` read `activeListCap` after releasing the pool read lock, while `recalculateWarmupParams` writes it under the write lock during `DiscoveryUpdate`. `activeListCap`, `warmupRounds`, and `warmupSkipCount` were guarded by the pool lock only by convention (declared at the top level of the struct), which let the unlocked read look correct; they are now nested inside the pool's lock-guarded `mu` struct so every access is spelled `cp.mu.<field>` and the guard is structural, and `snapshot()` reads `activeListCap` while holding the read lock. For the same reason `healthCheck` is moved under `mu` (it is rewritten by `updateConnectionPool` on pool reuse); this also surfaced one discovery-path read of `healthCheck` that had escaped the lock, now taken under the read lock
227
246
- Fix `BulkIndexerStats.NumAdded` overcounting items rejected by `Add()` when the caller's context is cancelled before the item could be enqueued: increment `NumAdded` only after the queue accepts the item, and add a new `BulkAddFailCount` counter for items dropped on the `<-ctx.Done()` branch. Migrate `bulkIndexerStats` fields to `sync/atomic.Uint64` typed values so future direct access is a compile-time error rather than a `-race`-only finding ([#783](https://github.com/opensearch-project/opensearch-go/issues/783))
228
247
- Fix `opensearchtransport.Client.setReqGlobalHeader` comparing the per-request header value against the global header name, so a request-level header never suppressed the matching global default and both were sent ([#859](https://github.com/opensearch-project/opensearch-go/pull/859))
229
248
- Fix gzip buffer-pool nil poisoning on compress error: `gzipCompressor.compress` returned `(nil, err)` while the caller's deferred `collectBuffer` still ran, putting a typed-nil `*bytes.Buffer` into the `sync.Pool` that panics on the next `Get().Reset()` ([#859](https://github.com/opensearch-project/opensearch-go/pull/859))
@@ -662,6 +681,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
0 commit comments