|
| 1 | +import _ from 'highland'; |
| 2 | +import { isServerError, isThrottlingError, isTransientError } from '@smithy/service-error-classification'; |
| 3 | +import { |
| 4 | + rejectWithFault, |
| 5 | + ratelimit, |
| 6 | +} from '../utils'; |
| 7 | + |
| 8 | +import Connector from '../connectors/athena'; |
| 9 | + |
| 10 | +export const startQueryExecution = ({ |
| 11 | + id: pipelineId, |
| 12 | + debug, |
| 13 | + queryRequestField = 'queryRequest', |
| 14 | + queryResponseField = 'queryResponse', |
| 15 | + parallel = Number(process.env.ATHENA_PARALLEL) || Number(process.env.PARALLEL) || 1, |
| 16 | + outputLocation = 'outputLocationRequest', |
| 17 | + encryptionEnabled = true, |
| 18 | + encryptionOption = 'CSE_KMS', |
| 19 | + kmsKey = process.env.REGIONAL_MASTER_KEY_ARN || /* istanbul ignore next */ process.env.MASTER_KEY_ARN, |
| 20 | + database = process.env.GLUE_DATABASE, |
| 21 | + catalog = process.env.GLUE_CATALOG, |
| 22 | + skipRetry = process.env.SKIP_RETRY === 'true' || process.env.NODE_ENV === 'test', |
| 23 | + ...opt |
| 24 | +} /* = {} */) => { |
| 25 | + const connector = new Connector({ |
| 26 | + pipelineId, debug, ...opt, |
| 27 | + }); |
| 28 | + |
| 29 | + const invoke = (uow) => { |
| 30 | + /* istanbul ignore if */ |
| 31 | + if (!uow[queryRequestField]) return _(Promise.resolve(uow)); |
| 32 | + |
| 33 | + const p = () => connector.startQueryExecution({ |
| 34 | + ClientRequestToken: `${uow.record?.dynamodb?.Keys?.sk?.S}-${pipelineId}`, |
| 35 | + WorkGroup: process.env.WORK_GROUP, |
| 36 | + ResultConfiguration: { |
| 37 | + OutputLocation: uow[outputLocation], |
| 38 | + EncryptionConfiguration: encryptionEnabled ? { |
| 39 | + EncryptionOption: encryptionOption, |
| 40 | + KmsKey: kmsKey, |
| 41 | + } : /* istanbul ignore next */ undefined, |
| 42 | + }, |
| 43 | + QueryExecutionContext: { |
| 44 | + Database: database, |
| 45 | + Catalog: catalog, |
| 46 | + }, |
| 47 | + |
| 48 | + ...uow[queryRequestField], |
| 49 | + }, uow) |
| 50 | + .then((queryResponse) => ({ ...uow, [queryResponseField]: queryResponse })) |
| 51 | + .catch(/* istanbul ignore next */(err) => { |
| 52 | + if (!skipRetry && (isThrottlingError(err) || isServerError(err) || isTransientError(err))) { // TODO potentially check retry count |
| 53 | + return { |
| 54 | + ...uow, |
| 55 | + [queryResponseField]: { retry: uow.record.eventID }, |
| 56 | + }; |
| 57 | + } |
| 58 | + return Promise.reject(err); |
| 59 | + }) |
| 60 | + .catch(rejectWithFault(uow)); |
| 61 | + |
| 62 | + return _(uow.metrics?.w(p, 'query') || p()); // wrap promise in a stream |
| 63 | + }; |
| 64 | + |
| 65 | + return (s) => s |
| 66 | + .through(ratelimit(opt)) |
| 67 | + .map(invoke) |
| 68 | + .parallel(parallel); |
| 69 | +}; |
0 commit comments