Paired with o2-enterprise `hf/issue-2491-admission-slot-leak` (same branch name). **Stacked on #13953** — base is that branch, so the diff here is just this change. Retargets to `main` automatically once #13953 merges. ## Problem #13953 fixed the wal file locks. `do_get` touches two more trace-id keyed resources, and both had the identical defect: release depended on control flow reaching a call, inside the window where gRPC cancellation drops the future. **The node's admission slot.** Released from three hand-written sites — the two error arms in `do_get` and `FlightEncoderStream::drop`. All three are skipped when the request is cancelled during plan generation, because the encoder stream does not exist yet. **The follower task status.** In the super-cluster path the entry was inserted before plan generation and removed after it: ```rust if is_super_cluster && !SEARCH_SERVER.contain_key(&trace_id).await { SEARCH_SERVER.insert(trace_id.clone(), TaskStatus::new_follower(vec![], false)).await; } let result = get_ctx_and_physical_plan(&trace_id, &req).await; // <-- cancellable if is_super_cluster && !SEARCH_SERVER.is_leader(&trace_id).await { SEARCH_SERVER.remove(&trace_id, false).await; } ``` Cancel in the middle and the entry stays in the map for the life of the process. Nothing else removes it: an explicit `cancel_query` would, but a timeout or a client disconnect would not. ## Approach Both move onto the same ownership chain #13953 established. `SessionGuard` — already armed on the first line of `do_get` and already carried into `FlightEncoderStream` — now releases the admission slot too, so the three call sites collapse into its drop. The follower task status is registered through an `AsyncDefer` that lives in the same scope as plan generation, so it is removed on every exit including a cancelled one. It is now removed only when this node registered it, rather than whenever the entry is not a leader's: a request can no longer clear an entry it did not create. In practice these coincide, since the composite `{trace_id}-{job_id}` is unique per request. ### Drive-by The `physical plan generate error` and `physical plan execution error` logs sat *inside* `if get_o2_config().work_group.max_nodes_per_query > 0`, so a plan failure was silent unless work groups happened to be configured — and silent in every OSS build. They are unconditional now. ## Enterprise side The paired PR gives `Running` reservations a TTL backstop. They had no expiry edge at all, so a slot whose release was lost — this cancellation path, or a leader that dies before sending `Release` — was held until the process restarted. This PR closes the local path; the backstop covers the remote one, which no local guard can. ## Verification - `cargo fmt --all` and the CI clippy command: clean - Enterprise verified via the `Cargo.toml.openobserve` swap against the paired branch: `cargo check --all-targets` clean, and `cargo clippy --no-deps -p openobserve-api-grpc --all-targets` clean. The workspace-wide enterprise clippy still reports the two pre-existing `cognitive_complexity` errors in `core/src/alerts/scheduler/handlers.rs` and `core/src/ofga/mod.rs`, untouched by this change - `api-grpc` flight tests 21/21 ## Also here Three zh-CN strings whose English is *events* said 活动 (activity). Unrelated to the rest of the PR, carried along at review request. | key | en-US | was | now | |---|---|---|---| | `home.docsCountLbl` | Events | 活动 | 事件 | | `rum.searchEvents` | Search Events | 搜索活动 | 搜索事件 | | `logs.noEvents.title` | No events found | 未找到任何活动 | 未找到任何事件 | zh-TW already had 事件 for all three, and every other locale translates them as events. `logs.noEvents` also contradicted itself — `descNoFilters` directly below the title already said 未找到任何事件. ## Not in this PR The `QueryManager` map has a `created_at` on every entry but no reaper. With this change its entries are removed on cancellation, so it is no longer known to grow — but it has no backstop the way the ledger now does.
web
This template should help get you started developing with Vue 3 in Vite.
Recommended IDE Setup
VSCode + Volar (and disable Vetur) + TypeScript Vue Plugin (Volar).
Type Support for .vue Imports in TS
TypeScript cannot handle type information for .vue imports by default, so we replace the tsc CLI with vue-tsc for type checking. In editors, we need TypeScript Vue Plugin (Volar) to make the TypeScript language service aware of .vue types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a Take Over Mode that is more performant. You can enable it by the following steps:
- Disable the built-in TypeScript Extension
- Run
Extensions: Show Built-in Extensionsfrom VSCode's command palette - Find
TypeScript and JavaScript Language Features, right click and selectDisable (Workspace)
- Run
- Reload the VSCode window by running
Developer: Reload Windowfrom the command palette.
Customize configuration
See Vite Configuration Reference.
Project Setup
npm install
Compile and Hot-Reload for Development
For stand-alone UI development environment, create .env file and which contains below environment variable
VITE_OPENOBSERVE_ENDPOINT=http://localhost:5080/
npm run dev
Type-Check, Compile and Minify for Production
npm run build
Run Unit Tests with Vitest
npm run test:unit
Run End-to-End Tests with Cypress
npm run test:e2e:dev
This runs the end-to-end tests against the Vite development server. It is much faster than the production build.
But it's still recommended to test the production build with test:e2e before deploying (e.g. in CI environments):
npm run build
npm run test:e2e
Lint with ESLint
npm run lint