Skip to content

Commit 96d02ef

Browse files
authored
feat(kernel): consume published @databricks/databricks-sql-kernel napi packages (0.2.0) (#434)
* feat(kernel): consume published @databricks/databricks-sql-kernel napi packages (0.2.0) Declare the eight per-platform kernel binary packages as optionalDependencies pinned to 0.2.0, so a released @databricks/sql pulls the matching native binding from npm on install instead of requiring a local 'npm run build:native'. npm resolves only the package matching the consumer's platform; the rest are skipped (optional), so installs on unsupported platforms keep working with the Thrift backend. Refresh native/kernel/README.md to drop the stale 'M0 / not yet published' note now that all 8 triples are live. Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com> * chore: update package-lock.json for kernel 0.2.0 optional deps Regenerated against public npm so the eight @databricks/databricks-sql-kernel-* 0.2.0 entries carry registry.npmjs.org resolved URLs + integrity, keeping npm ci in sync with package.json. Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com> * test(kernel): real e2e SELECT 1 via useKernel with result fetch Adds a focused live-warehouse e2e that connects with useKernel:true, runs SELECT 1, fetches the row, and asserts the value === 1 — the full DBSQLClient → KernelBackend → napi (npm-installed binding) → warehouse round-trip. Complements execution-e2e.test.ts, which exercises the operation lifecycle but does not read rows. Gated on the pecotesting secrets; skips when absent. Verified passing against a live warehouse on the published kernel 0.2.0 binary. Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com> --------- Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
1 parent 6110300 commit 96d02ef

4 files changed

Lines changed: 297 additions & 25 deletions

File tree

native/kernel/README.md

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,33 +61,36 @@ platform — each containing a single `.node` binary. `native/kernel/index.js`
6161
(the napi-rs router) `require()`s the package matching the consumer's
6262
`process.platform` / `process.arch` at load time.
6363

64-
> **M0 status:** these per-platform packages are **not yet published**, so
65-
> they are intentionally **not** declared in the driver's
66-
> `optionalDependencies`. (npm refuses an `npm ci` against a pinned
67-
> dependency it cannot resolve from the registry, so declaring an
68-
> unpublished package would break every install.) Until they ship, the
69-
> binding is produced locally via `npm run build:native` (which copies
70-
> `index.<triple>.node` into this directory). Once the packages are
71-
> published, add `@databricks/databricks-sql-kernel-<triple>` back to
72-
> `optionalDependencies` — npm then installs only the matching one.
73-
74-
## Supported platforms (M0)
75-
76-
M0 targets a **single** triple: **`linux-x64-gnu`** (package
77-
`@databricks/databricks-sql-kernel-linux-x64-gnu`, once published).
78-
79-
On every other platform (macOS, Windows, linux-arm64, linux-x64-musl
80-
/ Alpine, …) the kernel binding is simply absent: `KernelNativeLoader`
81-
returns `undefined` from `tryGet()` / throws a structured
82-
`MODULE_NOT_FOUND` hint from `get()`, and the driver continues to use
83-
the Thrift backend exclusively. This is expected, not a regression —
84-
additional triples are added to `optionalDependencies` as the kernel
85-
CI starts publishing them in later milestones.
64+
> **Status:** the per-platform packages are published on npm (kernel
65+
> `0.2.0`) and declared in the driver's `optionalDependencies`, pinned to
66+
> that exact version. `npm install` resolves only the package matching the
67+
> consumer's `process.platform` / `process.arch`; the others are skipped
68+
> (that is what `optionalDependencies` tolerates), so installing on an
69+
> unsupported platform does not fail. Local development can still override
70+
> the installed binary with `npm run build:native`, which copies a freshly
71+
> built `index.<triple>.node` into this directory — the router prefers that
72+
> local file over the installed package.
73+
74+
## Supported platforms
75+
76+
The driver declares all eight published triples in `optionalDependencies`:
77+
78+
- `linux-x64-gnu`, `linux-arm64-gnu`
79+
- `linux-x64-musl`, `linux-arm64-musl`
80+
- `darwin-x64`, `darwin-arm64`
81+
- `win32-x64-msvc`, `win32-arm64-msvc`
82+
83+
On any other platform (e.g. linux-arm gnueabihf, riscv64, s390x, FreeBSD)
84+
the kernel binding is simply absent: `KernelNativeLoader` returns
85+
`undefined` from `tryGet()` / throws a structured `MODULE_NOT_FOUND` hint
86+
from `get()`, and the driver continues to use the Thrift backend
87+
exclusively. This is expected, not a regression — additional triples are
88+
added to `optionalDependencies` as the kernel CI starts publishing them.
8689

8790
## Supply-chain note
8891

89-
The unpublished triple names (`@databricks/databricks-sql-kernel-darwin-arm64`,
90-
`…-win32-x64-msvc`, etc.) referenced by the router are **not**
92+
The triple names not yet built/published (`…-linux-arm-gnueabihf`,
93+
`…-riscv64-gnu`, etc.) referenced by the router boilerplate are **not**
9194
squat-able: `@databricks` is a Databricks-owned npm scope, and npm
9295
only allows org members to publish under a scope it owns. A third
9396
party therefore cannot register `@databricks/databricks-sql-kernel-*` and have

package-lock.json

Lines changed: 184 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@
9292
"winston": "^3.8.2"
9393
},
9494
"optionalDependencies": {
95-
"lz4": "^0.6.5"
95+
"lz4": "^0.6.5",
96+
"@databricks/databricks-sql-kernel-linux-x64-gnu": "0.2.0",
97+
"@databricks/databricks-sql-kernel-linux-arm64-gnu": "0.2.0",
98+
"@databricks/databricks-sql-kernel-linux-x64-musl": "0.2.0",
99+
"@databricks/databricks-sql-kernel-linux-arm64-musl": "0.2.0",
100+
"@databricks/databricks-sql-kernel-darwin-x64": "0.2.0",
101+
"@databricks/databricks-sql-kernel-darwin-arm64": "0.2.0",
102+
"@databricks/databricks-sql-kernel-win32-x64-msvc": "0.2.0",
103+
"@databricks/databricks-sql-kernel-win32-arm64-msvc": "0.2.0"
96104
}
97105
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright (c) 2026 Databricks, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import { expect } from 'chai';
16+
import { DBSQLClient } from '../../../lib';
17+
import { ConnectionOptions } from '../../../lib/contracts/IDBSQLClient';
18+
import { InternalConnectionOptions } from '../../../lib/contracts/InternalConnectionOptions';
19+
20+
/**
21+
* Canonical `SELECT 1` round-trip over the kernel backend.
22+
*
23+
* Unlike `execution-e2e.test.ts` (which exercises the operation
24+
* lifecycle but does not read rows), this asserts the full pipeline
25+
* end to end — including result fetch — when the kernel backend is
26+
* selected via `useKernel: true`:
27+
*
28+
* DBSQLClient.connect({ useKernel: true })
29+
* → KernelBackend → napi binding (loaded from the published
30+
* @databricks/databricks-sql-kernel-<triple> optional dependency)
31+
* → live warehouse → inline Arrow result → fetchAll()
32+
*
33+
* This is the smoke test for "the released driver consumes the npm
34+
* kernel package and a query actually returns a value", matching the
35+
* manual verification used to validate the optionalDependencies wiring.
36+
*
37+
* **Gating:** requires the pecotesting secrets exported in the shell.
38+
* If any is missing, the suite is skipped so machines without
39+
* provisioned credentials don't flap.
40+
*/
41+
describe('kernel SELECT 1 end-to-end (result fetch)', function e2eSuite() {
42+
const host = process.env.DATABRICKS_PECOTESTING_SERVER_HOSTNAME;
43+
const path = process.env.DATABRICKS_PECOTESTING_HTTP_PATH;
44+
const token = process.env.DATABRICKS_PECOTESTING_TOKEN_PERSONAL;
45+
46+
// Live-warehouse round-trips can take a few seconds through warm-up.
47+
this.timeout(60_000);
48+
49+
before(function gate() {
50+
if (!host || !path || !token) {
51+
// eslint-disable-next-line no-invalid-this
52+
this.skip();
53+
}
54+
});
55+
56+
it('runs SELECT 1 via useKernel and fetches the row', async () => {
57+
const client = new DBSQLClient();
58+
59+
await client.connect({
60+
host: host as string,
61+
path: path as string,
62+
token: token as string,
63+
useKernel: true,
64+
} as ConnectionOptions & InternalConnectionOptions);
65+
66+
const session = await client.openSession();
67+
const operation = await session.executeStatement('SELECT 1 AS one');
68+
69+
const rows = (await operation.fetchAll()) as Array<Record<string, unknown>>;
70+
expect(rows).to.be.an('array').with.length(1);
71+
expect(Number(rows[0].one)).to.equal(1);
72+
73+
await operation.close();
74+
await session.close();
75+
await client.close();
76+
});
77+
});

0 commit comments

Comments
 (0)