Skip to content

Commit

Permalink
DATA-3444 Add exportTabularData to data client (#428)
Browse files Browse the repository at this point in the history
  • Loading branch information
katiepeters authored Dec 17, 2024
1 parent e6a453f commit 63c34f7
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 0 deletions.
98 changes: 98 additions & 0 deletions src/app/data-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
DeleteBinaryDataByFilterResponse,
DeleteBinaryDataByIDsResponse,
DeleteTabularDataResponse,
ExportTabularDataRequest,
ExportTabularDataResponse,
Filter,
GetDatabaseConnectionRequest,
GetDatabaseConnectionResponse,
Expand Down Expand Up @@ -102,6 +104,102 @@ describe('DataClient tests', () => {
locationId: 'testLocationId',
});

describe('exportTabularData tests', () => {
const sharedAttributes = {
partId: 'partId1',
resourceName: 'resource1',
resourceSubtype: 'resource1:subtype',
methodName: 'Readings',
organizationId: 'orgId1',
locationId: 'locationId1',
robotName: 'robot1',
robotId: 'robotId1',
partName: 'part1',
tags: [],
};
const timeCaptured1 = new Date(2024, 1, 1);
const timeCaptured2 = new Date(2024, 1, 2);
const tabDataResponse1 = new ExportTabularDataResponse({
...sharedAttributes,
methodParameters: Struct.fromJson({ key: 'param1' }),
timeCaptured: Timestamp.fromDate(timeCaptured1),
payload: Struct.fromJson({ key: 'value1' }),
});
const tabDataResponse2 = new ExportTabularDataResponse({
...sharedAttributes,
methodParameters: Struct.fromJson({ key: 'param2' }),
timeCaptured: Timestamp.fromDate(timeCaptured2),
payload: Struct.fromJson({ key: 'value2' }),
});

let capReq: ExportTabularDataRequest;
beforeEach(() => {
mockTransport = createRouterTransport(({ service }) => {
service(DataService, {
exportTabularData: (req) => ({
[Symbol.asyncIterator]: async function* generateResponses() {
await Promise.resolve();
capReq = req;
yield tabDataResponse1;
yield tabDataResponse2;
},
}),
});
});
});

it('gets tabular data', async () => {
const data = await subject().exportTabularData(
'partId1',
'resource1',
'resource1:subtype',
'Readings'
);

expect(data.length).toEqual(2);

const expectedResponse1 = {
...sharedAttributes,
methodParameters: { key: 'param1' },
timeCaptured: timeCaptured1,
payload: { key: 'value1' },
};
const expectedResponse2 = {
...sharedAttributes,
methodParameters: { key: 'param2' },
timeCaptured: timeCaptured2,
payload: { key: 'value2' },
};

expect(data[0]).toMatchObject(expectedResponse1);
expect(data[1]).toMatchObject(expectedResponse2);
});

it('gets tabular data for an interval', async () => {
await subject().exportTabularData(
'partId1',
'resource1',
'resource1:subtype',
'Readings',
timeCaptured1,
timeCaptured2
);

const expectedRequest = new ExportTabularDataRequest({
partId: 'partId1',
resourceName: 'resource1',
resourceSubtype: 'resource1:subtype',
methodName: 'Readings',
interval: {
start: Timestamp.fromDate(timeCaptured1),
end: Timestamp.fromDate(timeCaptured2),
},
});

expect(capReq).toStrictEqual(expectedRequest);
});
});

describe('tabularDataBySQL tests', () => {
type returnType = JsonValue | Date;
const data: Record<string, returnType>[] = [
Expand Down
80 changes: 80 additions & 0 deletions src/app/data-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ interface TabularData {
timeReceived?: Date;
}

interface TabularDataPoint {
partId: string;
resourceName: string;
resourceSubtype: string;
methodName: string;
timeCaptured: Date | undefined;
organizationId: string;
locationId: string;
robotName: string;
robotId: string;
partName: string;
methodParameters: JsonValue | undefined;
tags: string[];
payload: JsonValue | undefined;
}

export type Dataset = Partial<PBDataset> & {
created?: Date;
};
Expand All @@ -53,6 +69,70 @@ export class DataClient {
this.dataSyncClient = createPromiseClient(DataSyncService, transport);
}

/**
* Obtain unified tabular data and metadata from the specified data source.
*
* @param partId The ID of the part that owns the data
* @param resourceName The name of the requested resource that captured the
* data
* @param resourceSubtype The subtype of the requested resource that captured
* the data
* @param methodName The data capture method name
* @param startTime Optional start time (`Date` object) for requesting a
* specific range of data
* @param endTime Optional end time (`Date` object) for requesting a specific
* range of data
* @returns An array of unified tabular data and metadata.
*/
async exportTabularData(
partId: string,
resourceName: string,
resourceSubtype: string,
methodName: string,
startTime?: Date,
endTime?: Date
) {
const interval = new CaptureInterval();
if (startTime) {
interval.start = Timestamp.fromDate(startTime);
}
if (endTime) {
interval.end = Timestamp.fromDate(endTime);
}

const req = {
partId,
resourceName,
resourceSubtype,
methodName,
interval,
};

const responses = this.dataClient.exportTabularData(req);

const dataArray: TabularDataPoint[] = [];

for await (const response of responses) {
dataArray.push({
partId: response.partId,
resourceName: response.resourceName,
resourceSubtype: response.resourceSubtype,
methodName: response.methodName,
timeCaptured: response.timeCaptured?.toDate(),
organizationId: response.organizationId,
locationId: response.locationId,
robotName: response.robotName,
robotId: response.robotId,
partName: response.partName,
methodParameters: response.methodParameters?.toJson(),
tags: response.tags,
payload: response.payload?.toJson(),
});
}

return dataArray;
}

/**
* Obtain unified tabular data and metadata, queried with SQL.
*
Expand Down

0 comments on commit 63c34f7

Please sign in to comment.