@clickhouse/client 1.18.4 → 1.18.5-head.09b78f0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/config.d.ts +17 -0
  2. package/dist/config.js +1 -0
  3. package/dist/config.js.map +1 -1
  4. package/dist/connection/create_connection.d.ts +2 -1
  5. package/dist/connection/create_connection.js +4 -1
  6. package/dist/connection/create_connection.js.map +1 -1
  7. package/dist/connection/node_base_connection.d.ts +9 -0
  8. package/dist/connection/node_base_connection.js.map +1 -1
  9. package/dist/connection/node_custom_agent_connection.js +3 -0
  10. package/dist/connection/node_custom_agent_connection.js.map +1 -1
  11. package/dist/connection/node_http_connection.js +3 -0
  12. package/dist/connection/node_http_connection.js.map +1 -1
  13. package/dist/connection/node_https_connection.js +3 -0
  14. package/dist/connection/node_https_connection.js.map +1 -1
  15. package/dist/version.d.ts +1 -1
  16. package/dist/version.js +1 -1
  17. package/dist/version.js.map +1 -1
  18. package/package.json +6 -2
  19. package/skills/clickhouse-js-node-coding/SKILL.md +146 -0
  20. package/skills/clickhouse-js-node-coding/evals/evals.json +103 -0
  21. package/skills/clickhouse-js-node-coding/reference/async-insert.md +103 -0
  22. package/skills/clickhouse-js-node-coding/reference/client-configuration.md +159 -0
  23. package/skills/clickhouse-js-node-coding/reference/custom-json.md +149 -0
  24. package/skills/clickhouse-js-node-coding/reference/data-types.md +169 -0
  25. package/skills/clickhouse-js-node-coding/reference/insert-columns.md +113 -0
  26. package/skills/clickhouse-js-node-coding/reference/insert-formats.md +145 -0
  27. package/skills/clickhouse-js-node-coding/reference/insert-values.md +141 -0
  28. package/skills/clickhouse-js-node-coding/reference/ping.md +120 -0
  29. package/skills/clickhouse-js-node-coding/reference/query-parameters.md +152 -0
  30. package/skills/clickhouse-js-node-coding/reference/select-formats.md +111 -0
  31. package/skills/clickhouse-js-node-coding/reference/sessions.md +152 -0
  32. package/skills/clickhouse-js-node-troubleshooting/reference/socket-hangup.md +15 -3
@@ -0,0 +1,152 @@
1
+ # Sessions and Temporary Tables
2
+
3
+ > **Applies to:** all versions. `session_id` is a server-level concept; the
4
+ > client just forwards it on every request that names it.
5
+
6
+ Backing examples:
7
+ [`examples/node/coding/session_id_and_temporary_tables.ts`](https://github.com/ClickHouse/clickhouse-js/blob/main/examples/node/coding/session_id_and_temporary_tables.ts),
8
+ [`examples/node/coding/session_level_commands.ts`](https://github.com/ClickHouse/clickhouse-js/blob/main/examples/node/coding/session_level_commands.ts).
9
+
10
+ ## When you need a session
11
+
12
+ Use a `session_id` whenever multiple calls must share **server-side state**:
13
+
14
+ - `CREATE TEMPORARY TABLE` (the table only exists within its session).
15
+ - `SET <setting> = <value>` to apply for subsequent queries on the same
16
+ session.
17
+ - Any other server feature scoped per session (e.g., session-scoped
18
+ variables in newer ClickHouse versions).
19
+
20
+ ## ⚠️ `session_id` and concurrency
21
+
22
+ ClickHouse **rejects concurrent queries within the same session** — if two
23
+ requests arrive at the server at the same time sharing the same `session_id`,
24
+ the second one gets an error like
25
+ `"Session is locked by a concurrent client"`. This has two practical
26
+ implications:
27
+
28
+ 1. **Do not set `session_id` on a global / module-static client** that handles
29
+ concurrent requests (e.g., an Express app's shared client). Every
30
+ in-flight request would share the same session and collide under load.
31
+ 2. **If you do set `session_id` on a client**, restrict its concurrency:
32
+ set `max_open_connections: 1` so at most one request is in flight at a
33
+ time, turning the pool into a serial queue. This is fine for a
34
+ dedicated per-workflow client but wrong for a shared application client.
35
+
36
+ The right pattern for application code: create a **short-lived client** (or
37
+ use per-request `session_id`) scoped to a single logical workflow, not to
38
+ the entire process.
39
+
40
+ ## Per-client `session_id`
41
+
42
+ Appropriate when **one client handles exactly one sequential workflow** (a
43
+ script, a background job, a single user's session that you've already
44
+ serialized).
45
+
46
+ ```ts
47
+ import { createClient } from '@clickhouse/client'
48
+ import * as crypto from 'node:crypto'
49
+
50
+ const client = createClient({
51
+ session_id: crypto.randomUUID(),
52
+ max_open_connections: 1, // prevent concurrent-session errors
53
+ })
54
+
55
+ await client.command({
56
+ query: 'CREATE TEMPORARY TABLE temporary_example (i Int32)',
57
+ })
58
+
59
+ await client.insert({
60
+ table: 'temporary_example',
61
+ values: [{ i: 42 }, { i: 144 }],
62
+ format: 'JSONEachRow',
63
+ })
64
+
65
+ const rs = await client.query({
66
+ query: 'SELECT * FROM temporary_example',
67
+ format: 'JSONEachRow',
68
+ })
69
+ console.info(await rs.json())
70
+ await client.close()
71
+ ```
72
+
73
+ ## Session-level `SET` commands
74
+
75
+ `SET` only persists within a session. With `session_id` defined on the
76
+ client, every subsequent call inherits the change.
77
+
78
+ ```ts
79
+ import { createClient } from '@clickhouse/client'
80
+ import * as crypto from 'node:crypto'
81
+
82
+ const client = createClient({
83
+ session_id: crypto.randomUUID(),
84
+ max_open_connections: 1, // prevent concurrent-session errors
85
+ })
86
+
87
+ await client.command({
88
+ query: 'SET output_format_json_quote_64bit_integers = 0',
89
+ clickhouse_settings: { wait_end_of_query: 1 }, // ack before next call
90
+ })
91
+
92
+ const rs1 = await client.query({
93
+ query: 'SELECT toInt64(42)',
94
+ format: 'JSONEachRow',
95
+ })
96
+ // → 64-bit integers come back as numbers in this query
97
+
98
+ await client.command({
99
+ query: 'SET output_format_json_quote_64bit_integers = 1',
100
+ clickhouse_settings: { wait_end_of_query: 1 },
101
+ })
102
+
103
+ const rs2 = await client.query({
104
+ query: 'SELECT toInt64(144)',
105
+ format: 'JSONEachRow',
106
+ })
107
+ // → 64-bit integers come back as strings again
108
+
109
+ await client.close()
110
+ ```
111
+
112
+ > **`wait_end_of_query: 1` matters here.** Without it, a `SET` on one
113
+ > connection in the pool may not yet be applied when the next query lands
114
+ > on the same socket.
115
+
116
+ ## Per-request `session_id`
117
+
118
+ You can also pass `session_id` on a single `query()` / `insert()` /
119
+ `command()` call to override (or set) it for that one request.
120
+
121
+ ## ⚠️ Sessions and load balancers / ClickHouse Cloud
122
+
123
+ Sessions are bound to a **specific ClickHouse node**. If a load balancer in
124
+ front of ClickHouse routes consecutive requests to different nodes, the
125
+ temporary table / `SET` won't be visible — you'll get
126
+ `UNKNOWN_TABLE` / surprising results.
127
+
128
+ Mitigations:
129
+
130
+ - Talk to a single node directly.
131
+ - For ClickHouse Cloud, use [replica-aware
132
+ routing](https://clickhouse.com/docs/manage/replica-aware-routing).
133
+ - Avoid sessions for cross-node workflows; persist intermediate state in a
134
+ regular (non-temporary) table instead.
135
+
136
+ ## Common pitfalls
137
+
138
+ - **Forgetting `session_id` and being surprised that
139
+ `CREATE TEMPORARY TABLE` "disappears."** Without a session, every request
140
+ may land on a different connection / server context.
141
+ - **Setting `session_id` on a shared application client.** Under concurrent
142
+ load, two in-flight requests will share the same session and one will fail
143
+ with `"Session is locked by a concurrent client"`. Use per-request
144
+ `session_id` or a dedicated short-lived client instead.
145
+ - **Reusing the same `session_id` across unrelated workflows.** A second
146
+ session-using consumer will trip over your temporary tables and `SET`
147
+ values. Generate a fresh UUID per logical session.
148
+ - **Leaving session state pinned for the lifetime of the process.** If
149
+ long-lived clients accumulate `SET` / temp-table state, consider creating
150
+ a short-lived sub-client with its own `session_id` for the unit of work.
151
+ - **Skipping `wait_end_of_query: 1` on `SET`** — race conditions between
152
+ `SET` and the next query can show up under load.
@@ -113,7 +113,7 @@ const client = createClient({
113
113
 
114
114
  **Node.js defaults to a total received HTTP header limit of approximately 16 KB (this can be increased via the `--max-http-header-size` CLI flag[^max-header-size]).** ClickHouse sends a new progress header with each interval (~200 bytes), and after ~75 progress headers accumulate, Node.js will throw an exception and terminate the request unless that limit is raised.
115
115
 
116
- [^max-header-size]: Node.js also exposes a `maxHeaderSize` option on `http(s).request`, but the ClickHouse JS client currently does not forward it through `createClient`. For now, the practical workaround in clickhouse-js is to either use the `--max-http-header-size` CLI flag / `NODE_OPTIONS` (process-wide) or supply a custom `http.Agent` configured with `maxHeaderSize`. A dedicated client option is coming soon.
116
+ [^max-header-size]: Since `>= 1.18.5`, the ClickHouse JS client also forwards a per-request limit via the `max_response_headers_size` (bytes) option on `createClient` (Node.js only see the example below). On older versions, the practical workarounds are the `--max-http-header-size` CLI flag / `NODE_OPTIONS` (process-wide) or supplying a custom `http.Agent` configured with `maxHeaderSize`.
117
117
 
118
118
  **Maximum safe query duration formula:**
119
119
 
@@ -133,11 +133,23 @@ Max duration (seconds) ≈ http_headers_progress_interval_ms × 75 ÷ 1000
133
133
 
134
134
  If you need a longer max safe duration without lengthening the progress interval, raise Node's HTTP header limit. For example, increasing it from the default 16 KB to **64 KB** quadruples the max safe duration (≈300 progress headers instead of ≈75).
135
135
 
136
+ ```ts
137
+ // Option 1 (recommended, since `>= 1.18.5`) — per-client, no process-wide flag needed
138
+ const client = createClient({
139
+ request_timeout: 400_000,
140
+ max_response_headers_size: 65536, // 64 KB; lifts the per-request header cap
141
+ clickhouse_settings: {
142
+ send_progress_in_http_headers: 1,
143
+ http_headers_progress_interval_ms: '110000',
144
+ },
145
+ })
146
+ ```
147
+
136
148
  ```bash
137
- # Option 1 — CLI flag when launching your app
149
+ # Option 2 — CLI flag when launching your app (process-wide; older client versions)
138
150
  node --max-http-header-size=65536 app.js
139
151
 
140
- # Option 2 — environment variable (works with any Node entry point, including npm/ts-node)
152
+ # Option 3 — environment variable (works with any Node entry point, including npm/ts-node)
141
153
  NODE_OPTIONS="--max-http-header-size=65536" node app.js
142
154
  ```
143
155