Skip to content

Commit

Permalink
Breaking changes: refactor Rows for better streaming performance (#109)
Browse files Browse the repository at this point in the history
- split2 moved to dev dependencies only (we can rewrite affected tests and examples later)
- use self-written Transform to push Row instances in bulk
- (breaking) Rows renamed to ResultSet
- (breaking) every stream iteration now provides Row[] instead of Row, just as it is returned from CH
  • Loading branch information
slvrtrn authored Oct 4, 2022
1 parent 1977fa4 commit c86c31d
Show file tree
Hide file tree
Showing 22 changed files with 363 additions and 280 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,12 @@ class ClickHouseClient {
}
```

#### Rows response abstraction
#### ResultSet response abstraction

Provides several convenience methods for data processing in your application.
Provides several convenience methods for data processing of select results in your application.

```ts
class Rows {
class ResultSet {
// Consume the entire stream and get the contents as a string
// Can be used with any DataFormat
// Should be called only once
Expand All @@ -268,17 +268,18 @@ class Rows {
// Can be used only with JSON formats
// Should be called only once
json<T>(): Promise<T> {}
// Returns a readable stream of Row instances for responses that can be streamed (i.e. all except JSON)
// Returns a readable stream for responses that can be streamed (i.e. all except JSON)
// Every iteration provides an array of `Row` instances
// Should be called only once
// NB: if called for the second time, the second stream will be just empty
stream(): Stream.Readable {}
}

class Row {
// Get the content of the row as plain string
text(): string {}
// Get the content of the row as a JS object
json<T>(): T {}
interface Row {
// Get the content of an individual row as a plain string
text(): string
// Get the content of an individual row as a JS object
json<T>(): T
}
```

Expand Down Expand Up @@ -368,7 +369,7 @@ class ClickHouseClient {

## Usage examples

You can find code samples in the [examples](./examples) folder.
You can find code samples in the [examples](./examples) folder (with [README](./examples/README.md)).

See also:

Expand Down
19 changes: 11 additions & 8 deletions __tests__/integration/abort_request.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AbortController } from 'node-abort-controller'
import type { Row } from '../../src'
import { type ClickHouseClient, type ResponseJSON } from '../../src'
import { createTestClient, guid, makeObjectStream } from '../utils'
import { createSimpleTable } from './fixtures/simple_table'
Expand Down Expand Up @@ -85,12 +86,14 @@ describe('abort request', () => {
})
.then(async function (rows) {
const stream = rows.stream()
for await (const chunk of stream) {
const [[number]] = chunk.json()
// abort when reach number 3
if (number === '3') {
stream.destroy()
}
for await (const rows of stream) {
rows.forEach((row: Row) => {
const [[number]] = row.json<[[string]]>()
// abort when reach number 3
if (number === '3') {
stream.destroy()
}
})
}
})
// There was a breaking change in Node.js 18.x behavior
Expand Down Expand Up @@ -285,12 +288,12 @@ async function assertActiveQueries(
) {
// eslint-disable-next-line no-constant-condition
while (true) {
const rows = await client.query({
const rs = await client.query({
query: 'SELECT query FROM system.processes',
format: 'JSON',
})

const queries = await rows.json<ResponseJSON<{ query: string }>>()
const queries = await rs.json<ResponseJSON<{ query: string }>>()

if (assertQueries(queries.data)) {
break
Expand Down
4 changes: 2 additions & 2 deletions __tests__/integration/insert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ describe('insert', () => {
format: 'JSONEachRow',
})

const Rows = await client.query({
const rs = await client.query({
query: `SELECT * FROM ${tableName}`,
format: 'JSONEachRow',
})

const result = await Rows.json<ResponseJSON>()
const result = await rs.json<ResponseJSON>()
expect(result).toEqual(values)
})

Expand Down
4 changes: 2 additions & 2 deletions __tests__/integration/request_compression.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ describe('insert compression', () => {
values: dataToInsert,
})

const Rows = await client.query({
const rs = await client.query({
query: `SELECT * FROM ${tableName}`,
format: 'JSON',
})

const result = await Rows.json<ResponseJSON>()
const result = await rs.json<ResponseJSON>()
expect(result.data.length).toBe(1_000)
})
})
4 changes: 2 additions & 2 deletions __tests__/integration/response_compression.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('response compression', () => {
},
})

const rows = await client.query({
const rs = await client.query({
query: `
SELECT number
FROM system.numbers
Expand All @@ -23,7 +23,7 @@ describe('response compression', () => {
format: 'JSONEachRow',
})

const response = await rows.json<{ number: string }[]>()
const response = await rs.json<{ number: string }[]>()
const last = response[response.length - 1]
expect(last.number).toBe('19999')
})
Expand Down
Loading

0 comments on commit c86c31d

Please sign in to comment.