Skip to content

Commit

Permalink
refactor: PointValues query, private Point cons
Browse files Browse the repository at this point in the history
  • Loading branch information
Sciator committed Sep 5, 2023
1 parent 3d6ef09 commit 763fea8
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 84 deletions.
4 changes: 2 additions & 2 deletions packages/client/src/InfluxDBClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {ClientOptions, QueryType, WriteOptions} from './options'
import {IllegalArgumentError} from './errors'
import {WritableData, writableDataToLineProtocol} from './util/generics'
import {throwReturn} from './util/common'
import {Point} from './Point'
import {PointValues} from './PointValues'

const argumentErrorMessage = `\
Please specify the 'database' as a method parameter or use default configuration \
Expand Down Expand Up @@ -80,7 +80,7 @@ export default class InfluxDBClient {
database: string,
queryType: QueryType,
measurement: string
): AsyncGenerator<Point, void, void> {
): AsyncGenerator<PointValues, void, void> {
const points = this._queryApi.queryPoints(
query,
database ??
Expand Down
71 changes: 40 additions & 31 deletions packages/client/src/Point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import {TimeConverter} from './WriteApi'
import {convertTimeToNanos, convertTime} from './util/time'
import {escape} from './util/escape'
import {WritePrecision} from './options'
import { PointFieldType, PointValues } from "./PointValues"
import {PointFieldType, PointValues} from './PointValues'

const fieldToLPString: {
(type: 'float', value: number): string,
(type: 'integer', value: number): string,
(type: 'uinteger', value: number): string,
(type: 'string', value: string): string,
(type: 'boolean', value: boolean): string,
(type: PointFieldType, value: number|string|boolean): string,
} = (type: PointFieldType, value: number|string|boolean): string => {
(type: 'float', value: number): string
(type: 'integer', value: number): string
(type: 'uinteger', value: number): string
(type: 'string', value: string): string
(type: 'boolean', value: boolean): string
(type: PointFieldType, value: number | string | boolean): string
} = (type: PointFieldType, value: number | string | boolean): string => {
switch (type) {
case 'string':
return escape.quoted(value as string)
Expand Down Expand Up @@ -46,15 +46,15 @@ export class Point {
*
* @param measurementName - the measurement name
*/
constructor(measurementName: string)
private constructor(measurementName: string)
/**
* Create a new Point with given values.
* After creating Point, it's values shouldn't be modified directly by PointValues object.
*
* @param measurementName - the measurement name
*/
constructor(values: PointValues)
constructor(arg0?: PointValues | string) {
private constructor(values: PointValues)
private constructor(arg0?: PointValues | string) {
if (arg0 instanceof PointValues) {
this._values = arg0
} else {
Expand All @@ -64,6 +64,14 @@ export class Point {
if (typeof arg0 === 'string') this._values.measurement(arg0)
}

public static measurement(name: string): Point {
return new Point(name)
}

public static fromValues(values: PointValues): Point {
return new Point(values)
}

/**
* Sets point's measurement.
*
Expand All @@ -76,7 +84,9 @@ export class Point {
}

public getMeasurement(): string {
return this._values.getMeasurement() as NonNullable<ReturnType<(typeof this._values.getMeasurement)>>
return this._values.getMeasurement() as NonNullable<
ReturnType<typeof this._values.getMeasurement>
>
}

/**
Expand Down Expand Up @@ -140,7 +150,7 @@ export class Point {
throw new Error(`uint value for field '${name}' out of range: ${value}`)
}
this._values.uintField(name, Math.floor(value as number))
} else {
} else {
const strVal = String(value)
for (let i = 0; i < strVal.length; i++) {
const code = strVal.charCodeAt(i)
Expand Down Expand Up @@ -197,8 +207,8 @@ export class Point {
public stringField(name: string, value: string | any): Point {
if (value !== null && value !== undefined) {
if (typeof value !== 'string') value = String(value)
this._values.stringField(name, value)
}
this._values.stringField(name, value)
}
return this
}

Expand Down Expand Up @@ -328,13 +338,14 @@ export class Point {
): string | undefined {
if (!this._values.getMeasurement()) return undefined
let fieldsLine = ''
this._values.getFieldNames()
this._values
.getFieldNames()
.sort()
.forEach((name) => {
if (name) {
const type = this._values.getFieldType(name)
const value = this._values.getField(name)
if (!type || !value) return;
if (type === undefined || value === undefined) return
const lpStringValue = fieldToLPString(type, value)
if (fieldsLine.length > 0) fieldsLine += ','
fieldsLine += `${escape.tag(name)}=${lpStringValue}`
Expand All @@ -343,18 +354,16 @@ export class Point {
if (fieldsLine.length === 0) return undefined // no fields present
let tagsLine = ''
const tagNames = this._values.getTagNames()
tagNames
.sort()
.forEach((x) => {
if (x) {
const val = this._values.getTag(x)
if (val) {
tagsLine += ','
tagsLine += `${escape.tag(x)}=${escape.tag(val)}`
}
tagNames.sort().forEach((x) => {
if (x) {
const val = this._values.getTag(x)
if (val) {
tagsLine += ','
tagsLine += `${escape.tag(x)}=${escape.tag(val)}`
}
})
let time = this._values.getTimestamp();
}
})
let time = this._values.getTimestamp()

if (!convertTimePrecision) {
time = convertTimeToNanos(time)
Expand All @@ -364,9 +373,9 @@ export class Point {
time = convertTimePrecision(time)
}

return `${escape.measurement(this.getMeasurement())}${tagsLine} ${fieldsLine}${
time !== undefined ? ` ${time}` : ''
}`
return `${escape.measurement(
this.getMeasurement()
)}${tagsLine} ${fieldsLine}${time !== undefined ? ` ${time}` : ''}`
}

toString(): string {
Expand Down
12 changes: 7 additions & 5 deletions packages/client/src/PointValues.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Point } from "./Point"
import {Point} from './Point'

export type PointFieldType =
| 'float'
Expand Down Expand Up @@ -72,7 +72,7 @@ export class PointValues {
}

public getTag(name: string): string | undefined {
return this._tags[name];
return this._tags[name]
}

public getTagNames(): string[] {
Expand Down Expand Up @@ -226,7 +226,9 @@ export class PointValues {
* @param value - field value
* @returns this
*/
public fields(fields: {[key: string]: number | boolean | string}): PointValues {
public fields(fields: {
[key: string]: number | boolean | string
}): PointValues {
for (const [name, value] of Object.entries(fields)) {
this.field(name, value)
}
Expand Down Expand Up @@ -318,11 +320,11 @@ export class PointValues {
}

public getTimestamp(): Date | number | string | undefined {
return this._time;
return this._time
}

public asPoint(): Point {
return new Point(this);
return Point.fromValues(this)
}

copy(): PointValues {
Expand Down
6 changes: 3 additions & 3 deletions packages/client/src/QueryApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Point} from './Point'
import {PointValues} from './PointValues'
import {QueryType} from './options'

/**
Expand All @@ -25,13 +25,13 @@ export default interface QueryApi {
* @param query - The query string.
* @param database - The name of the database to query.
* @param queryType - The type of query (default: 'sql').
* @returns An async generator that yields Point object.
* @returns An async generator that yields PointValues object.
*/
queryPoints(
query: string,
database: string,
queryType: QueryType
): AsyncGenerator<Point, void, void>
): AsyncGenerator<PointValues, void, void>

close(): Promise<void>
}
6 changes: 3 additions & 3 deletions packages/client/src/impl/QueryApiImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {ConnectionOptions, QueryType} from '../options'
import {createInt32Uint8Array} from '../util/common'
import {RpcMetadata, RpcOptions} from '@protobuf-ts/runtime-rpc'
import {impl} from './implSelector'
import {Point, PointFieldType} from '../Point'
import {PointFieldType, PointValues} from '../PointValues'

export default class QueryApiImpl implements QueryApi {
private _closed = false
Expand Down Expand Up @@ -86,12 +86,12 @@ export default class QueryApiImpl implements QueryApi {
query: string,
database: string,
queryType: QueryType
): AsyncGenerator<Point, void, void> {
): AsyncGenerator<PointValues, void, void> {
const batches = this._queryRawBatches(query, database, queryType)

for await (const batch of batches) {
for (let rowIndex = 0; rowIndex < batch.numRows; rowIndex++) {
const point = new Point()
const point = new PointValues()
for (let columnIndex = 0; columnIndex < batch.numCols; columnIndex++) {
const columnSchema = batch.schema.fields[columnIndex]
const name = columnSchema.name
Expand Down
5 changes: 3 additions & 2 deletions packages/client/test/integration/e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {expect} from 'chai'
import {InfluxDBClient, Point} from '../../src'
import {rejects} from 'assert'
import {PointValues} from '../../src/PointValues'

const getEnvVariables = () => {
const {
Expand Down Expand Up @@ -42,7 +43,7 @@ describe('e2e test', () => {
const avg1 = getRandomInt(110, 500)
const max1 = getRandomInt(900, 1000)

const point = new Point('stat')
const point = Point.measurement('stat')
.tag('unit', 'temperature')
.floatField('avg', avg1)
.floatField('max', max1)
Expand Down Expand Up @@ -76,7 +77,7 @@ describe('e2e test', () => {

const dataPoints = client.queryPoints(query, database, queryType, 'stat')

let pointRow: IteratorResult<Point, void>
let pointRow: IteratorResult<PointValues, void>
pointRow = await dataPoints.next()

expect(pointRow.done).to.equal(false)
Expand Down
34 changes: 24 additions & 10 deletions packages/client/test/unit/Write.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,16 @@ describe('Write', () => {
await rejects(subject.write('text value=1', DATABASE))
await rejects(subject.write(['text value=1', 'text value=2'], DATABASE))
await rejects(
subject.write(new Point('test').floatField('value', 1), DATABASE)
subject.write(
Point.measurement('test').floatField('value', 1),
DATABASE
)
)
await rejects(
subject.write([new Point('test').floatField('value', 1)], DATABASE)
subject.write(
[Point.measurement('test').floatField('value', 1)],
DATABASE
)
)
})
})
Expand Down Expand Up @@ -129,7 +135,7 @@ describe('Write', () => {
}
})
.persist()
const point = new Point('test')
const point = Point.measurement('test')
.tag('t', ' ')
.floatField('value', 1)
.timestamp('')
Expand All @@ -155,18 +161,20 @@ describe('Write', () => {
requests = 0

// generates no lines, no requests done
await subject.write(new Point(), DATABASE)
await subject.write(Point.measurement('m'), DATABASE)
await subject.write([], DATABASE)
await subject.write('', DATABASE)
expect(requests).to.equal(0)
expect(logs.error).has.length(0)
expect(logs.warn).has.length(0)

const points = [
new Point('test').floatField('value', 1).timestamp('1'),
new Point('test').floatField('value', 2).timestamp(2.1),
new Point('test').floatField('value', 3).timestamp(new Date(3)),
new Point('test')
Point.measurement('test').floatField('value', 1).timestamp('1'),
Point.measurement('test').floatField('value', 2).timestamp(2.1),
Point.measurement('test')
.floatField('value', 3)
.timestamp(new Date(3)),
Point.measurement('test')
.floatField('value', 4)
.timestamp(false as any as string), // server decides what to do with such values
]
Expand Down Expand Up @@ -224,7 +232,10 @@ describe('Write', () => {
return [204, '', {}]
})
.persist()
await subject.write(new Point('test').floatField('value', 1), DATABASE)
await subject.write(
Point.measurement('test').floatField('value', 1),
DATABASE
)
expect(logs.error).has.length(0)
expect(logs.warn).has.length(0)
expect(authorization).equals(`Token customToken`)
Expand All @@ -241,7 +252,10 @@ describe('Write', () => {
return [204, '', {}]
})
.persist()
await subject.write(new Point('test').floatField('value', 1), DATABASE)
await subject.write(
Point.measurement('test').floatField('value', 1),
DATABASE
)
await subject.close()
expect(logs.error).has.length(0)
expect(logs.warn).deep.equals([])
Expand Down
12 changes: 8 additions & 4 deletions packages/client/test/unit/util/generics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('writableDataToLineProtocol', () => {
})

it('should convert single Point to line protocol', () => {
const point = new Point('test').floatField('blah', 123.6)
const point = Point.measurement('test').floatField('blah', 123.6)
const output = writableDataToLineProtocol(point)
expect(output.length).to.equal(1)
expect(output[0]).satisfies((x: string) => {
Expand All @@ -31,10 +31,14 @@ describe('writableDataToLineProtocol', () => {
})

it('should convert array-like Point to line protocol', () => {
const point1 = new Point('test').floatField('blah', 123.6)
const point1 = Point.measurement('test').floatField('blah', 123.6)
const date = Date.now()
const point2 = new Point('test').floatField('blah', 456.7).timestamp(date)
const point3 = new Point('test').floatField('blah', 789.8).timestamp('')
const point2 = Point.measurement('test')
.floatField('blah', 456.7)
.timestamp(date)
const point3 = Point.measurement('test')
.floatField('blah', 789.8)
.timestamp('')
const input: WritableData = [point1, point2, point3]
const output = writableDataToLineProtocol(input)
expect(output.length).to.equal(3)
Expand Down
Loading

0 comments on commit 763fea8

Please sign in to comment.