Skip to content

Commit

Permalink
Add pathname config option, revert readonly switch/default settings (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
slvrtrn committed Mar 29, 2024
1 parent 08f4739 commit 459a40b
Show file tree
Hide file tree
Showing 19 changed files with 778 additions and 346 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ jobs:
run: |
npm install
- name: Install dependencies (examples)
working-directory: examples
run: |
npm install
- name: Run linting
run: |
npm run lint
Expand Down
67 changes: 24 additions & 43 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# 1.0.0 (Common, Node.js, Web)

Formal stable release milestone with a lot of improvements and a fair bit of breaking changes.
Formal stable release milestone with a lot of improvements and some [breaking changes](#breaking-changes-in-100).

The client will follow the [official semantic versioning](https://docs.npmjs.com/about-semantic-versioning) guidelines.
Major new features overview:

- [Advanced TypeScript support for `query` + `ResultSet`](#advanced-typescript-support-for-query--resultset)
- [URL configuration](#url-configuration)

From now on, the client will follow the [official semantic versioning](https://docs.npmjs.com/about-semantic-versioning) guidelines.

## Deprecated API

Expand All @@ -17,44 +22,14 @@ These parameters will be removed in the next major release (2.0.0).

See "New features" section for more details.

## Breaking changes

- `request_timeout` default value was incorrectly set to 300s instead of 30s. It is now correctly set to 30s by default. If your code relies on the previous incorrect default value, consider setting it explicitly.
- Client will enable [send_progress_in_http_headers](https://clickhouse.com/docs/en/operations/settings/settings#send_progress_in_http_headers) and set `http_headers_progress_interval_ms` to `20000` (20 seconds) by default. These settings in combination allow to avoid potential load balancer timeout issues in case of long-running queries without data coming in or out, such as `INSERT FROM SELECT` and similar ones, as the connection could be marked as idle by the LB and closed abruptly. In that case, a `socket hang up` error could be thrown on the client side. Currently, 20s is chosen as a safe value, since most LBs will have at least 30s of idle timeout; this is also in line with the default [AWS LB KeepAlive interval](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#connection-idle-timeout), which is 20s by default. It can be overridden when creating a client instance if your LB timeout value is even lower than that by manually changing the `clickhouse_settings.http_headers_progress_interval_ms` value.

NB: these settings will be enabled only if the client instance was created without setting `readonly` flag (see below).

- It is now possible to create a client in read-only mode, which will disable default compression and aforementioned ClickHouse HTTP settings. Previously, if you wanted to use the client with a user created with `READONLY = 1` mode, the response compression had to be disabled explicitly.

Pre 1.0.0:

```ts
const client = createClient({
compression: {
response: false,
},
})
```

With `send_progress_in_http_headers` and `http_headers_progress_interval_ms` settings now enabled by default, this is no longer sufficient. If you need to create a client instance for a read-only user, consider this instead:

```ts
// 1.0.0
const client = createClient({
readonly: true,
})
```

By default, `readonly` is `false`.

NB: this is not necessary if a user has `READONLY = 2` mode as it allows to modify the settings, so the client can be used without an additional `readonly` setting.

See also: [readonly documentation](https://clickhouse.com/docs/en/operations/settings/permissions-for-queries#readonly).
## Breaking changes in 1.0.0

- `compression.response` is now disabled by default in the client configuration options, as it cannot be used with readonly=1 users, and it was not clear from the ClickHouse error message what exact client option was causing the failing query in this case. If you'd like to continue using response compression, you should explicitly enable it in the client configuration.
- As the client now supports parsing [URL configuration](#url-configuration), you should specify `pathname` as a separate configuration option (as it would be considered as the `database` otherwise).
- (TypeScript only) `ResultSet` and `Row` are now more strictly typed, according to the format used during the `query` call. See [this section](#advanced-typescript-support-for-query--resultset) for more details.
- (TypeScript only) Both Node.js and Web versions now uniformly export correct `ClickHouseClient` and `ClickHouseClientConfigOptions` types, specific to each implementation. Exported `ClickHouseClient` now does not have a `Stream` type parameter, as it was unintended to expose it there. NB: you should still use `createClient` factory function provided in the package.

## New features
## New features in 1.0.0

### Advanced TypeScript support for `query` + `ResultSet`

Expand All @@ -71,7 +46,7 @@ Complete reference:
| JSON | ResponseJSON\<T\> | never | never | never |
| JSONObjectEachRow | Record\<string, T\> | never | never | never |
| All other JSON\*EachRow | Array\<T\> | Stream\<Array\<Row\<T\>\>\> | Array\<Row\<T\>\> | T |
| CSV/TSV/CustomSeparated/Parquet | never | Stream\<Array\<Row\<?\>\>\> | Array\<Row\<?\>\> | never |
| CSV/TSV/CustomSeparated/Parquet | never | Stream\<Array\<Row\<T\>\>\> | Array\<Row\<T\>\> | never |

By default, `T` (which represents `JSONType`) is still `unknown`. However, considering `JSONObjectsEachRow` example: prior to 1.0.0, you had to specify the entire type hint, including the shape of the data, manually:

Expand Down Expand Up @@ -155,7 +130,7 @@ const resultSet = await client.query('SELECT * FROM table', {
const json = resultSet.json()
```

There is one currently known limitation: as the general shape of the data and the methods allowed for calling are inferred from the format literal, there might be situations where it will fail to do so, for example:
Currently, there is one known limitation: as the general shape of the data and the methods allowed for calling are inferred from the format literal, there might be situations where it will fail to do so, for example:

```ts
// assuming that `queryParams` has `JSONObjectsEachRow` format inside
Expand All @@ -164,6 +139,7 @@ async function runQuery(
): Promise<Record<string, Data>> {
const resultSet = await client.query(queryParams)
// type hint here will provide a union of all known shapes instead of a specific one
// inferred shapes: Data[] | ResponseJSON<Data> | Record<string, Data>
return resultSet.json<Data>()
}
```
Expand All @@ -178,23 +154,26 @@ async function runQuery(
...queryParams,
format: 'JSONObjectsEachRow',
})
return resultSet.json<Data>() // TS understands that it is a Record<string, Data> now
// TS understands that it is a Record<string, Data> now
return resultSet.json<Data>()
}
```

If you are interested in more details, see the [related test](./packages/client-node/__tests__/integration/node_query_format_types.test.ts) (featuring a great ESLint plugin [expect-types](https://github.com/JoshuaKGoldberg/eslint-plugin-expect-type)) in the client package.

### URL configuration

- Added `url` configuration parameter. It is intended to replace the deprecated `host`, which was already supposed to be passed as a valid URL.
- It is now possible to configure most of the client instance parameters with a URL. The URL format is `http[s]://[username:password@]hostname:port[/database][?param1=value1&param2=value2]`. In almost every case, the name of a particular parameter reflects its path in the config options interface, with a few exceptions. The following parameters are supported:

| Parameter | Type |
| ------------------------------------------- | ----------------------------------------------------------------- |
| `readonly` | boolean. See below [1]. |
| `application_id` | non-empty string. |
| `session_id` | non-empty string. |
| `pathname` | an arbitrary string. |
| `application_id` | an arbitrary string. |
| `session_id` | an arbitrary string. |
| `request_timeout` | non-negative number. |
| `max_open_connections` | non-negative number, greater than zero. |
| `compression_request` | boolean. |
| `compression_request` | boolean. See below [1]. |
| `compression_response` | boolean. |
| `log_level` | allowed values: `OFF`, `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`. |
| `keep_alive_enabled` | boolean. |
Expand All @@ -215,6 +194,8 @@ createClient({
})
```

Note: boolean values for `clickhouse_settings` should be passed as `1`/`0` in the URL.

[3] Similar to [2], but for `http_header` configuration. For example, `?http_header_x-clickhouse-auth=foobar` will be an equivalent of:

```ts
Expand Down
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ Node.JS-specific examples are located in the `examples/node` directory.

We aim to cover various scenarios of client usage with these examples. You should be able to run any of these examples, see [How to run](#how-to-run) section below.

If something is missing, or you found a mistake in one of these examples, please open an issue or a pull request, or [contact us](../README.md#contact-us).

#### General usage

- [url_configuration.ts](url_configuration.ts) - client configuration using the URL parameters.
- [clickhouse_settings.ts](clickhouse_settings.ts) - ClickHouse settings on the client side, both global and per operation.
- [ping.ts](ping.ts) - sample checks if the server can be reached.
- [abort_request.ts](abort_request.ts) - cancelling an outgoing request or a read-only query.
- [cancel_query.ts](cancel_query.ts) - cancelling a potentially long-running query on the server side.
- [long_running_queries_timeouts.ts](long_running_queries_timeouts.ts) - avoiding timeout errors for long-running queries (two different approaches).
- [read_only_user.ts](read_only_user.ts) - an example of using the client with a read-only user, with possible read-only user limitations highlights.
- [basic_tls.ts](node/basic_tls.ts) - (Node.js only) using certificates for basic TLS authentication.
- [mutual_tls.ts](node/mutual_tls.ts) - (Node.js only) using certificates for mutual TLS authentication.
Expand Down
Loading

0 comments on commit 459a40b

Please sign in to comment.