1 | ;
|
2 | var task_resolve_1 = require("./task.resolve");
|
3 | var task_return_values_1 = require("./task.return.values");
|
4 | var Rx = require("rx");
|
5 | var debug = require("debug")("cb:task.runner");
|
6 | var _ = require("../lodash.custom");
|
7 | var once = require("once");
|
8 | var domain = require("domain");
|
9 | var TaskReportType;
|
10 | (function (TaskReportType) {
|
11 | TaskReportType[TaskReportType["start"] = "start"] = "start";
|
12 | TaskReportType[TaskReportType["end"] = "end"] = "end";
|
13 | TaskReportType[TaskReportType["error"] = "error"] = "error";
|
14 | })(TaskReportType = exports.TaskReportType || (exports.TaskReportType = {}));
|
15 | var TaskSkipReasons;
|
16 | (function (TaskSkipReasons) {
|
17 | TaskSkipReasons[TaskSkipReasons["SkipFlag"] = "SkipFlag"] = "SkipFlag";
|
18 | TaskSkipReasons[TaskSkipReasons["IfChanged"] = "IfChanged"] = "IfChanged";
|
19 | })(TaskSkipReasons = exports.TaskSkipReasons || (exports.TaskSkipReasons = {}));
|
20 | /**
|
21 | * This creates a wrapper around the actual function that will be run.
|
22 | * This done to allow the before/after reporting to work as expected for consumers
|
23 | */
|
24 | function time(scheduler) {
|
25 | return scheduler ? scheduler.now() : new Date().getTime();
|
26 | }
|
27 | exports.time = time;
|
28 | function createObservableFromSequenceItem(item, trigger, ctx) {
|
29 | var taskTrigger = _.assign({}, trigger, ctx.toJS());
|
30 | return Rx.Observable.create(function (observer) {
|
31 | var startTime = time(taskTrigger.config.scheduler);
|
32 | /**
|
33 | * Complete immediately if this item was marked
|
34 | * as 'skipped'
|
35 | */
|
36 | if (!taskTrigger.config.force && item.task.skipped) {
|
37 | var additionalStats = {
|
38 | skipped: true,
|
39 | skippedReason: TaskSkipReasons.SkipFlag
|
40 | };
|
41 | var stats_1 = getStartStats(startTime, additionalStats);
|
42 | observer.onNext(getTaskReport(TaskReportType.start, item, stats_1));
|
43 | observer.onNext(getTaskReport(TaskReportType.end, item, getEndStats(stats_1, startTime, additionalStats)));
|
44 | observer.onCompleted();
|
45 | return;
|
46 | }
|
47 | /**
|
48 | * Complete immediately if this item was marked
|
49 | * with an 'ifChanged' predicate
|
50 | */
|
51 | if (!taskTrigger.config.force && item.task.ifChanged.length && ctx.hasIn(["ifChanged"])) {
|
52 | var hasChanges = ctx
|
53 | .get("ifChanged")
|
54 | .filter(function (x) {
|
55 | return item.task.ifChanged.indexOf(x.get("userInput")) !== -1;
|
56 | })
|
57 | .some(function (x) { return x.get("changed"); });
|
58 | if (!hasChanges) {
|
59 | var additionalStats = {
|
60 | skipped: true,
|
61 | skippedReason: TaskSkipReasons.IfChanged
|
62 | };
|
63 | var stats_2 = getStartStats(startTime, additionalStats);
|
64 | observer.onNext(getTaskReport(TaskReportType.start, item, stats_2));
|
65 | observer.onNext(getTaskReport(TaskReportType.end, item, getEndStats(stats_2, startTime, additionalStats)));
|
66 | observer.onCompleted();
|
67 | return;
|
68 | }
|
69 | }
|
70 | /**
|
71 | * Timestamp when this task starts
|
72 | * @type {TaskStats}
|
73 | */
|
74 | var stats = getStartStats(startTime, { skipped: false });
|
75 | debug("> seqUID " + item.seqUID + " started");
|
76 | /**
|
77 | * Task started
|
78 | */
|
79 | observer.onNext(getTaskReport(TaskReportType.start, item, stats));
|
80 | /**
|
81 | * Exit after 1 second if we're in a 'dry run'
|
82 | */
|
83 | if (taskTrigger.config.dryRun) {
|
84 | return Rx.Observable
|
85 | .just("dryRun")
|
86 | .delay(taskTrigger.config.dryRunDuration, taskTrigger.config.scheduler)
|
87 | .do(function (_) {
|
88 | observer.onNext(getTaskReport(TaskReportType.end, item, getEndStats(stats, time(taskTrigger.config.scheduler))));
|
89 | observer.onCompleted();
|
90 | }).subscribe();
|
91 | }
|
92 | if (item.task.type === task_resolve_1.TaskTypes.InlineFunction
|
93 | || item.task.type === task_resolve_1.TaskTypes.ExternalTask
|
94 | || item.task.type === task_resolve_1.TaskTypes.Adaptor) {
|
95 | var argCount = item.factory.length;
|
96 | var cb_1 = once(function (err) {
|
97 | if (err) {
|
98 | observer.onError(err);
|
99 | return;
|
100 | }
|
101 | observer.onNext(getTaskReport(TaskReportType.end, item, getEndStats(stats, time(taskTrigger.config.scheduler))));
|
102 | observer.onCompleted();
|
103 | });
|
104 | var d_1 = domain.create();
|
105 | d_1.once("error", function (err) {
|
106 | cb_1(err);
|
107 | });
|
108 | var domainBoundFn = d_1.bind(item.factory.bind(null, item.options, taskTrigger));
|
109 | var done = function (err) {
|
110 | d_1.removeListener("error", function (err) {
|
111 | cb_1(err);
|
112 | });
|
113 | d_1.exit();
|
114 | return cb_1.apply(null, arguments);
|
115 | };
|
116 | var result = domainBoundFn(done);
|
117 | if (result) {
|
118 | var returns = task_return_values_1.default(result, done);
|
119 | /**
|
120 | * If the return value does not need to be consumed,
|
121 | * but it is IS a function, assume it's the tear-down logic
|
122 | * for this task - which also means it MUST signify completion
|
123 | * via the callback
|
124 | */
|
125 | if (!returns && typeof result === "function") {
|
126 | if (argCount >= 3) {
|
127 | return result;
|
128 | }
|
129 | else {
|
130 | done(new Error("You returned tear-down logic, but you never asked for the completion callback"));
|
131 | return;
|
132 | }
|
133 | }
|
134 | }
|
135 | else {
|
136 | /**
|
137 | * Assume sync function if nothing returned
|
138 | * and 3rd argument was not asked for
|
139 | */
|
140 | if (argCount < 3) {
|
141 | done();
|
142 | return;
|
143 | }
|
144 | }
|
145 | }
|
146 | }).catch(function (error) {
|
147 | /**
|
148 | * **--**--MAGIC--**--**
|
149 | * If a task throws an error of any kind, we want that error to propagate as normal,
|
150 | * but we want tp prepend an error report so that the error report can be observed
|
151 | * before the sequence ends.
|
152 | */
|
153 | return Rx.Observable.concat(Rx.Observable.just(getTaskErrorReport(item, getErrorStats(error, time(taskTrigger.config.scheduler)))), Rx.Observable.throw(error));
|
154 | });
|
155 | }
|
156 | exports.createObservableFromSequenceItem = createObservableFromSequenceItem;
|
157 | /**
|
158 | * Factory for TaskReports
|
159 | */
|
160 | function getTaskReport(type, item, stats) {
|
161 | return { type: type, item: item, stats: stats };
|
162 | }
|
163 | /**
|
164 | * Create a new stats object with startTime
|
165 | */
|
166 | function getStartStats(startTime, additional) {
|
167 | return _.assign({}, additional, {
|
168 | startTime: startTime,
|
169 | started: true,
|
170 | endTime: 0,
|
171 | duration: 0,
|
172 | completed: false,
|
173 | errors: []
|
174 | });
|
175 | }
|
176 | exports.getStartStats = getStartStats;
|
177 | /**
|
178 | * Create a new stats object with completed/duration flags etc
|
179 | */
|
180 | function getEndStats(stats, endTime, additional) {
|
181 | return _.assign({}, stats, additional, {
|
182 | endTime: endTime,
|
183 | duration: endTime - stats.startTime,
|
184 | completed: true
|
185 | });
|
186 | }
|
187 | /**
|
188 | * Factory for TaskReports that errored
|
189 | */
|
190 | function getTaskErrorReport(item, stats) {
|
191 | return { type: TaskReportType.error, item: item, stats: stats };
|
192 | }
|
193 | /**
|
194 | * Get basic stats for a task error
|
195 | */
|
196 | function getErrorStats(error, endTime) {
|
197 | if (error._cbError) {
|
198 | return {
|
199 | endTime: endTime,
|
200 | completed: false,
|
201 | errors: [error],
|
202 | cbError: true,
|
203 | cbExitCode: error._cbExitCode
|
204 | };
|
205 | }
|
206 | return {
|
207 | endTime: endTime,
|
208 | completed: false,
|
209 | errors: [error]
|
210 | };
|
211 | }
|
212 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5ydW5uZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdGFzay5ydW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUF5QztBQUl6QywyREFBb0Q7QUFHcEQsdUJBQWlDO0FBR2pDLElBQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBQ2pELElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBQ3RDLElBQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM3QixJQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7QUFzQ2pDLElBQVksY0FJWDtBQUpELFdBQVksY0FBYztJQUN0Qix5Q0FBYSxPQUFPLFdBQUEsQ0FBQTtJQUNwQix1Q0FBVyxLQUFLLFNBQUEsQ0FBQTtJQUNoQix5Q0FBYSxPQUFPLFdBQUEsQ0FBQTtBQUN4QixDQUFDLEVBSlcsY0FBYyxHQUFkLHNCQUFjLEtBQWQsc0JBQWMsUUFJekI7QUFFRCxJQUFZLGVBR1g7QUFIRCxXQUFZLGVBQWU7SUFDdkIsOENBQWdCLFVBQVUsY0FBQSxDQUFBO0lBQzFCLCtDQUFpQixXQUFXLGVBQUEsQ0FBQTtBQUNoQyxDQUFDLEVBSFcsZUFBZSxHQUFmLHVCQUFlLEtBQWYsdUJBQWUsUUFHMUI7QUFZRDs7O0dBR0c7QUFDSCxjQUFxQixTQUFVO0lBQzNCLE1BQU0sQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDOUQsQ0FBQztBQUZELG9CQUVDO0FBQ0QsMENBQWlELElBQWtCLEVBQUUsT0FBdUIsRUFBRSxHQUFlO0lBRXpHLElBQU0sV0FBVyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsSUFB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 |
\ | No newline at end of file |