@rainbow-o23/n3 0.1.21 → 1.0.23
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/README.md +23 -0
- package/index.cjs +63 -1
- package/index.js +63 -2
- package/lib/step/index.d.ts +1 -0
- package/lib/step/parallel-step-sets.d.ts +18 -0
- package/package.json +2 -2
- package/src/lib/step/index.ts +1 -0
- package/src/lib/step/parallel-step-sets.ts +92 -0
- package/src/lib/step/step-sets.ts +1 -1
- package/test/step/parallel-step.test.ts +25 -0
package/README.md
CHANGED
|
@@ -171,6 +171,29 @@ const RequestContent = {$content: content, $item: element, $semaphore};
|
|
|
171
171
|
If you need to terminate the loop prematurely, you just need to return the `$semaphore` signal from the request data. The loop will
|
|
172
172
|
automatically end, and the collected processing results will be gathered and returned as an array.
|
|
173
173
|
|
|
174
|
+
### Parallel
|
|
175
|
+
|
|
176
|
+
#### Constructor Parameters
|
|
177
|
+
|
|
178
|
+
| Name | Type | Default Value | Comments |
|
|
179
|
+
|-----------|-------------------------------------------------------------------|---------------|-----------------------------------------------|
|
|
180
|
+
| cloneData | ScriptFuncOrBody\<CloneDataFunc\<In, InFragment, EachInFragment>> | | Clone request data for each step. |
|
|
181
|
+
| race | boolean | false | Returns first settled result if race is true. |
|
|
182
|
+
|
|
183
|
+
The specified set of pipeline steps will be executed parallel, and
|
|
184
|
+
|
|
185
|
+
- All the execution results will be gathered into an array and returned when `race` is false,
|
|
186
|
+
- Returns the first settled result when `race` is true,
|
|
187
|
+
|
|
188
|
+
It is important to note that
|
|
189
|
+
|
|
190
|
+
- Each sub pipeline step will use the same request data, they share the same content memory address. So please be very
|
|
191
|
+
careful <span style='color: red;'>**NOT**</span> to attempt to modify the request data in the sub pipeline steps. Alternatively, you can
|
|
192
|
+
use `cloneData` to create a copy of the request data for each sub pipeline steps, so that request data operations can be modified in
|
|
193
|
+
certain sub pipeline steps without affecting other sub pipeline steps.
|
|
194
|
+
- The error handles of the `For Each` pipeline step will be used for each iteration of executing individual elements, rather than being
|
|
195
|
+
applied to the execution of the array as a whole.
|
|
196
|
+
|
|
174
197
|
### Trigger Pipeline
|
|
175
198
|
|
|
176
199
|
#### Constructor Parameters
|
package/index.cjs
CHANGED
|
@@ -701,7 +701,7 @@ class PipelineStepSets extends AbstractFragmentaryPipelineStep {
|
|
|
701
701
|
const request = await promise;
|
|
702
702
|
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
703
703
|
.execute(async () => {
|
|
704
|
-
this.
|
|
704
|
+
this.traceStepIn(traceId, step, request);
|
|
705
705
|
const response = await step.perform({ ...request, $context: { ...context, traceId } });
|
|
706
706
|
this.traceStepOut(traceId, step, response);
|
|
707
707
|
return this.returnOrContinueOrClear(request, response);
|
|
@@ -719,6 +719,67 @@ class AsyncPipelineStepSets extends PipelineStepSets {
|
|
|
719
719
|
}
|
|
720
720
|
}
|
|
721
721
|
|
|
722
|
+
class ParallelPipelineStepSets extends PipelineStepSets {
|
|
723
|
+
_cloneDataSnippet;
|
|
724
|
+
_cloneData;
|
|
725
|
+
_race;
|
|
726
|
+
constructor(options) {
|
|
727
|
+
super(options);
|
|
728
|
+
this._cloneDataSnippet = options.cloneData;
|
|
729
|
+
this._cloneData = Utils.createSyncFunction(this.getCloneDataSnippet(), {
|
|
730
|
+
createDefault: () => ($factor, _$request, _$helpers, _$) => {
|
|
731
|
+
return $factor;
|
|
732
|
+
},
|
|
733
|
+
getVariableNames: () => ['$factor', '$request', ...this.getHelpersVariableNames()],
|
|
734
|
+
error: (e) => {
|
|
735
|
+
this.getLogger().error(`Failed on create function for clone data, snippet is [${this.getCloneDataSnippet()}].`);
|
|
736
|
+
throw e;
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
this._race = options.race ?? false;
|
|
740
|
+
}
|
|
741
|
+
getCloneDataSnippet() {
|
|
742
|
+
return this._cloneDataSnippet;
|
|
743
|
+
}
|
|
744
|
+
raceOne() {
|
|
745
|
+
return this._race;
|
|
746
|
+
}
|
|
747
|
+
cloneDataForEach($factor, $request) {
|
|
748
|
+
if ($factor == null) {
|
|
749
|
+
return null;
|
|
750
|
+
}
|
|
751
|
+
const $helpers = this.getHelpers();
|
|
752
|
+
return this._cloneData($factor, $request, $helpers, $helpers);
|
|
753
|
+
}
|
|
754
|
+
async doPerform(data, request) {
|
|
755
|
+
return await this.performWithContext(request, async (request, context) => {
|
|
756
|
+
const { $context: { traceId } = {} } = request;
|
|
757
|
+
const steps = await this.createSteps();
|
|
758
|
+
const execute = () => {
|
|
759
|
+
return steps.map(async (step) => {
|
|
760
|
+
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
761
|
+
.execute(async () => {
|
|
762
|
+
const eachData = this.cloneDataForEach(data, request);
|
|
763
|
+
const eachRequest = { content: eachData, $context: { ...context, traceId } };
|
|
764
|
+
this.traceStepIn(traceId, step, request);
|
|
765
|
+
const response = await step.perform(eachRequest);
|
|
766
|
+
this.traceStepOut(traceId, step, response);
|
|
767
|
+
return response;
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
};
|
|
771
|
+
if (this.raceOne()) {
|
|
772
|
+
const response = await Promise.race(execute());
|
|
773
|
+
return response.content;
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
const responses = await Promise.all(execute());
|
|
777
|
+
return responses.map(response => response.content);
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
722
783
|
class EachPipelineStepSets extends PipelineStepSets {
|
|
723
784
|
_originalContentPropertyName;
|
|
724
785
|
_itemPropertyName;
|
|
@@ -2234,6 +2295,7 @@ exports.HttpUnknownErrorCode = HttpUnknownErrorCode;
|
|
|
2234
2295
|
exports.MssqlTypeOrmDatasource = MssqlTypeOrmDatasource;
|
|
2235
2296
|
exports.MysqlTypeOrmDatasource = MysqlTypeOrmDatasource;
|
|
2236
2297
|
exports.OracleTypeOrmDatasource = OracleTypeOrmDatasource;
|
|
2298
|
+
exports.ParallelPipelineStepSets = ParallelPipelineStepSets;
|
|
2237
2299
|
exports.PgsqlTypeOrmDatasource = PgsqlTypeOrmDatasource;
|
|
2238
2300
|
exports.PipelineStepSets = PipelineStepSets;
|
|
2239
2301
|
exports.RefPipelinePipelineStep = RefPipelinePipelineStep;
|
package/index.js
CHANGED
|
@@ -699,7 +699,7 @@ class PipelineStepSets extends AbstractFragmentaryPipelineStep {
|
|
|
699
699
|
const request = await promise;
|
|
700
700
|
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
701
701
|
.execute(async () => {
|
|
702
|
-
this.
|
|
702
|
+
this.traceStepIn(traceId, step, request);
|
|
703
703
|
const response = await step.perform({ ...request, $context: { ...context, traceId } });
|
|
704
704
|
this.traceStepOut(traceId, step, response);
|
|
705
705
|
return this.returnOrContinueOrClear(request, response);
|
|
@@ -717,6 +717,67 @@ class AsyncPipelineStepSets extends PipelineStepSets {
|
|
|
717
717
|
}
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
+
class ParallelPipelineStepSets extends PipelineStepSets {
|
|
721
|
+
_cloneDataSnippet;
|
|
722
|
+
_cloneData;
|
|
723
|
+
_race;
|
|
724
|
+
constructor(options) {
|
|
725
|
+
super(options);
|
|
726
|
+
this._cloneDataSnippet = options.cloneData;
|
|
727
|
+
this._cloneData = Utils.createSyncFunction(this.getCloneDataSnippet(), {
|
|
728
|
+
createDefault: () => ($factor, _$request, _$helpers, _$) => {
|
|
729
|
+
return $factor;
|
|
730
|
+
},
|
|
731
|
+
getVariableNames: () => ['$factor', '$request', ...this.getHelpersVariableNames()],
|
|
732
|
+
error: (e) => {
|
|
733
|
+
this.getLogger().error(`Failed on create function for clone data, snippet is [${this.getCloneDataSnippet()}].`);
|
|
734
|
+
throw e;
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
this._race = options.race ?? false;
|
|
738
|
+
}
|
|
739
|
+
getCloneDataSnippet() {
|
|
740
|
+
return this._cloneDataSnippet;
|
|
741
|
+
}
|
|
742
|
+
raceOne() {
|
|
743
|
+
return this._race;
|
|
744
|
+
}
|
|
745
|
+
cloneDataForEach($factor, $request) {
|
|
746
|
+
if ($factor == null) {
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
const $helpers = this.getHelpers();
|
|
750
|
+
return this._cloneData($factor, $request, $helpers, $helpers);
|
|
751
|
+
}
|
|
752
|
+
async doPerform(data, request) {
|
|
753
|
+
return await this.performWithContext(request, async (request, context) => {
|
|
754
|
+
const { $context: { traceId } = {} } = request;
|
|
755
|
+
const steps = await this.createSteps();
|
|
756
|
+
const execute = () => {
|
|
757
|
+
return steps.map(async (step) => {
|
|
758
|
+
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
759
|
+
.execute(async () => {
|
|
760
|
+
const eachData = this.cloneDataForEach(data, request);
|
|
761
|
+
const eachRequest = { content: eachData, $context: { ...context, traceId } };
|
|
762
|
+
this.traceStepIn(traceId, step, request);
|
|
763
|
+
const response = await step.perform(eachRequest);
|
|
764
|
+
this.traceStepOut(traceId, step, response);
|
|
765
|
+
return response;
|
|
766
|
+
});
|
|
767
|
+
});
|
|
768
|
+
};
|
|
769
|
+
if (this.raceOne()) {
|
|
770
|
+
const response = await Promise.race(execute());
|
|
771
|
+
return response.content;
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
const responses = await Promise.all(execute());
|
|
775
|
+
return responses.map(response => response.content);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
720
781
|
class EachPipelineStepSets extends PipelineStepSets {
|
|
721
782
|
_originalContentPropertyName;
|
|
722
783
|
_itemPropertyName;
|
|
@@ -2198,4 +2259,4 @@ class TypeOrmTransactionalPipelineStepSets extends PipelineStepSets {
|
|
|
2198
2259
|
}
|
|
2199
2260
|
}
|
|
2200
2261
|
|
|
2201
|
-
export { AbstractFragmentaryPipelineStep, AbstractTypeOrmBySQLPipelineStep, AbstractTypeOrmDataSource, AbstractTypeOrmLoadBySQLPipelineStep, AbstractTypeOrmPipelineStep, AsyncPipelineStepSets, BetterSqlite3TypeOrmDatasource, ConditionalPipelineStepSets, DEFAULT_TRANSACTION_NAME, DeletePropertyPipelineStep, ERR_EACH_FRAGMENT_NOT_ANY_ARRAY, ERR_FETCH_ERROR, ERR_PIPELINE_REF_NOT_EMPTY, ERR_PIPELINE_REF_NOT_FOUND, ERR_PIPELINE_STEP_CONDITIONAL_SNIPPET_NOT_EMPTY, ERR_PIPELINE_STEP_METHOD_NOT_SUPPORTED, ERR_PIPELINE_STEP_REF_NOT_EMPTY, ERR_PIPELINE_STEP_REF_NOT_FOUND, ERR_PIPELINE_STEP_SNIPPET_NOT_EMPTY, ERR_TYPEORM_DATASOURCE_CREATOR_NOT_FOUND, ERR_TYPEORM_DATASOURCE_NOT_FOUND, ERR_TYPEORM_DATASOURCE_TYPE_NOT_FOUND, ERR_TYPEORM_ENTITY_NOT_FOUND, ERR_TYPEORM_SQL_NOT_EMPTY, ERR_TYPEORM_STEP_SNIPPET_NOT_EMPTY, ERR_TYPEORM_TRANSACTION_NOT_FOUND, EachPipelineStepSets, FetchPipelineStep, GetPropertyPipelineStep, HttpAbortErrorCode, HttpUnknownErrorCode, MssqlTypeOrmDatasource, MysqlTypeOrmDatasource, OracleTypeOrmDatasource, ParsedSqlSegmentType, PgsqlTypeOrmDatasource, PipelineStepSets, RefPipelinePipelineStep, RefStepPipelineStep, RoutesPipelineStepSets, SnippetPipelineStep, SnowflakePipelineStep, SupportedDataSourceTypes, TypeOrmBulkSaveBySQLPipelineStep, TypeOrmBySnippetPipelineStep, TypeOrmDataSourceHelper, TypeOrmDataSourceManager, TypeOrmLoadEntityByIdPipelineStep, TypeOrmLoadManyBySQLPipelineStep, TypeOrmLoadOneBySQLPipelineStep, TypeOrmParsedSQLCache, TypeOrmSaveBySQLPipelineStep, TypeOrmSaveEntityPipelineStep, TypeOrmTransactionalPipelineStepSets, Utils };
|
|
2262
|
+
export { AbstractFragmentaryPipelineStep, AbstractTypeOrmBySQLPipelineStep, AbstractTypeOrmDataSource, AbstractTypeOrmLoadBySQLPipelineStep, AbstractTypeOrmPipelineStep, AsyncPipelineStepSets, BetterSqlite3TypeOrmDatasource, ConditionalPipelineStepSets, DEFAULT_TRANSACTION_NAME, DeletePropertyPipelineStep, ERR_EACH_FRAGMENT_NOT_ANY_ARRAY, ERR_FETCH_ERROR, ERR_PIPELINE_REF_NOT_EMPTY, ERR_PIPELINE_REF_NOT_FOUND, ERR_PIPELINE_STEP_CONDITIONAL_SNIPPET_NOT_EMPTY, ERR_PIPELINE_STEP_METHOD_NOT_SUPPORTED, ERR_PIPELINE_STEP_REF_NOT_EMPTY, ERR_PIPELINE_STEP_REF_NOT_FOUND, ERR_PIPELINE_STEP_SNIPPET_NOT_EMPTY, ERR_TYPEORM_DATASOURCE_CREATOR_NOT_FOUND, ERR_TYPEORM_DATASOURCE_NOT_FOUND, ERR_TYPEORM_DATASOURCE_TYPE_NOT_FOUND, ERR_TYPEORM_ENTITY_NOT_FOUND, ERR_TYPEORM_SQL_NOT_EMPTY, ERR_TYPEORM_STEP_SNIPPET_NOT_EMPTY, ERR_TYPEORM_TRANSACTION_NOT_FOUND, EachPipelineStepSets, FetchPipelineStep, GetPropertyPipelineStep, HttpAbortErrorCode, HttpUnknownErrorCode, MssqlTypeOrmDatasource, MysqlTypeOrmDatasource, OracleTypeOrmDatasource, ParallelPipelineStepSets, ParsedSqlSegmentType, PgsqlTypeOrmDatasource, PipelineStepSets, RefPipelinePipelineStep, RefStepPipelineStep, RoutesPipelineStepSets, SnippetPipelineStep, SnowflakePipelineStep, SupportedDataSourceTypes, TypeOrmBulkSaveBySQLPipelineStep, TypeOrmBySnippetPipelineStep, TypeOrmDataSourceHelper, TypeOrmDataSourceManager, TypeOrmLoadEntityByIdPipelineStep, TypeOrmLoadManyBySQLPipelineStep, TypeOrmLoadOneBySQLPipelineStep, TypeOrmParsedSQLCache, TypeOrmSaveBySQLPipelineStep, TypeOrmSaveEntityPipelineStep, TypeOrmTransactionalPipelineStepSets, Utils };
|
package/lib/step/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './utils';
|
|
|
3
3
|
export * from './abstract-fragmentary-pipeline-step';
|
|
4
4
|
export * from './step-sets';
|
|
5
5
|
export * from './async-step-sets';
|
|
6
|
+
export * from './parallel-step-sets';
|
|
6
7
|
export * from './each-step-sets';
|
|
7
8
|
export * from './conditional-step-sets';
|
|
8
9
|
export * from './routes-step-sets';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PipelineStepData, PipelineStepHelpers, PipelineStepPayload } from '@rainbow-o23/n1';
|
|
2
|
+
import { PipelineStepSets, PipelineStepSetsOptions } from './step-sets';
|
|
3
|
+
import { ScriptFuncOrBody } from './types';
|
|
4
|
+
export type CloneDataFunc<In, InFragment, EachInFragment = InFragment> = ($factor: InFragment, $request: PipelineStepData<In>, $helpers: PipelineStepHelpers, $: PipelineStepHelpers) => EachInFragment;
|
|
5
|
+
export interface ParallelPipelineStepSetsOptions<In = PipelineStepPayload, Out = PipelineStepPayload, InFragment = In, OutFragment = Out, EachInFragment = InFragment> extends PipelineStepSetsOptions<In, Out, InFragment, OutFragment> {
|
|
6
|
+
cloneData?: ScriptFuncOrBody<CloneDataFunc<In, InFragment, EachInFragment>>;
|
|
7
|
+
race?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class ParallelPipelineStepSets<In = PipelineStepPayload, Out = PipelineStepPayload, InFragment = In, OutFragment = Out, EachInFragment = InFragment> extends PipelineStepSets<In, Out, InFragment, OutFragment> {
|
|
10
|
+
private readonly _cloneDataSnippet;
|
|
11
|
+
private readonly _cloneData;
|
|
12
|
+
private readonly _race;
|
|
13
|
+
constructor(options: ParallelPipelineStepSetsOptions<In, Out, InFragment, OutFragment, EachInFragment>);
|
|
14
|
+
getCloneDataSnippet(): ScriptFuncOrBody<CloneDataFunc<In, InFragment, EachInFragment>>;
|
|
15
|
+
raceOne(): boolean;
|
|
16
|
+
protected cloneDataForEach($factor: InFragment, $request: PipelineStepData<In>): EachInFragment;
|
|
17
|
+
protected doPerform(data: InFragment, request: PipelineStepData<In>): Promise<OutFragment>;
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rainbow-o23/n3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "o23 pipelines",
|
|
5
5
|
"main": "index.cjs",
|
|
6
6
|
"module": "index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"url": "https://github.com/InsureMO/rainbow-o23/issues"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@rainbow-o23/n1": "0.
|
|
24
|
+
"@rainbow-o23/n1": "1.0.23",
|
|
25
25
|
"@theinternetfolks/snowflake": "^1.3.0",
|
|
26
26
|
"node-fetch": "2.6.7",
|
|
27
27
|
"typeorm": "^0.3.17"
|
package/src/lib/step/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './abstract-fragmentary-pipeline-step';
|
|
|
5
5
|
|
|
6
6
|
export * from './step-sets';
|
|
7
7
|
export * from './async-step-sets';
|
|
8
|
+
export * from './parallel-step-sets';
|
|
8
9
|
export * from './each-step-sets';
|
|
9
10
|
export * from './conditional-step-sets';
|
|
10
11
|
export * from './routes-step-sets';
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import {PipelineStepData, PipelineStepHelpers, PipelineStepPayload} from '@rainbow-o23/n1';
|
|
2
|
+
import {PipelineStepSets, PipelineStepSetsContext, PipelineStepSetsOptions} from './step-sets';
|
|
3
|
+
import {ScriptFuncOrBody} from './types';
|
|
4
|
+
import {Utils} from './utils';
|
|
5
|
+
|
|
6
|
+
export type CloneDataFunc<In, InFragment, EachInFragment = InFragment> = ($factor: InFragment, $request: PipelineStepData<In>, $helpers: PipelineStepHelpers, $: PipelineStepHelpers) => EachInFragment;
|
|
7
|
+
|
|
8
|
+
export interface ParallelPipelineStepSetsOptions<In = PipelineStepPayload, Out = PipelineStepPayload, InFragment = In, OutFragment = Out, EachInFragment = InFragment>
|
|
9
|
+
extends PipelineStepSetsOptions<In, Out, InFragment, OutFragment> {
|
|
10
|
+
cloneData?: ScriptFuncOrBody<CloneDataFunc<In, InFragment, EachInFragment>>;
|
|
11
|
+
race?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* pipeline steps to execute sets of steps parallel.
|
|
16
|
+
*/
|
|
17
|
+
export class ParallelPipelineStepSets<In = PipelineStepPayload, Out = PipelineStepPayload, InFragment = In, OutFragment = Out, EachInFragment = InFragment>
|
|
18
|
+
extends PipelineStepSets<In, Out, InFragment, OutFragment> {
|
|
19
|
+
private readonly _cloneDataSnippet: ScriptFuncOrBody<CloneDataFunc<In, InFragment, EachInFragment>>;
|
|
20
|
+
private readonly _cloneData: CloneDataFunc<In, InFragment, EachInFragment>;
|
|
21
|
+
private readonly _race: boolean;
|
|
22
|
+
|
|
23
|
+
public constructor(options: ParallelPipelineStepSetsOptions<In, Out, InFragment, OutFragment, EachInFragment>) {
|
|
24
|
+
super(options);
|
|
25
|
+
this._cloneDataSnippet = options.cloneData;
|
|
26
|
+
this._cloneData = Utils.createSyncFunction(this.getCloneDataSnippet(), {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28
|
+
createDefault: () => ($factor: InFragment, _$request: PipelineStepData<In>, _$helpers: PipelineStepHelpers, _$: PipelineStepHelpers): EachInFragment => {
|
|
29
|
+
return $factor as unknown as EachInFragment;
|
|
30
|
+
},
|
|
31
|
+
getVariableNames: () => ['$factor', '$request', ...this.getHelpersVariableNames()], //this.generateFromRequestVariableNames(),
|
|
32
|
+
error: (e: Error) => {
|
|
33
|
+
this.getLogger().error(`Failed on create function for clone data, snippet is [${this.getCloneDataSnippet()}].`);
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
this._race = options.race ?? false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public getCloneDataSnippet(): ScriptFuncOrBody<CloneDataFunc<In, InFragment, EachInFragment>> {
|
|
41
|
+
return this._cloneDataSnippet;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* returns true when only one needs to be retrieved
|
|
46
|
+
*/
|
|
47
|
+
public raceOne(): boolean {
|
|
48
|
+
return this._race;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* default get request content
|
|
53
|
+
*/
|
|
54
|
+
protected cloneDataForEach($factor: InFragment, $request: PipelineStepData<In>): EachInFragment {
|
|
55
|
+
if ($factor == null) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const $helpers = this.getHelpers();
|
|
59
|
+
return this._cloneData($factor, $request, $helpers, $helpers);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
protected async doPerform(data: InFragment, request: PipelineStepData<In>): Promise<OutFragment> {
|
|
63
|
+
return await this.performWithContext(
|
|
64
|
+
request, async (request: PipelineStepData<In>, context: PipelineStepSetsContext): Promise<OutFragment> => {
|
|
65
|
+
const {$context: {traceId} = {}} = request;
|
|
66
|
+
const steps = await this.createSteps();
|
|
67
|
+
const execute = () => {
|
|
68
|
+
return steps.map(async step => {
|
|
69
|
+
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
70
|
+
.execute(async () => {
|
|
71
|
+
const eachData = this.cloneDataForEach(data, request);
|
|
72
|
+
const eachRequest = {content: eachData, $context: {...context, traceId}};
|
|
73
|
+
this.traceStepIn(traceId, step, request);
|
|
74
|
+
const response = await step.perform(eachRequest);
|
|
75
|
+
this.traceStepOut(traceId, step, response);
|
|
76
|
+
// return
|
|
77
|
+
return response;
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
if (this.raceOne()) {
|
|
82
|
+
// race
|
|
83
|
+
const response = await Promise.race(execute());
|
|
84
|
+
return response.content as OutFragment;
|
|
85
|
+
} else {
|
|
86
|
+
// all
|
|
87
|
+
const responses = await Promise.all(execute());
|
|
88
|
+
return responses.map(response => response.content) as OutFragment;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -85,7 +85,7 @@ export class PipelineStepSets<In = PipelineStepPayload, Out = PipelineStepPayloa
|
|
|
85
85
|
const request = await promise;
|
|
86
86
|
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
87
87
|
.execute(async () => {
|
|
88
|
-
this.
|
|
88
|
+
this.traceStepIn(traceId, step, request);
|
|
89
89
|
const response = await step.perform({...request, $context: {...context, traceId}});
|
|
90
90
|
this.traceStepOut(traceId, step, response);
|
|
91
91
|
// if no response returned, keep using request for next
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {createConfig, createLogger, PipelineStep, PipelineStepBuilder, PipelineStepOptions} from '@rainbow-o23/n1';
|
|
2
|
+
import {ParallelPipelineStepSets, SnippetPipelineStep} from '../../src';
|
|
3
|
+
|
|
4
|
+
const logger = createLogger();
|
|
5
|
+
const config = createConfig(logger);
|
|
6
|
+
|
|
7
|
+
test('Parallel Pipeline Step Test #1, + 100', async () => {
|
|
8
|
+
const step = new ParallelPipelineStepSets({
|
|
9
|
+
config, logger, steps: [
|
|
10
|
+
new class implements PipelineStepBuilder {
|
|
11
|
+
async create(options?: PipelineStepOptions): Promise<PipelineStep> {
|
|
12
|
+
return new SnippetPipelineStep({config, logger, snippet: 'return $factor.base * 100;'});
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
new class implements PipelineStepBuilder {
|
|
16
|
+
async create(options?: PipelineStepOptions): Promise<PipelineStep> {
|
|
17
|
+
return new SnippetPipelineStep({config, logger, snippet: 'return $factor.base * 200;'});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
const request = {content: {base: 1}};
|
|
23
|
+
const response = await step.perform(request);
|
|
24
|
+
expect(response.content).toEqual([100, 200]);
|
|
25
|
+
});
|