Skip to content

Commit

Permalink
feat(getContent): return a property w/ an array of any errors that ha…
Browse files Browse the repository at this point in the history
…ppened during composition

affects: @esri/hub-common, @esri/hub-content
  • Loading branch information
tomwayson committed Oct 13, 2020
1 parent 12c6f06 commit b78696d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 25 deletions.
14 changes: 14 additions & 0 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ export interface IHubResource {
// Unique or additional formal metadata that will be displayed in sidebar
}

/**
* Information about an error that occurred while indexing or composing content
*/
export interface IEnrichmentErrorInfo {
type: "HTTP" | "AGO" | "Other";
statusCode?: number;
message?: string;
}

/**
* Properties that are common to all Hub content types (dataset, map, document, etc)
*
Expand Down Expand Up @@ -288,6 +297,11 @@ export interface IHubContent extends IHubResource, IItem {
portalDataUrl?: string;
/** The ids of any groups that the item belongs to */
groupIds?: string[];
/**
* Any errors encountered when indexing or composing the content
* see https://github.com/ArcGIS/hub-indexer/blob/dc6146c3b7b4007b530f8e6357a9c36db59a6996/docs/errors.md#response-formatting-for-errors
*/
errors?: IEnrichmentErrorInfo[];
}

interface IActionLink {
Expand Down
51 changes: 28 additions & 23 deletions packages/content/src/portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { IItem, getItem, getItemGroups } from "@esri/arcgis-rest-portal";
import {
HubType,
IEnrichmentErrorInfo,
IHubContent,
IHubGeography,
IHubRequestOptions,
Expand All @@ -16,8 +17,7 @@ import {
getItemDataUrl,
getItemThumbnailUrl,
cloneObject,
includes,
failSafe
includes
} from "@esri/hub-common";
import { getContentMetadata } from "./metadata";

Expand Down Expand Up @@ -45,29 +45,34 @@ function fetchProperties(
itemId: string,
requestOptions: IHubRequestOptions
): Promise<{ [key: string]: unknown }> {
const errors: IEnrichmentErrorInfo[] = [];
const propertyNames = Object.keys(propertyRequests);
// ideally we'd be able to use hashSettled(), but that's not standard
// so instead return the property name to indicate that the request failed
const requests = propertyNames.map(propertyName =>
failSafe(propertyRequests[propertyName], propertyName)(
itemId,
requestOptions
)
);
const requests = propertyNames.map(propertyName => {
// initiate the request and return the promise
const request = propertyRequests[propertyName];
return request(itemId, requestOptions).catch(e => {
// there was an error w/ the request, capture it
const message = (e && e.message) || e;
errors.push({
// NOTE: for now we just return the message and type "Other"
// but we could later introspect for HTTP or AGO errors
// and/or return the status code if available
type: "Other",
message
});
// and then set this property to null
return null;
});
});
return Promise.all(requests).then(values => {
return values.reduce(
(properties, value, i) => {
const propertyName = propertyNames[i];
if (value === propertyName) {
// capture that the request failed
properties.errors.push(propertyName);
} else {
properties[propertyName] = value;
}
return properties;
},
{ errors: [] } as { [key: string]: unknown }
);
// include any errors in the returned properties
const properties: { [key: string]: unknown } = { errors };
// populate the remaining property values
values.forEach((value, i) => {
const name = propertyNames[i];
properties[name] = value;
});
return properties;
});
}

Expand Down
5 changes: 3 additions & 2 deletions packages/content/test/portal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,11 @@ describe("get content from portal", () => {
Promise.resolve(mockItemGroups)
);
// emulate no metadata exists for this item
const message = "Some error";
const getContentMetadataSpy = spyOn(
metadataModule,
"getContentMetadata"
).and.returnValue(Promise.reject());
).and.returnValue(Promise.reject(message));
const item = itemJson as IItem;
const id = item.id;
getContentFromPortal(id, requestOpts).then(content => {
Expand All @@ -179,7 +180,7 @@ describe("get content from portal", () => {
expect(content.groupIds).toEqual(["memberGroupId"]);
// verify that we failed to fetch the metadata
expect(getContentMetadataSpy.calls.argsFor(0)[0]).toBe(id);
expect(content.errors).toEqual(["metadata"]);
expect(content.errors).toEqual([{ type: "Other", message }]);
done();
});
});
Expand Down

0 comments on commit b78696d

Please sign in to comment.