Skip to content

Commit

Permalink
feat: Refactor Site Wise Asset session interface to support Promises (#…
Browse files Browse the repository at this point in the history
…40)

break up the query style interface into individual method calls with unique signatures. Add methods that return a Promise.
  • Loading branch information
gareth-amazon authored Jan 31, 2022
1 parent 38f5f84 commit 184ccc6
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ export class IotAssetDetails {

componentWillLoad() {
this.assetSession = getSiteWiseAssetModule().startSession();
this.assetSession.addRequest(this.query, (summary: AssetSummary) => {
this.assetSession.requestAssetSummary(this.query, (summary: AssetSummary) => {
this.assetSummary = summary;
const assetId = this.assetSummary?.id as string;
const modelQuery: AssetModelQuery = { assetModelId: this.assetSummary.assetModelId as string };
this.assetSession.addRequest(modelQuery, (assetModel: DescribeAssetModelResponse) => {
this.assetSession.requestAssetModel(modelQuery, (assetModel: DescribeAssetModelResponse) => {
this.assetModel = assetModel;
assetModel.assetModelProperties?.forEach((prop) => {
let propQuery: AssetPropertyValueQuery = { assetId: assetId, propertyId: prop.id as string };
this.assetSession.addRequest(propQuery, (propValue: AssetPropertyValue) => {
this.assetSession.requestAssetPropertyValue(propQuery, (propValue: AssetPropertyValue) => {
const copy = new Map(this.assetPropertyValues);
copy.set(prop.id as string, this.convertToString(propValue));
this.assetPropertyValues = copy;
Expand Down
118 changes: 82 additions & 36 deletions packages/core/src/asset-modules/mocks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
AssetModelQuery,
AssetPropertyValueQuery,
AssetSummaryQuery,
HIERARCHY_ROOT_ID,
HierarchyAssetSummaryList,
isAssetHierarchyQuery,
isAssetModelQuery,
Expand All @@ -12,9 +13,15 @@ import {
SiteWiseAssetModuleInterface,
SiteWiseAssetSessionInterface,
} from './sitewise/types';
import { AssetState, DescribeAssetModelResponse, DescribeAssetResponse, Quality } from '@aws-sdk/client-iotsitewise';
import { Observable, Subscription } from 'rxjs';
import { AssetPropertyValue, AssetSummary } from '@aws-sdk/client-iotsitewise/dist-types/ts3.4';
import {
AssetPropertyValue,
AssetState,
AssetSummary,
DescribeAssetModelResponse,
DescribeAssetResponse,
Quality,
} from '@aws-sdk/client-iotsitewise';
import { lastValueFrom, Observable, Subscription } from 'rxjs';

export const ASSET_ID = 'assetABC123';
export const ASSET_MODEL_ID = 'assetModelABC123';
Expand Down Expand Up @@ -119,40 +126,79 @@ export class MockSiteWiseAssetSession implements SiteWiseAssetSessionInterface {
this.replayData = replayData;
}

addRequest(query: AssetModelQuery, observer: (assetModel: DescribeAssetModelResponse) => void): Subscription;
addRequest(query: AssetPropertyValueQuery, observer: (assetPropertyValue: AssetPropertyValue) => void): Subscription;
addRequest(query: AssetHierarchyQuery, observer: (assetSummary: HierarchyAssetSummaryList) => void): Subscription;
addRequest(query: AssetSummaryQuery, observer: (assetSummary: AssetSummary) => void): Subscription;
addRequest(
query: AssetModelQuery | AssetPropertyValueQuery | AssetHierarchyQuery | AssetSummaryQuery,
observer:
| ((assetModel: DescribeAssetModelResponse) => void)
| ((assetPropertyValue: AssetPropertyValue) => void)
| ((assetSummary: HierarchyAssetSummaryList) => void)
| ((assetSummary: AssetSummary) => void)
private _requestAssetSummary(query: { assetId: string }): Observable<AssetSummary> {
return new Observable<AssetSummary>((observer) => {
observer.next(this.replayData.assets.get(query.assetId));
});
}
requestAssetSummary(query: { assetId: string }, observer: (assetSummary: AssetSummary) => void): Subscription {
return this._requestAssetSummary(query).subscribe(observer);
}
fetchAssetSummary(query: { assetId: string }): Promise<AssetSummary> {
return lastValueFrom(this._requestAssetSummary(query));
}

_requestAssetModel(query: { assetModelId: string }): Observable<DescribeAssetModelResponse> {
return new Observable<DescribeAssetModelResponse>((observer) => {
observer.next(this.replayData.models.get(query.assetModelId));
});
}
requestAssetModel(
query: { assetModelId: string },
observer: (assetSummary: DescribeAssetModelResponse) => void
): Subscription {
return this._requestAssetModel(query).subscribe(observer);
}
fetchAssetModel(query: { assetModelId: string }): Promise<DescribeAssetModelResponse> {
return lastValueFrom(this._requestAssetModel(query));
}

_requestAssetPropertyValue(query: { assetId: string; propertyId: string }): Observable<AssetPropertyValue> {
return new Observable<AssetPropertyValue>((observer) => {
observer.next(this.replayData.properties.get(query.assetId + ':' + query.propertyId));
});
}
requestAssetPropertyValue(
query: { assetId: string; propertyId: string },
observer: (assetSummary: AssetPropertyValue) => void
): Subscription {
let observable: Observable<any>;
if (isAssetModelQuery(query)) {
observable = new Observable<DescribeAssetModelResponse>((observer) => {
observer.next(this.replayData.models.get(query.assetModelId));
});
} else if (isAssetPropertyValueQuery(query)) {
observable = new Observable<AssetPropertyValue>((observer) => {
observer.next(this.replayData.properties.get(query.assetId + ':' + query.propertyId));
});
} else if (isAssetHierarchyQuery(query)) {
observable = new Observable<HierarchyAssetSummaryList>((observer) => {
observer.next(this.replayData.hierarchies.get(assetHierarchyQueryKey(query)));
});
} else if (isAssetSummaryQuery(query)) {
observable = new Observable<AssetSummary>((observer) => {
observer.next(this.replayData.assets.get(query.assetId));
});
} else {
throw 'Unexpected request type: the type of the request object could not be determined';
}

return observable.subscribe(observer);
return this._requestAssetPropertyValue(query).subscribe(observer);
}
fetchAssetPropertyValue(query: { assetId: string; propertyId: string }): Promise<AssetPropertyValue> {
return lastValueFrom(this._requestAssetPropertyValue(query));
}

_requestAssetHierarchy(query: {
assetId?: string | undefined;
assetHierarchyId: string;
}): Observable<HierarchyAssetSummaryList> {
return new Observable<HierarchyAssetSummaryList>((observer) => {
observer.next(this.replayData.hierarchies.get(assetHierarchyQueryKey(query)));
});
}
requestAssetHierarchy(
query: { assetId?: string | undefined; assetHierarchyId: string },
observer: (assetSummary: HierarchyAssetSummaryList) => void
): Subscription {
return this._requestAssetHierarchy(query).subscribe(observer);
}
fetchAssetHierarchy(query: {
assetId?: string | undefined;
assetHierarchyId: string;
}): Promise<HierarchyAssetSummaryList> {
return lastValueFrom(this._requestAssetHierarchy(query));
}

_requestRootAssets(): Observable<HierarchyAssetSummaryList> {
return new Observable<HierarchyAssetSummaryList>((observer) => {
observer.next(this.replayData.hierarchies.get(assetHierarchyQueryKey({ assetHierarchyId: HIERARCHY_ROOT_ID })));
});
}
requestRootAssets(observer: (assetSummary: HierarchyAssetSummaryList) => void): Subscription {
return this._requestRootAssets().subscribe(observer);
}
fetchRootAssets(): Promise<HierarchyAssetSummaryList> {
return lastValueFrom(this._requestRootAssets());
}

close(): void {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class SiteWiseAssetTreeSession {
// query starts at the specified root Asset
const root = new Branch();
this.branches[this.rootBranchRef.key] = root;
this.assetSession.addRequest({ assetId: query.rootAssetId }, (assetSummary) => {
this.assetSession.requestAssetSummary({ assetId: query.rootAssetId }, (assetSummary) => {
this.saveAsset(assetSummary);
root.assetIds.push(assetSummary.id as string);
this.updateTree();
Expand Down Expand Up @@ -90,15 +90,23 @@ export class SiteWiseAssetTreeSession {

// if the branch does not exist, or isn't fully loaded, start loading it
if (!existingExpanded || existingExpanded.loadingState != LoadingStateEnum.LOADED) {
const hierarchyQuery: AssetHierarchyQuery = {
assetId: branchRef.assetId,
assetHierarchyId: branchRef.hierarchyId,
};

this.assetSession.addRequest(hierarchyQuery, (results) => {
this.saveExpandedHierarchy(branchRef, results.assets, results.loadingState);
this.updateTree();
});
if (branchRef.hierarchyId === HIERARCHY_ROOT_ID) {
this.assetSession.requestRootAssets((results) => {
this.saveExpandedHierarchy(branchRef, results.assets, results.loadingState);
this.updateTree();
});
} else {
this.assetSession.requestAssetHierarchy(
{
assetId: branchRef.assetId,
assetHierarchyId: branchRef.hierarchyId,
},
(results) => {
this.saveExpandedHierarchy(branchRef, results.assets, results.loadingState);
this.updateTree();
}
);
}
}
}

Expand All @@ -110,18 +118,24 @@ export class SiteWiseAssetTreeSession {

// load related Asset Model and any of the requested properties that the Model contains
if (this.query.withModels || this.query.propertyIds?.length) {
this.assetSession.addRequest({ assetModelId: assetNode.asset.assetModelId } as AssetModelQuery, (model) => {
assetNode.model = model;
this.updateTree();
this.query.propertyIds?.forEach((propertyId) => {
if (this.containsPropertyId(model, propertyId)) {
this.assetSession.addRequest({ assetId: assetId, propertyId: propertyId }, (propertyValue) => {
assetNode.properties.set(propertyId, propertyValue);
this.updateTree();
});
}
});
});
this.assetSession.requestAssetModel(
{ assetModelId: assetNode.asset.assetModelId } as AssetModelQuery,
(model) => {
assetNode.model = model;
this.updateTree();
this.query.propertyIds?.forEach((propertyId) => {
if (this.containsPropertyId(model, propertyId)) {
this.assetSession.requestAssetPropertyValue(
{ assetId: assetId, propertyId: propertyId },
(propertyValue) => {
assetNode.properties.set(propertyId, propertyValue);
this.updateTree();
}
);
}
});
}
);
}
}

Expand Down
127 changes: 90 additions & 37 deletions packages/core/src/asset-modules/sitewise/session.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { Observable, Subscription } from 'rxjs';
import { lastValueFrom, Observable, Subscription } from 'rxjs';
import {
AssetHierarchyQuery,
AssetModelQuery,
AssetPropertyValueQuery,
AssetQuery,
AssetSummaryQuery,
HIERARCHY_ROOT_ID,
HierarchyAssetSummaryList,
isAssetHierarchyQuery,
isAssetModelQuery,
isAssetPropertyValueQuery,
isAssetSummaryQuery,
SiteWiseAssetSessionInterface,
} from './types';
import { AssetSummary, DescribeAssetModelResponse } from '@aws-sdk/client-iotsitewise/dist-types';
Expand All @@ -26,40 +23,96 @@ export class SiteWiseAssetSession implements SiteWiseAssetSessionInterface {
this.processor = processor;
}

public addRequest(query: AssetModelQuery, observer: (assetModel: DescribeAssetModelResponse) => void): Subscription;
public addRequest(
query: AssetPropertyValueQuery,
observer: (assetPropertyValue: AssetPropertyValue) => void
): Subscription;
public addRequest(
private _requestAssetSummary(query: AssetSummaryQuery): Observable<AssetSummary> {
const observable: Observable<AssetSummary> = new Observable<AssetSummary>((observer) => {
this.processor.getAssetSummary(query, observer);
this.requestQueue.push({ query: query, observable: observable });
});
return observable;
}

private _requestAssetModel(query: AssetModelQuery): Observable<DescribeAssetModelResponse> {
const observable: Observable<DescribeAssetModelResponse> = new Observable<DescribeAssetModelResponse>(
(observer) => {
this.processor.getAssetModel(query, observer);
this.requestQueue.push({ query: query, observable: observable });
}
);
return observable;
}

private _requestAssetPropertyValue(query: AssetPropertyValueQuery): Observable<AssetPropertyValue> {
const observable: Observable<AssetPropertyValue> = new Observable<AssetPropertyValue>((observer) => {
this.processor.getAssetPropertyValue(query, observer);
this.requestQueue.push({ query: query, observable: observable });
});
return observable;
}

private _requestRootAssets(): Observable<HierarchyAssetSummaryList> {
const observable: Observable<HierarchyAssetSummaryList> = new Observable<HierarchyAssetSummaryList>((observer) => {
const query: AssetHierarchyQuery = { assetHierarchyId: HIERARCHY_ROOT_ID };
this.processor.getAssetHierarchy(query, observer);
this.requestQueue.push({ query: query, observable: observable });
});
return observable;
}

private _requestAssetHierarchy(query: AssetHierarchyQuery): Observable<HierarchyAssetSummaryList> {
const observable: Observable<HierarchyAssetSummaryList> = new Observable<HierarchyAssetSummaryList>((observer) => {
this.processor.getAssetHierarchy(query, observer);
this.requestQueue.push({ query: query, observable: observable });
});
return observable;
}

fetchAssetHierarchy(query: AssetHierarchyQuery): Promise<HierarchyAssetSummaryList> {
return lastValueFrom(this._requestAssetHierarchy(query));
}

fetchAssetModel(query: AssetModelQuery): Promise<DescribeAssetModelResponse> {
return lastValueFrom(this._requestAssetModel(query));
}

fetchAssetPropertyValue(query: AssetPropertyValueQuery): Promise<AssetPropertyValue> {
return lastValueFrom(this._requestAssetPropertyValue(query));
}

fetchAssetSummary(query: AssetSummaryQuery): Promise<AssetSummary> {
return lastValueFrom(this._requestAssetSummary(query));
}

fetchRootAssets(): Promise<HierarchyAssetSummaryList> {
return lastValueFrom(this._requestRootAssets());
}

requestAssetHierarchy(
query: AssetHierarchyQuery,
observer: (assetSummary: HierarchyAssetSummaryList) => void
): Subscription;
public addRequest(query: AssetSummaryQuery, observer: (assetSummary: AssetSummary) => void): Subscription;
public addRequest<Result>(query: AssetQuery, observerAny: (consumedType: Result) => void): Subscription {
let observable: Observable<any>;
if (isAssetModelQuery(query)) {
observable = new Observable<DescribeAssetModelResponse>((observer) => {
this.processor.getAssetModel(query, observer);
});
} else if (isAssetPropertyValueQuery(query)) {
observable = new Observable<AssetPropertyValue>((observer) => {
this.processor.getAssetPropertyValue(query, observer);
});
} else if (isAssetHierarchyQuery(query)) {
observable = new Observable<HierarchyAssetSummaryList>((observer) => {
this.processor.getAssetHierarchy(query, observer);
});
} else if (isAssetSummaryQuery(query)) {
observable = new Observable<AssetSummary>((observer) => {
this.processor.getAssetSummary(query, observer);
});
} else {
throw 'Unexpected request type: the type of the request object could not be determined';
}

this.requestQueue.push({ query: query, observable: observable });
return observable.subscribe(observerAny);
): Subscription {
return this._requestAssetHierarchy(query).subscribe(observer);
}

requestAssetModel(
query: AssetModelQuery,
observer: (assetSummary: DescribeAssetModelResponse) => void
): Subscription {
return this._requestAssetModel(query).subscribe(observer);
}

requestAssetPropertyValue(
query: AssetPropertyValueQuery,
observer: (assetSummary: AssetPropertyValue) => void
): Subscription {
return this._requestAssetPropertyValue(query).subscribe(observer);
}

requestAssetSummary(query: AssetSummaryQuery, observer: (assetSummary: AssetSummary) => void): Subscription {
return this._requestAssetSummary(query).subscribe(observer);
}

requestRootAssets(observer: (assetSummary: HierarchyAssetSummaryList) => void): Subscription {
return this._requestRootAssets().subscribe(observer);
}

/**
Expand Down
Loading

0 comments on commit 184ccc6

Please sign in to comment.