@bitblit/ratchet-epsilon-common 6.0.146-alpha → 6.0.147-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -9
- package/src/background/background-dynamo-log-table-handler.ts +44 -0
- package/src/background/background-entry.ts +4 -0
- package/src/background/background-execution-event-type.ts +9 -0
- package/src/background/background-execution-event.ts +9 -0
- package/src/background/background-execution-listener.ts +6 -0
- package/src/background/background-handler.ts +352 -0
- package/src/background/background-http-adapter-handler.ts +166 -0
- package/src/background/background-meta-response-internal.ts +5 -0
- package/src/background/background-process-handling.ts +6 -0
- package/src/background/background-process-log-table-entry.ts +11 -0
- package/src/background/background-queue-response-internal.ts +9 -0
- package/src/background/background-validator.ts +105 -0
- package/src/background/epsilon-background-process-error.ts +110 -0
- package/src/background/internal-background-entry.ts +10 -0
- package/src/background/manager/abstract-background-manager.ts +120 -0
- package/src/background/manager/aws-large-payload-s3-sqs-sns-background-manager.ts +87 -0
- package/src/background/manager/aws-sqs-sns-background-manager.ts +201 -0
- package/src/background/manager/background-manager-like.ts +44 -0
- package/src/background/manager/background-manager.spec.ts +89 -0
- package/src/background/manager/single-thread-local-background-manager.ts +58 -0
- package/src/background/s3-background-transaction-logger.ts +65 -0
- package/src/build/ratchet-epsilon-common-info.ts +19 -0
- package/src/built-in/background/echo-processor.ts +17 -0
- package/src/built-in/background/log-and-enqueue-echo-processor.ts +14 -0
- package/src/built-in/background/log-message-background-error-processor.ts +10 -0
- package/src/built-in/background/no-op-processor.ts +12 -0
- package/src/built-in/background/retry-processor.ts +51 -0
- package/src/built-in/background/sample-delay-processor.ts +15 -0
- package/src/built-in/background/sample-input-validated-processor-data.ts +4 -0
- package/src/built-in/background/sample-input-validated-processor.ts +14 -0
- package/src/built-in/built-in-trace-id-generators.ts +22 -0
- package/src/built-in/daemon/daemon-authorizer-function.ts +4 -0
- package/src/built-in/daemon/daemon-config.ts +9 -0
- package/src/built-in/daemon/daemon-group-selection-function.ts +3 -0
- package/src/built-in/daemon/daemon-handler.ts +87 -0
- package/src/built-in/daemon/daemon-process-state-list.ts +9 -0
- package/src/built-in/http/apollo/apollo-util.ts +43 -0
- package/src/built-in/http/apollo/default-epsilon-apollo-context.ts +11 -0
- package/src/built-in/http/apollo/epsilon-apollo-context-builder-options.ts +5 -0
- package/src/built-in/http/apollo/epsilon-lambda-apollo-context-function-argument.ts +6 -0
- package/src/built-in/http/apollo/epsilon-lambda-apollo-options.ts +11 -0
- package/src/built-in/http/apollo-filter.ts +151 -0
- package/src/built-in/http/built-in-auth-filters.ts +73 -0
- package/src/built-in/http/built-in-authorizers.ts +22 -0
- package/src/built-in/http/built-in-filters.spec.ts +26 -0
- package/src/built-in/http/built-in-filters.ts +300 -0
- package/src/built-in/http/built-in-handlers.ts +85 -0
- package/src/built-in/http/log-level-manipulation-filter.ts +26 -0
- package/src/built-in/http/run-handler-as-filter.spec.ts +67 -0
- package/src/built-in/http/run-handler-as-filter.ts +102 -0
- package/src/cli/ratchet-cli-handler.ts +23 -0
- package/src/cli/run-background-process-from-command-line.ts +32 -0
- package/src/config/background/background-aws-config.ts +8 -0
- package/src/config/background/background-config.ts +15 -0
- package/src/config/background/background-error-processor.ts +5 -0
- package/src/config/background/background-processor.ts +14 -0
- package/src/config/background/background-transaction-log.ts +9 -0
- package/src/config/background/background-transaction-logger.ts +6 -0
- package/src/config/cron/abstract-cron-entry.ts +17 -0
- package/src/config/cron/cron-background-entry.ts +17 -0
- package/src/config/cron/cron-config.ts +10 -0
- package/src/config/dynamo-db-config.ts +6 -0
- package/src/config/epsilon-config.ts +30 -0
- package/src/config/epsilon-lambda-event-handler.ts +12 -0
- package/src/config/epsilon-logger-config.ts +23 -0
- package/src/config/espilon-server-mode.ts +10 -0
- package/src/config/generic-aws-event-handler-function.ts +1 -0
- package/src/config/http/authorizer-function.ts +9 -0
- package/src/config/http/epsilon-authorization-context.ts +5 -0
- package/src/config/http/epsilon-cors-approach.ts +7 -0
- package/src/config/http/extended-api-gateway-event.ts +8 -0
- package/src/config/http/filter-chain-context.ts +15 -0
- package/src/config/http/filter-function.ts +3 -0
- package/src/config/http/handler-function.ts +4 -0
- package/src/config/http/http-config.ts +27 -0
- package/src/config/http/http-processing-config.ts +23 -0
- package/src/config/http/mapped-http-processing-config.ts +12 -0
- package/src/config/http/null-returned-object-handling.ts +7 -0
- package/src/config/inter-api/inter-api-aws-config.ts +5 -0
- package/src/config/inter-api/inter-api-config.ts +7 -0
- package/src/config/inter-api/inter-api-process-mapping.ts +11 -0
- package/src/config/local-server/local-server-event-logging-style.ts +8 -0
- package/src/config/local-server/local-server-http-method-handling.ts +7 -0
- package/src/config/local-server/local-server-options.ts +12 -0
- package/src/config/logging-trace-id-generator.ts +3 -0
- package/src/config/no-handlers-found-error.ts +6 -0
- package/src/config/open-api/open-api-document-components.ts +4 -0
- package/src/config/open-api/open-api-document.ts +7 -0
- package/src/config/s3-config.ts +8 -0
- package/src/config/sns-config.ts +7 -0
- package/src/config/sqs-config.ts +7 -0
- package/src/epsilon-build-properties.ts +21 -0
- package/src/epsilon-constants.ts +62 -0
- package/src/epsilon-global-handler.ts +238 -0
- package/src/epsilon-instance.ts +20 -0
- package/src/epsilon-logging-extension-processor.ts +19 -0
- package/src/http/auth/api-gateway-adapter-authentication-handler.ts +95 -0
- package/src/http/auth/auth0-web-token-manipulator.ts +69 -0
- package/src/http/auth/basic-auth-token.ts +7 -0
- package/src/http/auth/google-web-token-manipulator.spec.ts +15 -0
- package/src/http/auth/google-web-token-manipulator.ts +80 -0
- package/src/http/auth/jwt-ratchet-local-web-token-manipulator.ts +37 -0
- package/src/http/auth/local-web-token-manipulator.spec.ts +34 -0
- package/src/http/auth/local-web-token-manipulator.ts +114 -0
- package/src/http/auth/web-token-manipulator.ts +9 -0
- package/src/http/error/bad-gateway.ts +11 -0
- package/src/http/error/bad-request-error.ts +11 -0
- package/src/http/error/conflict-error.ts +12 -0
- package/src/http/error/forbidden-error.ts +12 -0
- package/src/http/error/gateway-timeout.ts +12 -0
- package/src/http/error/method-not-allowed-error.ts +12 -0
- package/src/http/error/misconfigured-error.ts +12 -0
- package/src/http/error/not-found-error.ts +12 -0
- package/src/http/error/not-implemented.ts +12 -0
- package/src/http/error/request-timeout-error.ts +12 -0
- package/src/http/error/service-unavailable.ts +12 -0
- package/src/http/error/too-many-requests-error.ts +12 -0
- package/src/http/error/unauthorized-error.ts +12 -0
- package/src/http/event-util.spec.ts +190 -0
- package/src/http/event-util.ts +272 -0
- package/src/http/response-util.spec.ts +117 -0
- package/src/http/response-util.ts +164 -0
- package/src/http/route/epsilon-router.ts +9 -0
- package/src/http/route/extended-auth-response-context.ts +7 -0
- package/src/http/route/route-and-parse.ts +8 -0
- package/src/http/route/route-mapping.ts +21 -0
- package/src/http/route/route-validator-config.ts +5 -0
- package/src/http/route/router-util.spec.ts +33 -0
- package/src/http/route/router-util.ts +314 -0
- package/src/http/web-handler.spec.ts +99 -0
- package/src/http/web-handler.ts +157 -0
- package/src/http/web-v2-handler.ts +34 -0
- package/src/inter-api/inter-api-entry.ts +8 -0
- package/src/inter-api/inter-api-util.spec.ts +77 -0
- package/src/inter-api/inter-api-util.ts +71 -0
- package/src/inter-api-manager.ts +75 -0
- package/src/lambda-event-handler/cron-epsilon-lambda-event-handler.spec.ts +130 -0
- package/src/lambda-event-handler/cron-epsilon-lambda-event-handler.ts +132 -0
- package/src/lambda-event-handler/dynamo-epsilon-lambda-event-handler.ts +42 -0
- package/src/lambda-event-handler/generic-sns-epsilon-lambda-event-handler.ts +38 -0
- package/src/lambda-event-handler/generic-sqs-epsilon-lambda-event-handler.ts +43 -0
- package/src/lambda-event-handler/inter-api-epsilon-lambda-event-handler.ts +33 -0
- package/src/lambda-event-handler/s3-epsilon-lambda-event-handler.ts +50 -0
- package/src/local-container-server.ts +128 -0
- package/src/local-server.spec.ts +16 -0
- package/src/local-server.ts +426 -0
- package/src/open-api-util/open-api-doc-modifications.ts +9 -0
- package/src/open-api-util/open-api-doc-modifier.spec.ts +22 -0
- package/src/open-api-util/open-api-doc-modifier.ts +90 -0
- package/src/open-api-util/yaml-combiner.spec.ts +26 -0
- package/src/open-api-util/yaml-combiner.ts +35 -0
- package/src/sample/sample-server-components-with-apollo.ts +87 -0
- package/src/sample/sample-server-components.ts +183 -0
- package/src/sample/sample-server-static-files.ts +614 -0
- package/src/sample/test-error-server.ts +140 -0
- package/src/util/aws-util.ts +89 -0
- package/src/util/context-global-data.ts +13 -0
- package/src/util/context-util.ts +156 -0
- package/src/util/cron-util.spec.ts +190 -0
- package/src/util/cron-util.ts +86 -0
- package/src/util/epsilon-config-parser.ts +90 -0
- package/src/util/epsilon-server-util.spec.ts +18 -0
- package/src/util/epsilon-server-util.ts +16 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitblit/ratchet-epsilon-common",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.147-alpha",
|
|
4
4
|
"description": "Tiny adapter to simplify building API gateway Lambda APIS",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"files": [
|
|
11
|
+
"src/**",
|
|
11
12
|
"lib/**",
|
|
12
13
|
"bin/**"
|
|
13
14
|
],
|
|
@@ -66,10 +67,10 @@
|
|
|
66
67
|
"@aws-sdk/client-sns": "3.922.0",
|
|
67
68
|
"@aws-sdk/client-sqs": "3.922.0",
|
|
68
69
|
"@aws-sdk/types": "3.922.0",
|
|
69
|
-
"@bitblit/ratchet-aws": "6.0.
|
|
70
|
-
"@bitblit/ratchet-common": "6.0.
|
|
71
|
-
"@bitblit/ratchet-misc": "6.0.
|
|
72
|
-
"@bitblit/ratchet-node-only": "6.0.
|
|
70
|
+
"@bitblit/ratchet-aws": "6.0.147-alpha",
|
|
71
|
+
"@bitblit/ratchet-common": "6.0.147-alpha",
|
|
72
|
+
"@bitblit/ratchet-misc": "6.0.147-alpha",
|
|
73
|
+
"@bitblit/ratchet-node-only": "6.0.147-alpha",
|
|
73
74
|
"@smithy/abort-controller": "4.2.4",
|
|
74
75
|
"@smithy/smithy-client": "4.9.2",
|
|
75
76
|
"@smithy/util-waiter": "4.2.4",
|
|
@@ -86,10 +87,10 @@
|
|
|
86
87
|
},
|
|
87
88
|
"peerDependencies": {
|
|
88
89
|
"@apollo/server": "^5.1.0",
|
|
89
|
-
"@bitblit/ratchet-aws": "6.0.
|
|
90
|
-
"@bitblit/ratchet-common": "6.0.
|
|
91
|
-
"@bitblit/ratchet-misc": "6.0.
|
|
92
|
-
"@bitblit/ratchet-node-only": "6.0.
|
|
90
|
+
"@bitblit/ratchet-aws": "6.0.147-alpha",
|
|
91
|
+
"@bitblit/ratchet-common": "6.0.147-alpha",
|
|
92
|
+
"@bitblit/ratchet-misc": "6.0.147-alpha",
|
|
93
|
+
"@bitblit/ratchet-node-only": "6.0.147-alpha",
|
|
93
94
|
"graphql": "^16.12.0"
|
|
94
95
|
},
|
|
95
96
|
"peerDependenciesMeta": {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { BackgroundExecutionListener } from './background-execution-listener.js';
|
|
2
|
+
import { BackgroundExecutionEvent } from './background-execution-event.js';
|
|
3
|
+
import { BackgroundExecutionEventType } from './background-execution-event-type.js';
|
|
4
|
+
import { DynamoRatchetLike } from '@bitblit/ratchet-aws/dynamodb/dynamo-ratchet-like';
|
|
5
|
+
import { BackgroundProcessLogTableEntry } from './background-process-log-table-entry.js';
|
|
6
|
+
import { ContextUtil } from '../util/context-util.js';
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
Table should be
|
|
10
|
+
- Hash key : guid
|
|
11
|
+
- Range key: timestamp
|
|
12
|
+
*/
|
|
13
|
+
export class BackgroundDynamoLogTableHandler<T> implements BackgroundExecutionListener<T> {
|
|
14
|
+
constructor(
|
|
15
|
+
private dynamo: DynamoRatchetLike,
|
|
16
|
+
private tableName: string,
|
|
17
|
+
private env: string,
|
|
18
|
+
private backgroundQueueName: string,
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
async onEvent(event: BackgroundExecutionEvent<T>): Promise<void> {
|
|
22
|
+
const entry: BackgroundProcessLogTableEntry = {
|
|
23
|
+
env: this.env,
|
|
24
|
+
backgroundQueueName: this.backgroundQueueName,
|
|
25
|
+
requestId: ContextUtil.currentRequestId(),
|
|
26
|
+
guid: event.guid,
|
|
27
|
+
processTypeName: event.processorType,
|
|
28
|
+
state: event.type.toString(),
|
|
29
|
+
timestampEpochMs: new Date().getTime(),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (event.type == BackgroundExecutionEventType.DataValidationError) {
|
|
33
|
+
const errors: string[] = event?.errors?.length ? event.errors : ['No-Error']; // DDB does not allow empty sets
|
|
34
|
+
entry.errors = errors;
|
|
35
|
+
} else if (event.type == BackgroundExecutionEventType.ProcessStarting) {
|
|
36
|
+
entry.params = event.data;
|
|
37
|
+
} else if (event.type == BackgroundExecutionEventType.ExecutionFailedError) {
|
|
38
|
+
const errors: string[] = event?.errors?.length ? event.errors : ['No-Error']; // DDB does not allow empty sets
|
|
39
|
+
entry.errors = errors;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await this.dynamo.simplePut(this.tableName, entry);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// NOTE: This is a psuedo-enum to fix some issues with Typescript enums. See: https://exploringjs.com/tackling-ts/ch_enum-alternatives.html for details
|
|
2
|
+
export const BackgroundExecutionEventType = {
|
|
3
|
+
ProcessStarting: 'ProcessStarting',
|
|
4
|
+
DataValidationError: 'DataValidationError',
|
|
5
|
+
ExecutionSuccessfullyComplete: 'ExecutionSuccessfullyComplete',
|
|
6
|
+
ExecutionFailedError: 'ExecutionRuntimeError',
|
|
7
|
+
NoMatchProcessorName: 'NoMatchProcessorName',
|
|
8
|
+
};
|
|
9
|
+
export type BackgroundExecutionEventType = (typeof BackgroundExecutionEventType)[keyof typeof BackgroundExecutionEventType];
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { Logger } from '@bitblit/ratchet-common/logger/logger';
|
|
2
|
+
import { ErrorRatchet } from '@bitblit/ratchet-common/lang/error-ratchet';
|
|
3
|
+
import { StringRatchet } from '@bitblit/ratchet-common/lang/string-ratchet';
|
|
4
|
+
import { StopWatch } from '@bitblit/ratchet-common/lang/stop-watch';
|
|
5
|
+
import { Context, ProxyResult, SNSEvent } from 'aws-lambda';
|
|
6
|
+
import { LambdaEventDetector } from '@bitblit/ratchet-aws/lambda/lambda-event-detector';
|
|
7
|
+
import { EpsilonConstants } from '../epsilon-constants.js';
|
|
8
|
+
import { ModelValidator } from '@bitblit/ratchet-misc/model-validator/model-validator';
|
|
9
|
+
import { BackgroundValidator } from './background-validator.js';
|
|
10
|
+
import { BackgroundConfig } from '../config/background/background-config.js';
|
|
11
|
+
import { BackgroundProcessor } from '../config/background/background-processor.js';
|
|
12
|
+
import { InternalBackgroundEntry } from './internal-background-entry.js';
|
|
13
|
+
import { BackgroundTransactionLog } from '../config/background/background-transaction-log.js';
|
|
14
|
+
import { BackgroundExecutionEvent } from './background-execution-event.js';
|
|
15
|
+
import { BackgroundExecutionListener } from './background-execution-listener.js';
|
|
16
|
+
import { BackgroundExecutionEventType } from './background-execution-event-type.js';
|
|
17
|
+
import { EpsilonLambdaEventHandler } from '../config/epsilon-lambda-event-handler.js';
|
|
18
|
+
import { ContextUtil } from '../util/context-util.js';
|
|
19
|
+
import { BackgroundManagerLike } from './manager/background-manager-like.js';
|
|
20
|
+
import { AbstractBackgroundManager } from './manager/abstract-background-manager.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* We use a FIFO queue so that 2 different Lambdas don't both work on the same
|
|
24
|
+
* thing at the same time.
|
|
25
|
+
*/
|
|
26
|
+
export class BackgroundHandler implements EpsilonLambdaEventHandler<SNSEvent> {
|
|
27
|
+
private processors: Map<string, BackgroundProcessor<any>>;
|
|
28
|
+
private validator: BackgroundValidator;
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
private cfg: BackgroundConfig,
|
|
32
|
+
private mgr: BackgroundManagerLike,
|
|
33
|
+
private modelValidator?: ModelValidator,
|
|
34
|
+
) {
|
|
35
|
+
const cfgErrors: string[] = BackgroundValidator.validateConfig(cfg);
|
|
36
|
+
if (cfgErrors.length > 0) {
|
|
37
|
+
ErrorRatchet.throwFormattedErr('Invalid background config : %j', cfgErrors);
|
|
38
|
+
}
|
|
39
|
+
Logger.silly('Starting Background processor, %d processors', cfg.processors.length);
|
|
40
|
+
this.validator = new BackgroundValidator(cfg, modelValidator);
|
|
41
|
+
this.processors = BackgroundValidator.validateAndMapProcessors(cfg.processors, modelValidator);
|
|
42
|
+
|
|
43
|
+
// If there is an immediate processing queue, wire me up to use it
|
|
44
|
+
if (mgr?.immediateProcessQueue && mgr.immediateProcessQueue()) {
|
|
45
|
+
Logger.info('Attaching to immediate processing queue');
|
|
46
|
+
mgr.immediateProcessQueue().subscribe(async (evt) => {
|
|
47
|
+
Logger.debug('Processing local background entry : %j', evt);
|
|
48
|
+
const rval: boolean = await this.processSingleBackgroundEntry(evt);
|
|
49
|
+
Logger.info('Processor returned %s', rval);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public get validProcessorNames(): string[] {
|
|
55
|
+
return this.processors ? Array.from(this.processors.keys()) : [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public extractLabel(evt: SNSEvent, _context: Context): string {
|
|
59
|
+
let rval: string = null;
|
|
60
|
+
if (this.isBackgroundStartSnsEvent(evt)) {
|
|
61
|
+
rval = 'BG:START-EVT';
|
|
62
|
+
} else if (this.isBackgroundImmediateFireEvent(evt)) {
|
|
63
|
+
const pEvt: InternalBackgroundEntry<any> = this.parseImmediateFireBackgroundEntry(evt);
|
|
64
|
+
rval = 'BG:' + pEvt.type + ':' + pEvt.guid;
|
|
65
|
+
} else {
|
|
66
|
+
rval = 'BG:UNKNOWN';
|
|
67
|
+
}
|
|
68
|
+
return rval;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public handlesEvent(evt: any): boolean {
|
|
72
|
+
return LambdaEventDetector.isValidSnsEvent(evt) && this.isBackgroundSNSEvent(evt);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public isBackgroundSNSEvent(event: any): boolean {
|
|
76
|
+
return this.isBackgroundStartSnsEvent(event) || this.isBackgroundImmediateFireEvent(event);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public isBackgroundStartSnsEvent(event: any): boolean {
|
|
80
|
+
let rval: boolean = false;
|
|
81
|
+
if (event) {
|
|
82
|
+
if (LambdaEventDetector.isSingleSnsEvent(event)) {
|
|
83
|
+
const cast: SNSEvent = event as SNSEvent;
|
|
84
|
+
rval = cast.Records[0].Sns.Message === EpsilonConstants.BACKGROUND_SNS_START_MARKER;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return rval;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public isBackgroundImmediateFireEvent(event: any): boolean {
|
|
91
|
+
let rval: boolean = false;
|
|
92
|
+
|
|
93
|
+
if (event) {
|
|
94
|
+
if (LambdaEventDetector.isSingleSnsEvent(event)) {
|
|
95
|
+
const cast: SNSEvent = event as SNSEvent;
|
|
96
|
+
const msg: string = cast.Records[0].Sns.Message;
|
|
97
|
+
if (StringRatchet.trimToNull(msg)) {
|
|
98
|
+
const parsed: any = JSON.parse(msg);
|
|
99
|
+
rval = !!parsed && parsed['type'] === EpsilonConstants.BACKGROUND_SNS_IMMEDIATE_RUN_FLAG;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return rval;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public parseImmediateFireBackgroundEntry(event: any): InternalBackgroundEntry<any> {
|
|
107
|
+
let rval: InternalBackgroundEntry<any> = null;
|
|
108
|
+
try {
|
|
109
|
+
if (event) {
|
|
110
|
+
if (LambdaEventDetector.isSingleSnsEvent(event)) {
|
|
111
|
+
const cast: SNSEvent = event as SNSEvent;
|
|
112
|
+
const msg: string = cast.Records[0].Sns.Message;
|
|
113
|
+
if (StringRatchet.trimToNull(msg)) {
|
|
114
|
+
const parsed: any = JSON.parse(msg);
|
|
115
|
+
if (!!parsed && parsed['type'] === EpsilonConstants.BACKGROUND_SNS_IMMEDIATE_RUN_FLAG) {
|
|
116
|
+
rval = parsed['backgroundEntry'];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
Logger.error('Could not parse %j as an immediate run event : %s', event, err, err);
|
|
123
|
+
}
|
|
124
|
+
return rval;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/*
|
|
128
|
+
public isBackgroundSqsMessage(message: AWS.SQS.Types.ReceiveMessageResult): boolean {
|
|
129
|
+
let rval: boolean = false;
|
|
130
|
+
if (message && message.Messages && message.Messages.length > 0) {
|
|
131
|
+
const missingFlagField: any = message.Messages.find((se) => {
|
|
132
|
+
try {
|
|
133
|
+
const parsed: any = JSON.parse(se.Body);
|
|
134
|
+
return !parsed[EpsilonConstants.BACKGROUND_SQS_TYPE_FIELD];
|
|
135
|
+
} catch (err) {
|
|
136
|
+
Logger.warn('Failed to parse message : %j %s', se, err);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
if (missingFlagField) {
|
|
141
|
+
Logger.silly('Found at least one message missing a type field');
|
|
142
|
+
} else {
|
|
143
|
+
rval = true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return rval;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
// Either trigger a pull of the SQS queue, or process immediately
|
|
152
|
+
|
|
153
|
+
public async processEvent(event: any, _context: Context): Promise<ProxyResult> {
|
|
154
|
+
let procd: number = null;
|
|
155
|
+
if (!this.isBackgroundStartSnsEvent(event)) {
|
|
156
|
+
const backgroundEntry: InternalBackgroundEntry<any> = this.parseImmediateFireBackgroundEntry(event);
|
|
157
|
+
if (backgroundEntry) {
|
|
158
|
+
Logger.silly('Processing immediate fire event : %j', backgroundEntry);
|
|
159
|
+
const result: boolean = await this.processSingleBackgroundEntry(backgroundEntry);
|
|
160
|
+
Logger.silly('Result was : %s', result);
|
|
161
|
+
procd = 1; // Process a single entry
|
|
162
|
+
} else {
|
|
163
|
+
Logger.warn('Tried to process non-background start / immediate event : %j returning false', event);
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
Logger.info('Reading task from background queue');
|
|
167
|
+
procd = await this.takeAndProcessSingleBackgroundQueueEntry();
|
|
168
|
+
if (procd > 0) {
|
|
169
|
+
Logger.info('Processed %d elements from background queue, refiring', procd);
|
|
170
|
+
const refire: string = await this.mgr.fireStartProcessingRequest();
|
|
171
|
+
Logger.info('Refire returned %s', refire);
|
|
172
|
+
} else {
|
|
173
|
+
Logger.info('No items processed - stopping');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const rval: ProxyResult = {
|
|
178
|
+
statusCode: 200,
|
|
179
|
+
body: StringRatchet.safeString(procd),
|
|
180
|
+
isBase64Encoded: false,
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
return rval;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private async takeAndProcessSingleBackgroundQueueEntry(): Promise<number> {
|
|
187
|
+
let rval: number = null;
|
|
188
|
+
const entries: InternalBackgroundEntry<any>[] = await this.mgr.takeEntryFromBackgroundQueue();
|
|
189
|
+
|
|
190
|
+
// Do them one at a time since Background is meant to throttle. Also, it should really
|
|
191
|
+
// only be one per pull anyway
|
|
192
|
+
Logger.info('Found %d entries - processing', entries.length);
|
|
193
|
+
for (const e of entries) {
|
|
194
|
+
//for (let i = 0; i < entries.length; i++) {
|
|
195
|
+
//const e: InternalBackgroundEntry<any> = entries[i];
|
|
196
|
+
const result: boolean = await this.processSingleBackgroundEntry(e);
|
|
197
|
+
rval += result ? 1 : 0;
|
|
198
|
+
}
|
|
199
|
+
Logger.debug('Returning %d', rval);
|
|
200
|
+
|
|
201
|
+
return rval;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private async safeWriteToLogger(entry: BackgroundTransactionLog): Promise<void> {
|
|
205
|
+
if (this.cfg.transactionLogger) {
|
|
206
|
+
try {
|
|
207
|
+
await this.cfg.transactionLogger.logTransaction(entry);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
Logger.error('Failed to write to transaction logger : %j : %s', entry, err, err);
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
Logger.silly('Skipping - no logger defined');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private async conditionallyStartTransactionLog(e: InternalBackgroundEntry<any>): Promise<void> {
|
|
217
|
+
if (!StringRatchet.trimToNull(e.guid)) {
|
|
218
|
+
Logger.warn('No guid found - creating');
|
|
219
|
+
e.guid = AbstractBackgroundManager.generateBackgroundGuid();
|
|
220
|
+
|
|
221
|
+
const log: BackgroundTransactionLog = {
|
|
222
|
+
request: e,
|
|
223
|
+
running: true,
|
|
224
|
+
};
|
|
225
|
+
await this.safeWriteToLogger(log);
|
|
226
|
+
}
|
|
227
|
+
Logger.debug('Starting transaction log');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private async conditionallyCompleteTransactionLog(
|
|
231
|
+
e: InternalBackgroundEntry<any>,
|
|
232
|
+
result: any,
|
|
233
|
+
error: any,
|
|
234
|
+
runtimeMS: number,
|
|
235
|
+
): Promise<void> {
|
|
236
|
+
Logger.debug('Completing transaction log');
|
|
237
|
+
const log: BackgroundTransactionLog = {
|
|
238
|
+
request: e,
|
|
239
|
+
result: result,
|
|
240
|
+
error: error ? ErrorRatchet.safeStringifyErr(error) : null,
|
|
241
|
+
running: false,
|
|
242
|
+
runtimeMS: runtimeMS,
|
|
243
|
+
};
|
|
244
|
+
await this.safeWriteToLogger(log);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private async conditionallyRunErrorProcessor(e: InternalBackgroundEntry<any>, error: any): Promise<void> {
|
|
248
|
+
try {
|
|
249
|
+
if (this.cfg.errorProcessor) {
|
|
250
|
+
Logger.info('Running error processor');
|
|
251
|
+
await this.cfg.errorProcessor.handleError(e, error);
|
|
252
|
+
}
|
|
253
|
+
} catch (err) {
|
|
254
|
+
Logger.error('Background : BAD - Failed to run error processor : %s', err, err);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private async fireListenerEvent(event: BackgroundExecutionEvent<any>) {
|
|
259
|
+
const listeners: BackgroundExecutionListener<any>[] = this.cfg.executionListeners || [];
|
|
260
|
+
for (const listener of listeners) {
|
|
261
|
+
try {
|
|
262
|
+
await listener.onEvent(event);
|
|
263
|
+
} catch (err) {
|
|
264
|
+
Logger.error('Failure triggering handler %s : %s', StringRatchet.trimToNull(listener?.label) || 'No-name', err);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// CAW 2020-08-08 : I am making processSingle public because there are times (such as when
|
|
270
|
+
// using AWS batch) that you want to be able to run a background command directly, eg, from
|
|
271
|
+
// the command line without needing an AWS-compliant event wrapping it. Thus, this.
|
|
272
|
+
public async processSingleBackgroundEntry(inE: InternalBackgroundEntry<any>): Promise<boolean> {
|
|
273
|
+
let e: InternalBackgroundEntry<any> = inE; // Just to make it clear the input parameter is invariant
|
|
274
|
+
// Set the trace ids appropriately
|
|
275
|
+
ContextUtil.setOverrideTraceFromInternalBackgroundEntry(e);
|
|
276
|
+
Logger.info('Background Process Start: %j', e);
|
|
277
|
+
const sw: StopWatch = new StopWatch();
|
|
278
|
+
await this.conditionallyStartTransactionLog(e);
|
|
279
|
+
if (this?.mgr?.modifyPayloadPreProcess) {
|
|
280
|
+
Logger.silly('Firing payload pre-process');
|
|
281
|
+
e = await this.mgr.modifyPayloadPreProcess(e);
|
|
282
|
+
}
|
|
283
|
+
let rval: boolean = false;
|
|
284
|
+
try {
|
|
285
|
+
await this.fireListenerEvent({
|
|
286
|
+
type: BackgroundExecutionEventType.ProcessStarting,
|
|
287
|
+
processorType: e.type,
|
|
288
|
+
data: e.data,
|
|
289
|
+
guid: e.guid,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
const processorInput: BackgroundProcessor<any> = this.processors.get(e.type);
|
|
293
|
+
if (!processorInput) {
|
|
294
|
+
ErrorRatchet.throwFormattedErr('Found no processor for background entry : %j (returning false)', e);
|
|
295
|
+
await this.fireListenerEvent({
|
|
296
|
+
type: BackgroundExecutionEventType.NoMatchProcessorName,
|
|
297
|
+
processorType: e.type,
|
|
298
|
+
data: e.data,
|
|
299
|
+
guid: e.guid,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
let dataValidationErrors: string[] = [];
|
|
304
|
+
if (StringRatchet.trimToNull(processorInput.dataSchemaName)) {
|
|
305
|
+
// If it was submitted through HTTP this was checked on the API side, but if they used the
|
|
306
|
+
// background manager directly (or direct-posted to SQS/SNS) that would have been bypassed. We'll double
|
|
307
|
+
// check here
|
|
308
|
+
dataValidationErrors = this.modelValidator.validate(processorInput.dataSchemaName, e.data, false, false);
|
|
309
|
+
}
|
|
310
|
+
if (dataValidationErrors.length > 0) {
|
|
311
|
+
await this.fireListenerEvent({
|
|
312
|
+
type: BackgroundExecutionEventType.DataValidationError,
|
|
313
|
+
processorType: e.type,
|
|
314
|
+
data: e.data,
|
|
315
|
+
errors: dataValidationErrors,
|
|
316
|
+
guid: e.guid,
|
|
317
|
+
});
|
|
318
|
+
ErrorRatchet.throwFormattedErr('Not processing, data failed validation; entry was %j : errors : %j', e, dataValidationErrors);
|
|
319
|
+
} else {
|
|
320
|
+
let result: any = await processorInput.handleEvent(e.data, this.mgr);
|
|
321
|
+
result = result || 'SUCCESSFUL COMPLETION : NO RESULT RETURNED';
|
|
322
|
+
await this.conditionallyCompleteTransactionLog(e, result, null, sw.elapsedMS());
|
|
323
|
+
await this.fireListenerEvent({
|
|
324
|
+
type: BackgroundExecutionEventType.ExecutionSuccessfullyComplete,
|
|
325
|
+
processorType: e.type,
|
|
326
|
+
data: result,
|
|
327
|
+
guid: e.guid,
|
|
328
|
+
});
|
|
329
|
+
rval = true;
|
|
330
|
+
}
|
|
331
|
+
} catch (err) {
|
|
332
|
+
Logger.error('Background Process Error: %j : %s', e, err, err);
|
|
333
|
+
await this.conditionallyRunErrorProcessor(e, err);
|
|
334
|
+
await this.conditionallyCompleteTransactionLog(e, null, err, sw.elapsedMS());
|
|
335
|
+
await this.fireListenerEvent({
|
|
336
|
+
type: BackgroundExecutionEventType.ExecutionFailedError,
|
|
337
|
+
processorType: e.type,
|
|
338
|
+
data: e.data,
|
|
339
|
+
errors: [ErrorRatchet.safeStringifyErr(err)],
|
|
340
|
+
guid: e.guid,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
Logger.info('Background Process Stop: %j : %s', e, sw.dump());
|
|
344
|
+
return rval;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Returns a copy so you cannot modify the internal one here
|
|
348
|
+
public getConfig(): BackgroundConfig {
|
|
349
|
+
const rval: BackgroundConfig = Object.assign({}, this.cfg);
|
|
350
|
+
return rval;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Logger } from '@bitblit/ratchet-common/logger/logger';
|
|
2
|
+
import { BackgroundEntry } from './background-entry.js';
|
|
3
|
+
import { Context } from 'aws-lambda';
|
|
4
|
+
import { ExtendedAPIGatewayEvent } from '../config/http/extended-api-gateway-event.js';
|
|
5
|
+
import { BackgroundQueueResponseInternal } from './background-queue-response-internal.js';
|
|
6
|
+
import { BackgroundProcessHandling } from './background-process-handling.js';
|
|
7
|
+
import { BackgroundConfig } from '../config/background/background-config.js';
|
|
8
|
+
import { ModelValidator } from '@bitblit/ratchet-misc/model-validator/model-validator';
|
|
9
|
+
import { BadRequestError } from '../http/error/bad-request-error.js';
|
|
10
|
+
import { BackgroundProcessor } from '../config/background/background-processor.js';
|
|
11
|
+
import { BackgroundMetaResponseInternal } from './background-meta-response-internal.js';
|
|
12
|
+
import { BackgroundTransactionLog } from '../config/background/background-transaction-log.js';
|
|
13
|
+
import { NotFoundError } from '../http/error/not-found-error.js';
|
|
14
|
+
import { BackgroundManagerLike } from './manager/background-manager-like.js';
|
|
15
|
+
import { PromiseRatchet } from '@bitblit/ratchet-common/lang/promise-ratchet';
|
|
16
|
+
import { StringRatchet } from '@bitblit/ratchet-common/lang/string-ratchet';
|
|
17
|
+
import { StopWatch } from '@bitblit/ratchet-common/lang/stop-watch';
|
|
18
|
+
import { BooleanRatchet } from '@bitblit/ratchet-common/lang/boolean-ratchet';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* We use a FIFO queue so that 2 different Lambdas don't both work on the same
|
|
22
|
+
* thing at the same time.
|
|
23
|
+
*/
|
|
24
|
+
export class BackgroundHttpAdapterHandler {
|
|
25
|
+
constructor(
|
|
26
|
+
private backgroundConfig: BackgroundConfig,
|
|
27
|
+
private modelValidator: ModelValidator,
|
|
28
|
+
private backgroundManager: BackgroundManagerLike,
|
|
29
|
+
private maxWaitInMsForBackgroundJobToStart: number = 10_000,
|
|
30
|
+
) {}
|
|
31
|
+
|
|
32
|
+
public get httpMetaEndpoint(): string {
|
|
33
|
+
return this.backgroundConfig.httpMetaEndpoint;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public get httpSubmissionPath(): string {
|
|
37
|
+
return this.backgroundConfig.httpSubmissionPath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public get httpStatusPath(): string {
|
|
41
|
+
return this.backgroundConfig.httpStatusEndpoint;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public get implyTypeFromPathSuffix(): boolean {
|
|
45
|
+
return this.backgroundConfig.implyTypeFromPathSuffix;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async handleBackgroundStatusRequest(evt: ExtendedAPIGatewayEvent, _context: Context): Promise<BackgroundTransactionLog> {
|
|
49
|
+
Logger.info('handleBackgroundStatusRequest called');
|
|
50
|
+
if (!this.backgroundConfig.transactionLogger) {
|
|
51
|
+
throw new BadRequestError('Process logging not enabled');
|
|
52
|
+
} else {
|
|
53
|
+
const guid: string =
|
|
54
|
+
StringRatchet.trimToNull(evt.pathParameters['guid']) || StringRatchet.trimToNull(evt.queryStringParameters['guid']);
|
|
55
|
+
if (guid) {
|
|
56
|
+
const sw: StopWatch = new StopWatch();
|
|
57
|
+
let log: BackgroundTransactionLog = null;
|
|
58
|
+
while (!log && sw.elapsedMS() < this.maxWaitInMsForBackgroundJobToStart) {
|
|
59
|
+
log = await this.backgroundConfig.transactionLogger.readTransactionLog(guid);
|
|
60
|
+
if (!log) {
|
|
61
|
+
Logger.debug(
|
|
62
|
+
'No log found yet, waiting 500 ms and retrying (%s of %d waited so far)',
|
|
63
|
+
sw.dump(),
|
|
64
|
+
this.maxWaitInMsForBackgroundJobToStart,
|
|
65
|
+
);
|
|
66
|
+
await PromiseRatchet.wait(500);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!log) {
|
|
71
|
+
throw new NotFoundError().withFormattedErrorMessage('No background result found for guid %s', guid);
|
|
72
|
+
}
|
|
73
|
+
return log;
|
|
74
|
+
} else {
|
|
75
|
+
throw new BadRequestError('No guid specified');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public async handleBackgroundMetaRequest(_evt: ExtendedAPIGatewayEvent, _context: Context): Promise<BackgroundMetaResponseInternal> {
|
|
81
|
+
Logger.info('handleBackgroundMetaRequest called');
|
|
82
|
+
const currentCount: number = await this.backgroundManager.fetchApproximateNumberOfQueueEntries();
|
|
83
|
+
const valid: string[] = this.backgroundConfig.processors.map((b) => b.typeName).filter((a) => !!a);
|
|
84
|
+
valid.sort((a, b) => a.localeCompare(b));
|
|
85
|
+
const rval: BackgroundMetaResponseInternal = {
|
|
86
|
+
currentQueueLength: currentCount,
|
|
87
|
+
validTypes: valid,
|
|
88
|
+
backgroundManagerName: this.backgroundManager.backgroundManagerName,
|
|
89
|
+
};
|
|
90
|
+
return rval;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public async handleBackgroundSubmission(evt: ExtendedAPIGatewayEvent, _context: Context): Promise<BackgroundQueueResponseInternal> {
|
|
94
|
+
Logger.info('handleBackgroundSubmission : %j (mgr:%s)', evt.parsedBody, this.backgroundManager.backgroundManagerName);
|
|
95
|
+
|
|
96
|
+
let rval: BackgroundQueueResponseInternal = null;
|
|
97
|
+
|
|
98
|
+
const startIdx: number = evt.path.indexOf(this.httpSubmissionPath) + this.httpSubmissionPath.length;
|
|
99
|
+
let pathSuppliedBackgroundType: string = this.backgroundConfig.implyTypeFromPathSuffix
|
|
100
|
+
? evt.path.substring(startIdx).split('-').join('').toLowerCase()
|
|
101
|
+
: '';
|
|
102
|
+
// Strip any query params or fragments
|
|
103
|
+
if (pathSuppliedBackgroundType.includes('?')) {
|
|
104
|
+
pathSuppliedBackgroundType = pathSuppliedBackgroundType.substring(0, pathSuppliedBackgroundType.indexOf('?'));
|
|
105
|
+
}
|
|
106
|
+
if (pathSuppliedBackgroundType.includes('#')) {
|
|
107
|
+
pathSuppliedBackgroundType = pathSuppliedBackgroundType.substring(0, pathSuppliedBackgroundType.indexOf('#'));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const entry: BackgroundEntry<any> = evt.parsedBody || {}; // Many background submissions contain no body (pure triggers)
|
|
111
|
+
|
|
112
|
+
// So, either this was configured pathed (like xxx/background/{typename} or non-pathed
|
|
113
|
+
// like /xxx/background. If non-pathed, you must supply the type field in the body. If
|
|
114
|
+
// pathed, you must either NOT supply the type field in the body, since it'll be determined
|
|
115
|
+
// by the path, or the types must match
|
|
116
|
+
if (StringRatchet.trimToNull(pathSuppliedBackgroundType)) {
|
|
117
|
+
if (StringRatchet.trimToNull(entry?.type) && entry.type.toLocaleLowerCase() !== pathSuppliedBackgroundType.toLocaleLowerCase()) {
|
|
118
|
+
throw new BadRequestError('Background submission has type but does not match path supplied type');
|
|
119
|
+
} else {
|
|
120
|
+
entry.type = pathSuppliedBackgroundType;
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
// No path, must be in here
|
|
124
|
+
if (!StringRatchet.trimToNull(entry?.type)) {
|
|
125
|
+
throw new BadRequestError('Background submission missing type and not configured in pathed mode');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const foundProc: BackgroundProcessor<any> = this.backgroundConfig.processors.find(
|
|
130
|
+
(s) => s.typeName.toLowerCase() === entry.type.toLowerCase(),
|
|
131
|
+
);
|
|
132
|
+
const immediate: boolean = BooleanRatchet.parseBool(evt.queryStringParameters['immediate']);
|
|
133
|
+
const startProcessor: boolean = BooleanRatchet.parseBool(evt.queryStringParameters['startProcessor']);
|
|
134
|
+
|
|
135
|
+
if (foundProc) {
|
|
136
|
+
// Perform a validation (if this is a path-supplied type it probably already happened, but don't hurt to do it again)
|
|
137
|
+
// If you're worried about that, and you do path-typing, just don't have your processors set the dataModelName
|
|
138
|
+
if (StringRatchet.trimToNull(foundProc.dataSchemaName)) {
|
|
139
|
+
// I'm not allowing empty and extra properties here since this is a fully internally defined object
|
|
140
|
+
const errors: string[] = this.modelValidator.validate(foundProc.dataSchemaName, entry.data, false, false);
|
|
141
|
+
if (errors.length > 0) {
|
|
142
|
+
throw new BadRequestError().withErrors(errors);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let result: string = null;
|
|
147
|
+
if (immediate) {
|
|
148
|
+
result = await this.backgroundManager.fireImmediateProcessRequest(entry);
|
|
149
|
+
} else {
|
|
150
|
+
result = await this.backgroundManager.addEntryToQueue(entry, startProcessor);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
rval = {
|
|
154
|
+
processHandling: immediate ? BackgroundProcessHandling.Immediate : BackgroundProcessHandling.Queued,
|
|
155
|
+
startProcessorRequested: startProcessor,
|
|
156
|
+
success: true,
|
|
157
|
+
resultId: result,
|
|
158
|
+
error: null,
|
|
159
|
+
};
|
|
160
|
+
} else {
|
|
161
|
+
throw new BadRequestError().withFormattedErrorMessage('Could not find target background processor : %s', entry.type);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return rval;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// NOTE: This is a psuedo-enum to fix some issues with Typescript enums. See: https://exploringjs.com/tackling-ts/ch_enum-alternatives.html for details
|
|
2
|
+
export const BackgroundProcessHandling = {
|
|
3
|
+
Queued: 'Queued',
|
|
4
|
+
Immediate: 'Immediate',
|
|
5
|
+
};
|
|
6
|
+
export type BackgroundProcessHandling = (typeof BackgroundProcessHandling)[keyof typeof BackgroundProcessHandling];
|