Skip to content

Commit 36ce14b

Browse files
committed
Merge branch 'harmony-1978' of https://github.com/nasa/harmony into harmony-1978
2 parents f3402eb + eed9d93 commit 36ce14b

40 files changed

+728
-236
lines changed

db/db.sql

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ CREATE TABLE `job_errors` (
4141
`jobID` char(36) not null,
4242
`url` varchar(4096) not null,
4343
`message` varchar(4096) not null,
44+
`level` varchar(255) check (
45+
`level` in (
46+
'error',
47+
'warning'
48+
)
49+
) not null default 'error',
50+
`category` varchar(255),
4451
`createdAt` datetime not null,
4552
`updatedAt` datetime not null,
4653
FOREIGN KEY(jobID) REFERENCES jobs(jobID)
@@ -80,7 +87,8 @@ CREATE TABLE `work_items` (
8087
`workflowStepIndex` integer not null,
8188
`scrollID` varchar(4096),
8289
`serviceID` varchar(255) not null,
83-
`status` text check (`status` in ('ready', 'queued', 'running', 'successful', 'failed', 'canceled')) not null,
90+
`status` varchar(255) check (`status` in ('ready', 'queued', 'running', 'successful', 'failed', 'canceled', 'warning')) not null,
91+
`sub_status` varchar(255),
8492
`stacCatalogLocation` varchar(255),
8593
`totalItemsSize` double precision not null default 0,
8694
`outputItemSizesJson` text,
@@ -183,9 +191,12 @@ CREATE INDEX jobs_username_idx ON jobs(jobID, username);
183191
CREATE INDEX job_links_jobID_idx ON job_links(jobID);
184192
CREATE INDEX job_links_jobID_id_idx ON job_links(jobID, id);
185193
CREATE INDEX job_errors_jobID_idx ON job_errors(jobID);
194+
CREATE INDEX job_errors_level_idx ON job_errors(level);
195+
CREATE INDEX job_errors_category_idx ON job_errors(category);
186196
CREATE INDEX work_items_jobID_idx ON work_items(jobID);
187197
CREATE INDEX work_items_serviceID_idx ON work_items(serviceID);
188198
CREATE INDEX work_items_status_idx ON work_items(status);
199+
CREATE INDEX work_items_sub_status_idx ON work_items(sub_status);
189200
CREATE INDEX workflow_steps_jobID_idx ON workflow_steps(jobID);
190201
CREATE INDEX workflow_steps_jobID_StepIndex_idx ON workflow_steps(jobID, stepIndex);
191202
CREATE INDEX workflow_steps_serviceID_idx ON workflow_steps(serviceID);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* @param { import("knex").Knex } knex
3+
* @returns { Promise<void> }
4+
*/
5+
exports.up = function (knex, Promise) {
6+
return knex.schema.raw(`
7+
ALTER TABLE "work_items"
8+
DROP CONSTRAINT "work_items_status_check",
9+
ADD CONSTRAINT "work_items_status_check"
10+
CHECK (status IN ('ready', 'queued', 'running', 'successful', 'failed', 'canceled', 'warning')),
11+
ADD COLUMN "sub_status" VARCHAR(255);
12+
13+
CREATE INDEX work_items_sub_status_index ON work_items (sub_status);
14+
`);
15+
};
16+
17+
/**
18+
* @param { import("knex").Knex } knex
19+
* @returns { Promise<void> }
20+
*/
21+
exports.down = function (knex) {
22+
return knex.schema.raw(`
23+
DROP INDEX work_items_sub_status_index;
24+
ALTER TABLE "work_items"
25+
DROP COLUMN "sub_status",
26+
DROP CONSTRAINT "work_items_status_check",
27+
ADD CONSTRAINT "work_items_status_check"
28+
CHECK (status IN ('ready', 'queued', 'running', 'successful', 'failed', 'canceled'));
29+
`);
30+
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @param { import("knex").Knex } knex
3+
* @returns { Promise<void> }
4+
*/
5+
exports.up = function (knex, Promise) {
6+
return knex.schema.raw(`
7+
ALTER TABLE "job_errors"
8+
ADD COLUMN "level" VARCHAR(255) DEFAULT 'error' NOT NULL,
9+
ADD CONSTRAINT "job_errors_level_check"
10+
CHECK (level IN ('error', 'warning')),
11+
ADD COLUMN "category" VARCHAR(255);
12+
13+
CREATE INDEX job_errors_level_index ON job_errors (level);
14+
CREATE INDEX job_errors_category_index ON job_errors (category);
15+
`);
16+
};
17+
18+
/**
19+
* @param { import("knex").Knex } knex
20+
* @returns { Promise<void> }
21+
*/
22+
exports.down = function (knex) {
23+
return knex.schema.raw(`
24+
DROP INDEX job_errors_category_index;
25+
DROP INDEX job_errors_level_index;
26+
ALTER TABLE "job_errors"
27+
DROP COLUMN "category",
28+
DROP CONSTRAINT "job_errors_level_check",
29+
DROP COLUMN "level";
30+
`);
31+
};

docs/guides/adapting-new-services.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ The structure of an entry in the [services.yml](../../config/services.yml) file
187187
- image/png
188188
- image/gif
189189
reprojection: true # The service supports reprojection
190+
validate_variables: true # Whether to validate the requested variables exist in the CMR. Defaults to true.
190191
steps:
191192
- image: !Env ${QUERY_CMR_IMAGE} # The image to use for the first step in the chain
192193
- image: !Env ${HARMONY_EXAMPLE_IMAGE} # The image to use for the second step in the chain

packages/util/tsconfig.build.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
"allowJs": true,
1111
"noImplicitAny": false,
1212
"sourceMap": true,
13-
"outDir": "built"
13+
"outDir": "built",
14+
"typeRoots": [
15+
"node_modules/@types"
16+
]
1417
},
1518
"include": ["."],
1619
"exclude": ["./node_modules", "coverage"]

packages/util/tsconfig.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
"allowJs": true,
1111
"noImplicitAny": false,
1212
"sourceMap": true,
13-
"outDir": "built"
13+
"outDir": "built",
14+
"typeRoots": [
15+
"node_modules/@types"
16+
],
1417
},
1518
"include": ["."],
1619
"exclude": ["./node_modules", "coverage"]

services/harmony/app/backends/workflow-orchestration/work-item-updates.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,8 @@ export async function preprocessWorkItem(
552552
let outputItemSizes;
553553
let catalogItems;
554554
try {
555-
if (status === WorkItemStatus.SUCCESSFUL && !nextWorkflowStep) {
555+
// TODO fix this in HARMONY-1995
556+
if ([WorkItemStatus.SUCCESSFUL, WorkItemStatus.WARNING].includes(status) && !nextWorkflowStep) {
556557
// if we are CREATING STAC CATALOGS for the last step in the chain we should read the catalog items
557558
// since they are needed for generating the output links we will save
558559
catalogItems = await readCatalogsItems(results);
@@ -608,13 +609,13 @@ export async function processWorkItem(
608609
): Promise<void> {
609610
const { jobID } = job;
610611
const { status, errorMessage, catalogItems, outputItemSizes } = preprocessResult;
611-
const { workItemID, hits, results, scrollID } = update;
612+
const { workItemID, hits, results, scrollID, sub_status } = update;
612613
const startTime = new Date().getTime();
613614
let durationMs;
614615
let jobSaveStartTime;
615616
let didCreateWorkItem = false;
616-
if (status === WorkItemStatus.SUCCESSFUL) {
617-
logger.info(`Updating work item ${workItemID} to ${status}`);
617+
if (status === WorkItemStatus.SUCCESSFUL || status === WorkItemStatus.WARNING) {
618+
logger.info(`Updating work item ${workItemID} to ${status} | ${sub_status}`);
618619
}
619620

620621
try {
@@ -700,6 +701,7 @@ export async function processWorkItem(
700701
tx,
701702
workItemID,
702703
status,
704+
sub_status,
703705
duration,
704706
totalItemsSize,
705707
outputItemSizes);
@@ -711,6 +713,7 @@ export async function processWorkItem(
711713
logger.info(`Updated work item. Duration (ms) was: ${duration}`);
712714

713715
workItem.status = status;
716+
workItem.sub_status = sub_status;
714717

715718
let allWorkItemsForStepComplete = false;
716719

services/harmony/app/backends/workflow-orchestration/workflow-orchestration.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export async function updateWorkItem(req: HarmonyRequest, res: Response): Promis
9696
const { id } = req.params;
9797
const {
9898
status,
99+
sub_status,
99100
hits,
100101
results,
101102
scrollID,
@@ -116,6 +117,7 @@ export async function updateWorkItem(req: HarmonyRequest, res: Response): Promis
116117
const update = {
117118
workItemID: parseInt(id),
118119
status,
120+
sub_status,
119121
hits,
120122
results,
121123
scrollID,

services/harmony/app/frontends/capabilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ async function loadCollectionInfo(req: HarmonyRequest): Promise<CmrCollection> {
8585
collections = await getCollectionsByShortName(req.context, shortname, req.accessToken);
8686
if (collections.length === 0) {
8787
const message = `Unable to find collection short name ${shortname} in the CMR. Please `
88-
+ ' make sure the short name is correct and that you have access to the collection.';
88+
+ 'make sure the short name is correct and that you have access to the collection.';
8989
throw new NotFoundError(message);
9090
}
9191
pickedCollection = collections[0];

services/harmony/app/frontends/ogc-coverages/describe-collections.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import HarmonyRequest from '../../models/harmony-request';
44
import { RequestValidationError } from '../../util/errors';
55
import { keysToLowerCase } from '../../util/object';
66
import { getSanitizedRequestUrl } from '../../util/url';
7-
import { parseVariables, fullPath } from '../../util/variables';
7+
import { parseVariables, fullPath, getVariableInfo } from '../../util/variables';
88
import { getServiceConfigs } from '../../models/services';
99

1010
const WGS84 = 'http://www.opengis.net/def/crs/OGC/1.3/CRS84';
@@ -72,7 +72,7 @@ function buildCollectionInfo(
7272
* Get a list of variables that are defined in the service configs as being available for
7373
* processing for the given collection. If the returned set is empty this means there are no
7474
* limits set as to which variables a service will process.
75-
* @param collection - the CMR collection
75+
* @param collection - the CMR collection
7676
* @returns A Set of variable IDs obtained from service configs
7777
*/
7878
function getSupportedVariablesForCollection(
@@ -111,7 +111,7 @@ export function describeCollections(req: HarmonyRequest, res: Response): void {
111111
const ogcCollections = [];
112112
const requestUrl = getSanitizedRequestUrl(req, false);
113113
const ogcApiRoot = requestUrl.replace(/\/collections$/, '');
114-
for (const collection of req.collections) {
114+
for (const collection of req.context.collections) {
115115
const collectionShortLabel = `${collection.short_name} v${collection.version_id}`;
116116
const rootLink = {
117117
title: `OGC coverages API root for ${collectionShortLabel}`,
@@ -136,7 +136,7 @@ export function describeCollections(req: HarmonyRequest, res: Response): void {
136136
}
137137
for (const variable of collection.variables) {
138138
// if a service has limited the variables for the collection, only allow variables in that
139-
// set
139+
// set
140140
if (supportedVariables.has(variable.meta['concept-id']) || supportedVariables.size === 0) {
141141
const collectionInfo = buildCollectionInfo(
142142
collection, variable, `${requestUrl}/${encodeURIComponent(fullPath(variable))}`, extent,
@@ -165,11 +165,12 @@ export function describeCollection(req: HarmonyRequest, res: Response): void {
165165
if (query.f && query.f !== 'json') {
166166
throw new RequestValidationError(`Unsupported format "${query.f}". Currently only the json format is supported.`);
167167
}
168-
const collection = req.collections[0];
168+
const collection = req.context.collections[0];
169169
const requestUrl = getSanitizedRequestUrl(req, false);
170170
const extent = generateExtent(collection);
171-
const variableInfo = parseVariables([collection], req.params.collectionId);
172-
const variable = variableInfo[0].variables[0];
171+
const requestedVariableId = parseVariables(req.params.collectionId, []);
172+
const variableInfos = getVariableInfo([collection], requestedVariableId, true);
173+
const variable = variableInfos[0].variables[0];
173174
const collectionInfo = buildCollectionInfo(collection, variable, requestUrl, extent);
174175
res.send(collectionInfo);
175176
}

0 commit comments

Comments
 (0)