@bitblit/ratchet-epsilon-common 6.1.172-alpha → 6.1.174-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/lib/built-in/http/apollo/epsilon-auto-directives.d.ts +8 -0
- package/lib/built-in/http/apollo/epsilon-auto-directives.js +43 -0
- package/lib/built-in/http/apollo/epsilon-auto-directives.js.map +1 -0
- package/lib/built-in/http/apollo/epsilon-background-processor-gql-bridge.d.ts +12 -0
- package/lib/built-in/http/apollo/epsilon-background-processor-gql-bridge.js +91 -0
- package/lib/built-in/http/apollo/epsilon-background-processor-gql-bridge.js.map +1 -0
- package/package.json +14 -10
- package/src/built-in/http/apollo/epsilon-auto-directives.ts +61 -0
- package/src/built-in/http/apollo/epsilon-background-processor-gql-bridge.ts +125 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GraphQLSchema } from "graphql";
|
|
2
|
+
export declare class EpsilonAutoDirectives {
|
|
3
|
+
private constructor();
|
|
4
|
+
static DIRECTIVE_GQL: string;
|
|
5
|
+
private static wrapWithAuthenticated;
|
|
6
|
+
private static wrapWithTimed;
|
|
7
|
+
static applyDirectiveDecorators(schema: GraphQLSchema): GraphQLSchema;
|
|
8
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mapSchema, MapperKind, getDirective } from "@graphql-tools/utils";
|
|
2
|
+
import { UnauthorizedError } from "../../../http/error/unauthorized-error.js";
|
|
3
|
+
export class EpsilonAutoDirectives {
|
|
4
|
+
constructor() { }
|
|
5
|
+
static DIRECTIVE_GQL = 'directive @ep_authenticated on FIELD_DEFINITION\n' +
|
|
6
|
+
'directive @ep_timed(name: String) on FIELD_DEFINITION\n';
|
|
7
|
+
static wrapWithAuthenticated(resolve) {
|
|
8
|
+
return async (parent, args, ctx, info) => {
|
|
9
|
+
if (!ctx.user)
|
|
10
|
+
throw new UnauthorizedError('No token provided');
|
|
11
|
+
return resolve(parent, args, ctx, info);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
static wrapWithTimed(resolve, name) {
|
|
15
|
+
return async (parent, args, ctx, info) => {
|
|
16
|
+
const label = name ?? `${info.parentType.name}.${info.fieldName}`;
|
|
17
|
+
const start = performance.now();
|
|
18
|
+
try {
|
|
19
|
+
return await resolve(parent, args, ctx, info);
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
const ms = performance.now() - start;
|
|
23
|
+
ctx.metrics?.timings?.push({ label, ms });
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
static applyDirectiveDecorators(schema) {
|
|
28
|
+
return mapSchema(schema, {
|
|
29
|
+
[MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName) => {
|
|
30
|
+
const originalResolve = fieldConfig.resolve ?? ((src) => src[fieldName]);
|
|
31
|
+
const auth = getDirective(schema, fieldConfig, "ep_authenticated")?.[0];
|
|
32
|
+
const timed = getDirective(schema, fieldConfig, "ep_timed")?.[0];
|
|
33
|
+
let resolve = originalResolve;
|
|
34
|
+
if (auth)
|
|
35
|
+
resolve = EpsilonAutoDirectives.wrapWithAuthenticated(resolve);
|
|
36
|
+
if (timed)
|
|
37
|
+
resolve = EpsilonAutoDirectives.wrapWithTimed(resolve, timed.name);
|
|
38
|
+
return { ...fieldConfig, resolve };
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=epsilon-auto-directives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epsilon-auto-directives.js","sourceRoot":"","sources":["../../../../src/built-in/http/apollo/epsilon-auto-directives.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAI9E,MAAM,OAAO,qBAAqB;IAGhC,gBAAuB,CAAC;IAEjB,MAAM,CAAC,aAAa,GAAG,mDAAmD;QAC/E,yDAAyD,CAAA;IAEnD,MAAM,CAAC,qBAAqB,CAAC,OAAmB;QACtD,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACvC,IAAI,CAAC,GAAG,CAAC,IAAI;gBAAE,MAAM,IAAI,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;YAChE,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,aAAa,CAAC,OAAmB,EAAE,IAAa;QAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACvC,MAAM,KAAK,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClE,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBACrC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,wBAAwB,CAAC,MAAqB;QAC1D,OAAO,SAAS,CAAC,MAAM,EAAE;YACvB,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE;gBAEpD,MAAM,eAAe,GAClB,WAAW,CAAC,OAAe,IAAI,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;gBAGjE,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAEzD,CAAC;gBACd,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAElD,CAAC;gBAEd,IAAI,OAAO,GAAG,eAAe,CAAC;gBAE9B,IAAI,IAAI;oBAAE,OAAO,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;gBACzE,IAAI,KAAK;oBAAE,OAAO,GAAG,qBAAqB,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAE9E,OAAO,EAAE,GAAG,WAAW,EAAE,OAAO,EAAE,CAAC;YACrC,CAAC;SACF,CAAC,CAAC;IACL,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AwsBatchRatchet } from "@bitblit/ratchet-aws/batch/aws-batch-ratchet";
|
|
2
|
+
import { BackgroundManagerLike } from "../../../background/manager/background-manager-like.ts";
|
|
3
|
+
type ResolverFn = (parent: any, args: any, ctx: any, info: any) => any;
|
|
4
|
+
export declare class EpsilonBackgroundProcessorGqlBridge {
|
|
5
|
+
private constructor();
|
|
6
|
+
static BRIDGE_TYPES: string;
|
|
7
|
+
static BRIDGE_MUTATIONS: string;
|
|
8
|
+
static BRIDGE_QUERIES: string;
|
|
9
|
+
static createStartBackgroundProcessResolver(awsBatchRatchet: AwsBatchRatchet, backgroundManager: BackgroundManagerLike): ResolverFn;
|
|
10
|
+
private static scheduleBackgroundTaskV1;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Logger } from "@bitblit/ratchet-common/logger/logger";
|
|
2
|
+
import { StringRatchet } from "@bitblit/ratchet-common/lang/string-ratchet";
|
|
3
|
+
import { DateTime } from "luxon";
|
|
4
|
+
import { Base64Ratchet } from "@bitblit/ratchet-common/lang/base64-ratchet";
|
|
5
|
+
import { ContextUtil } from "../../../util/context-util.js";
|
|
6
|
+
export class EpsilonBackgroundProcessorGqlBridge {
|
|
7
|
+
constructor() { }
|
|
8
|
+
static BRIDGE_TYPES = `
|
|
9
|
+
type EpsilonBackgroundProcessStatusRequest {
|
|
10
|
+
guid: String!
|
|
11
|
+
createdEpochMS: Int!
|
|
12
|
+
traceId: String
|
|
13
|
+
traceDepth: Int
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type EpsilonBackgroundProcessStatus {
|
|
17
|
+
request: EpsilonBackgroundProcessStatusRequest
|
|
18
|
+
running: Boolean
|
|
19
|
+
runtimeMS: Int
|
|
20
|
+
resultJson: String
|
|
21
|
+
error: String
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
input EpsilonBackgroundProcessStartRequest {
|
|
25
|
+
processName: String!
|
|
26
|
+
processDataJson: String
|
|
27
|
+
startMode: EpsilonBackgroundProcessStartMode!
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
enum EpsilonBackgroundProcessStartMode {
|
|
31
|
+
RunImmediate
|
|
32
|
+
LongRunning
|
|
33
|
+
EnqueueOnly
|
|
34
|
+
EnqueueAndStart
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
static BRIDGE_MUTATIONS = `
|
|
38
|
+
startBackgroundProcess(request: EpsilonBackgroundProcessStartRequest!): String @authenticated
|
|
39
|
+
`;
|
|
40
|
+
static BRIDGE_QUERIES = `
|
|
41
|
+
readBackgroundProcessStatus(guid: String!): EpsilonBackgroundProcessStatus @authenticated
|
|
42
|
+
`;
|
|
43
|
+
static createStartBackgroundProcessResolver(awsBatchRatchet, backgroundManager) {
|
|
44
|
+
const rval = async (root, { request }, _context) => {
|
|
45
|
+
Logger.info('epsilonStartBackgroundProcess : %j', request);
|
|
46
|
+
let rval = null;
|
|
47
|
+
const data = StringRatchet.trimToNull(request.processDataJson) ? JSON.parse(request.processDataJson) : {};
|
|
48
|
+
if (request.startMode === 'LongRunning') {
|
|
49
|
+
Logger.info('Running in AWS Batch');
|
|
50
|
+
Logger.info('Scheduling for batch : %j', data);
|
|
51
|
+
const resp = await EpsilonBackgroundProcessorGqlBridge.scheduleBackgroundTaskV1(awsBatchRatchet, request.processName, data);
|
|
52
|
+
Logger.info('Result of submission was %s', resp);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (request.startMode === 'RunImmediate') {
|
|
56
|
+
Logger.info('Running immediate');
|
|
57
|
+
rval = await backgroundManager
|
|
58
|
+
.fireImmediateProcessRequestByParts(request.processName, data);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const fireStartMessage = request.startMode === 'EnqueueAndStart';
|
|
62
|
+
Logger.info('Enqueueing, fire start = %s', fireStartMessage);
|
|
63
|
+
rval = await backgroundManager
|
|
64
|
+
.addEntryToQueueByParts(request.processName, data, request.startMode === 'EnqueueAndStart');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
Logger.info('Returning : %s', rval);
|
|
68
|
+
return rval;
|
|
69
|
+
};
|
|
70
|
+
return rval;
|
|
71
|
+
}
|
|
72
|
+
static async scheduleBackgroundTaskV1(awsBatch, taskName, data = {}) {
|
|
73
|
+
const jobName = `${awsBatch.defaultJobDefinition}-${taskName}_${DateTime.utc().toFormat('yyyy-MM-dd-HH-mm')}`;
|
|
74
|
+
const options = {
|
|
75
|
+
jobName: jobName,
|
|
76
|
+
jobDefinition: awsBatch.defaultJobDefinition,
|
|
77
|
+
jobQueue: awsBatch.defaultQueueName,
|
|
78
|
+
parameters: {
|
|
79
|
+
taskName: taskName,
|
|
80
|
+
taskDataBase64: Base64Ratchet.encodeStringToBase64String(JSON.stringify(data || {})),
|
|
81
|
+
taskMetaDataBase64: Base64Ratchet.encodeStringToBase64String('{}'),
|
|
82
|
+
traceId: ContextUtil.currentTraceId(),
|
|
83
|
+
traceDepth: StringRatchet.safeString(ContextUtil.currentTraceDepth() + 1),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
Logger.info('scheduleBackgroundTaskV3a : options: %j', options);
|
|
87
|
+
const rval = await awsBatch.scheduleJob(options);
|
|
88
|
+
return rval;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=epsilon-background-processor-gql-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epsilon-background-processor-gql-bridge.js","sourceRoot":"","sources":["../../../../src/built-in/http/apollo/epsilon-background-processor-gql-bridge.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitblit/ratchet-epsilon-common",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.174-alpha",
|
|
4
4
|
"description": "Tiny adapter to simplify building API gateway Lambda APIS",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"bin": {
|
|
@@ -67,10 +67,10 @@
|
|
|
67
67
|
"@aws-sdk/client-sns": "3.922.0",
|
|
68
68
|
"@aws-sdk/client-sqs": "3.922.0",
|
|
69
69
|
"@aws-sdk/types": "3.922.0",
|
|
70
|
-
"@bitblit/ratchet-aws": "6.1.
|
|
71
|
-
"@bitblit/ratchet-common": "6.1.
|
|
72
|
-
"@bitblit/ratchet-misc": "6.1.
|
|
73
|
-
"@bitblit/ratchet-node-only": "6.1.
|
|
70
|
+
"@bitblit/ratchet-aws": "6.1.174-alpha",
|
|
71
|
+
"@bitblit/ratchet-common": "6.1.174-alpha",
|
|
72
|
+
"@bitblit/ratchet-misc": "6.1.174-alpha",
|
|
73
|
+
"@bitblit/ratchet-node-only": "6.1.174-alpha",
|
|
74
74
|
"@smithy/abort-controller": "4.2.5",
|
|
75
75
|
"@smithy/smithy-client": "4.9.10",
|
|
76
76
|
"@smithy/util-waiter": "4.2.5",
|
|
@@ -87,10 +87,12 @@
|
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
89
|
"@apollo/server": "^5.2.0",
|
|
90
|
-
"@bitblit/ratchet-aws": "6.1.
|
|
91
|
-
"@bitblit/ratchet-common": "6.1.
|
|
92
|
-
"@bitblit/ratchet-misc": "6.1.
|
|
93
|
-
"@bitblit/ratchet-node-only": "6.1.
|
|
90
|
+
"@bitblit/ratchet-aws": "6.1.174-alpha",
|
|
91
|
+
"@bitblit/ratchet-common": "6.1.174-alpha",
|
|
92
|
+
"@bitblit/ratchet-misc": "6.1.174-alpha",
|
|
93
|
+
"@bitblit/ratchet-node-only": "6.1.174-alpha",
|
|
94
|
+
"@graphql-tools/schema": "^10.0.31",
|
|
95
|
+
"@graphql-tools/utils": "^11.0.0",
|
|
94
96
|
"graphql": "^16.12.0"
|
|
95
97
|
},
|
|
96
98
|
"peerDependenciesMeta": {
|
|
@@ -102,7 +104,9 @@
|
|
|
102
104
|
}
|
|
103
105
|
},
|
|
104
106
|
"devDependencies": {
|
|
105
|
-
"@apollo/server": "5.
|
|
107
|
+
"@apollo/server": "5.3.0",
|
|
108
|
+
"@graphql-tools/schema": "10.0.31",
|
|
109
|
+
"@graphql-tools/utils": "11.0.0",
|
|
106
110
|
"@types/aws-lambda": "8.10.159",
|
|
107
111
|
"aws-sdk-client-mock": "4.1.0",
|
|
108
112
|
"graphql": "16.12.0",
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { mapSchema, MapperKind, getDirective } from "@graphql-tools/utils";
|
|
2
|
+
import { GraphQLSchema } from "graphql";
|
|
3
|
+
import { UnauthorizedError } from "../../../http/error/unauthorized-error.ts";
|
|
4
|
+
|
|
5
|
+
type ResolverFn = (parent: any, args: any, ctx: any, info: any) => any;
|
|
6
|
+
|
|
7
|
+
export class EpsilonAutoDirectives {
|
|
8
|
+
// Prevent instantiation
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
10
|
+
private constructor() {}
|
|
11
|
+
|
|
12
|
+
public static DIRECTIVE_GQL = 'directive @ep_authenticated on FIELD_DEFINITION\n' +
|
|
13
|
+
'directive @ep_timed(name: String) on FIELD_DEFINITION\n'
|
|
14
|
+
|
|
15
|
+
private static wrapWithAuthenticated(resolve: ResolverFn): ResolverFn {
|
|
16
|
+
return async (parent, args, ctx, info) => {
|
|
17
|
+
if (!ctx.user) throw new UnauthorizedError('No token provided');
|
|
18
|
+
return resolve(parent, args, ctx, info);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private static wrapWithTimed(resolve: ResolverFn, name?: string): ResolverFn {
|
|
23
|
+
return async (parent, args, ctx, info) => {
|
|
24
|
+
const label = name ?? `${info.parentType.name}.${info.fieldName}`;
|
|
25
|
+
const start = performance.now();
|
|
26
|
+
try {
|
|
27
|
+
return await resolve(parent, args, ctx, info);
|
|
28
|
+
} finally {
|
|
29
|
+
const ms = performance.now() - start;
|
|
30
|
+
ctx.metrics?.timings?.push({ label, ms });
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public static applyDirectiveDecorators(schema: GraphQLSchema): GraphQLSchema {
|
|
36
|
+
return mapSchema(schema, {
|
|
37
|
+
[MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName) => {
|
|
38
|
+
//const nm = fieldConfig['name'];
|
|
39
|
+
const originalResolve: ResolverFn =
|
|
40
|
+
(fieldConfig.resolve as any) ?? ((src: any) => src[fieldName]);
|
|
41
|
+
|
|
42
|
+
// Read directives off the schema AST node
|
|
43
|
+
const auth = getDirective(schema, fieldConfig, "ep_authenticated")?.[0] as
|
|
44
|
+
| { role?: string }
|
|
45
|
+
| undefined;
|
|
46
|
+
const timed = getDirective(schema, fieldConfig, "ep_timed")?.[0] as
|
|
47
|
+
| { name?: string }
|
|
48
|
+
| undefined;
|
|
49
|
+
|
|
50
|
+
let resolve = originalResolve;
|
|
51
|
+
|
|
52
|
+
if (auth) resolve = EpsilonAutoDirectives.wrapWithAuthenticated(resolve);
|
|
53
|
+
if (timed) resolve = EpsilonAutoDirectives.wrapWithTimed(resolve, timed.name);
|
|
54
|
+
|
|
55
|
+
return { ...fieldConfig, resolve };
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { mapSchema, MapperKind, getDirective } from "@graphql-tools/utils";
|
|
2
|
+
import { GraphQLSchema } from "graphql";
|
|
3
|
+
import { UnauthorizedError } from "../../../http/error/unauthorized-error.ts";
|
|
4
|
+
import { Logger } from "@bitblit/ratchet-common/logger/logger";
|
|
5
|
+
import { StringRatchet } from "@bitblit/ratchet-common/lang/string-ratchet";
|
|
6
|
+
import {BatchClient, SubmitJobCommandInput, SubmitJobCommandOutput, SubmitJobResponse} from '@aws-sdk/client-batch';
|
|
7
|
+
import { AwsBatchRatchet } from "@bitblit/ratchet-aws/batch/aws-batch-ratchet";
|
|
8
|
+
import { BackgroundManagerLike } from "../../../background/manager/background-manager-like.ts";
|
|
9
|
+
import { DateTime } from "luxon";
|
|
10
|
+
import { Base64Ratchet } from "@bitblit/ratchet-common/lang/base64-ratchet";
|
|
11
|
+
import { ContextUtil } from "../../../util/context-util.ts";
|
|
12
|
+
|
|
13
|
+
type ResolverFn = (parent: any, args: any, ctx: any, info: any) => any;
|
|
14
|
+
|
|
15
|
+
export class EpsilonBackgroundProcessorGqlBridge {
|
|
16
|
+
// Prevent instantiation
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
18
|
+
private constructor() {}
|
|
19
|
+
|
|
20
|
+
public static BRIDGE_TYPES =
|
|
21
|
+
`
|
|
22
|
+
type EpsilonBackgroundProcessStatusRequest {
|
|
23
|
+
guid: String!
|
|
24
|
+
createdEpochMS: Int!
|
|
25
|
+
traceId: String
|
|
26
|
+
traceDepth: Int
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type EpsilonBackgroundProcessStatus {
|
|
30
|
+
request: EpsilonBackgroundProcessStatusRequest
|
|
31
|
+
running: Boolean
|
|
32
|
+
runtimeMS: Int
|
|
33
|
+
resultJson: String
|
|
34
|
+
error: String
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
input EpsilonBackgroundProcessStartRequest {
|
|
38
|
+
processName: String!
|
|
39
|
+
processDataJson: String
|
|
40
|
+
startMode: EpsilonBackgroundProcessStartMode!
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
enum EpsilonBackgroundProcessStartMode {
|
|
44
|
+
RunImmediate
|
|
45
|
+
LongRunning
|
|
46
|
+
EnqueueOnly
|
|
47
|
+
EnqueueAndStart
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
public static BRIDGE_MUTATIONS =
|
|
52
|
+
`
|
|
53
|
+
startBackgroundProcess(request: EpsilonBackgroundProcessStartRequest!): String @authenticated
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
public static BRIDGE_QUERIES =
|
|
57
|
+
`
|
|
58
|
+
readBackgroundProcessStatus(guid: String!): EpsilonBackgroundProcessStatus @authenticated
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
public static createStartBackgroundProcessResolver(awsBatchRatchet:AwsBatchRatchet, backgroundManager: BackgroundManagerLike): ResolverFn {
|
|
62
|
+
const rval: ResolverFn = async (root, { request }, _context) => {
|
|
63
|
+
//const requestCast: ParaTradeBackgroundProcessStartRequest = request;
|
|
64
|
+
Logger.info('epsilonStartBackgroundProcess : %j', request);
|
|
65
|
+
let rval: string = null;
|
|
66
|
+
const data: any = StringRatchet.trimToNull(request.processDataJson) ? JSON.parse(request.processDataJson) : {};
|
|
67
|
+
if (request.startMode === 'LongRunning') {
|
|
68
|
+
Logger.info('Running in AWS Batch');
|
|
69
|
+
Logger.info('Scheduling for batch : %j', data);
|
|
70
|
+
|
|
71
|
+
//const resp: SubmitJobCommandOutput = await this.startAwsBatchProcessor.scheduleBackgroundTaskV2(requestCast.processName, data);
|
|
72
|
+
const resp: SubmitJobCommandOutput = await EpsilonBackgroundProcessorGqlBridge.scheduleBackgroundTaskV1(
|
|
73
|
+
awsBatchRatchet,
|
|
74
|
+
request.processName,
|
|
75
|
+
data,
|
|
76
|
+
);
|
|
77
|
+
Logger.info('Result of submission was %s', resp);
|
|
78
|
+
} else {
|
|
79
|
+
if (request.startMode === 'RunImmediate') {
|
|
80
|
+
Logger.info('Running immediate');
|
|
81
|
+
rval = await backgroundManager
|
|
82
|
+
.fireImmediateProcessRequestByParts(request.processName, data);
|
|
83
|
+
} else {
|
|
84
|
+
const fireStartMessage: boolean = request.startMode === 'EnqueueAndStart';
|
|
85
|
+
Logger.info('Enqueueing, fire start = %s', fireStartMessage);
|
|
86
|
+
|
|
87
|
+
rval = await backgroundManager
|
|
88
|
+
.addEntryToQueueByParts(
|
|
89
|
+
request.processName,
|
|
90
|
+
data,
|
|
91
|
+
request.startMode === 'EnqueueAndStart',
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
Logger.info('Returning : %s', rval);
|
|
96
|
+
return rval;
|
|
97
|
+
}
|
|
98
|
+
return rval;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private static async scheduleBackgroundTaskV1(
|
|
102
|
+
awsBatch: AwsBatchRatchet,
|
|
103
|
+
taskName: string,
|
|
104
|
+
data: any = {},
|
|
105
|
+
): Promise<SubmitJobCommandOutput> {
|
|
106
|
+
const jobName: string = `${awsBatch.defaultJobDefinition}-${taskName}_${DateTime.utc().toFormat('yyyy-MM-dd-HH-mm')}`;
|
|
107
|
+
const options: SubmitJobCommandInput = {
|
|
108
|
+
jobName: jobName,
|
|
109
|
+
jobDefinition: awsBatch.defaultJobDefinition,
|
|
110
|
+
jobQueue: awsBatch.defaultQueueName,
|
|
111
|
+
parameters: {
|
|
112
|
+
taskName: taskName,
|
|
113
|
+
taskDataBase64: Base64Ratchet.encodeStringToBase64String(JSON.stringify(data || {})),
|
|
114
|
+
taskMetaDataBase64: Base64Ratchet.encodeStringToBase64String('{}'),
|
|
115
|
+
traceId: ContextUtil.currentTraceId(),
|
|
116
|
+
traceDepth: StringRatchet.safeString(ContextUtil.currentTraceDepth() + 1),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
Logger.info('scheduleBackgroundTaskV3a : options: %j', options);
|
|
120
|
+
const rval: SubmitJobCommandOutput = await awsBatch.scheduleJob(options);
|
|
121
|
+
return rval;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
}
|