@lage-run/scheduler 1.1.3 → 1.1.5

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/CHANGELOG.json CHANGED
@@ -2,7 +2,49 @@
2
2
  "name": "@lage-run/scheduler",
3
3
  "entries": [
4
4
  {
5
- "date": "Tue, 30 May 2023 18:19:19 GMT",
5
+ "date": "Wed, 21 Jun 2023 19:05:46 GMT",
6
+ "tag": "@lage-run/scheduler_v1.1.5",
7
+ "version": "1.1.5",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "author": "beachball",
12
+ "package": "@lage-run/scheduler",
13
+ "comment": "Bump @lage-run/hasher to v1.0.2",
14
+ "commit": "3efba30544ff1844986f469e01b47316d700ceeb"
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Thu, 15 Jun 2023 17:04:58 GMT",
21
+ "tag": "@lage-run/scheduler_v1.1.4",
22
+ "version": "1.1.4",
23
+ "comments": {
24
+ "patch": [
25
+ {
26
+ "author": "altinokd@microsoft.com",
27
+ "package": "@lage-run/scheduler",
28
+ "commit": "91dfab46c2cb13c175931f12f2964b2b9ace491a",
29
+ "comment": "Return value from worker run functions as part of TargetRun.result object. Encapsulated status and result fields. Added a way to reset WrappedTarget"
30
+ },
31
+ {
32
+ "author": "beachball",
33
+ "package": "@lage-run/scheduler",
34
+ "comment": "Bump @lage-run/config to v0.3.1",
35
+ "commit": "91dfab46c2cb13c175931f12f2964b2b9ace491a"
36
+ },
37
+ {
38
+ "author": "beachball",
39
+ "package": "@lage-run/scheduler",
40
+ "comment": "Bump @lage-run/scheduler-types to v0.3.10",
41
+ "commit": "91dfab46c2cb13c175931f12f2964b2b9ace491a"
42
+ }
43
+ ]
44
+ }
45
+ },
46
+ {
47
+ "date": "Tue, 30 May 2023 18:19:34 GMT",
6
48
  "tag": "@lage-run/scheduler_v1.1.3",
7
49
  "version": "1.1.3",
8
50
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,30 @@
1
1
  # Change Log - @lage-run/scheduler
2
2
 
3
- This log was last generated on Tue, 30 May 2023 18:19:19 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 21 Jun 2023 19:05:46 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.1.5
8
+
9
+ Wed, 21 Jun 2023 19:05:46 GMT
10
+
11
+ ### Patches
12
+
13
+ - Bump @lage-run/hasher to v1.0.2
14
+
15
+ ## 1.1.4
16
+
17
+ Thu, 15 Jun 2023 17:04:58 GMT
18
+
19
+ ### Patches
20
+
21
+ - Return value from worker run functions as part of TargetRun.result object. Encapsulated status and result fields. Added a way to reset WrappedTarget (altinokd@microsoft.com)
22
+ - Bump @lage-run/config to v0.3.1
23
+ - Bump @lage-run/scheduler-types to v0.3.10
24
+
7
25
  ## 1.1.3
8
26
 
9
- Tue, 30 May 2023 18:19:19 GMT
27
+ Tue, 30 May 2023 18:19:34 GMT
10
28
 
11
29
  ### Patches
12
30
 
@@ -3,6 +3,7 @@
3
3
  /// <reference types="global" />
4
4
  import { WrappedTarget } from "./WrappedTarget.js";
5
5
  import { TargetRunnerPicker } from "./runners/TargetRunnerPicker.js";
6
+ import type { WorkerResult } from "./WrappedTarget.js";
6
7
  import type { Logger } from "@lage-run/logger";
7
8
  import type { TargetGraph } from "@lage-run/target-graph";
8
9
  import type { TargetScheduler, SchedulerRunSummary } from "@lage-run/scheduler-types";
@@ -42,7 +43,7 @@ export interface SimpleSchedulerOptions {
42
43
  * 1. Allow for multiple kinds of runner (currently only ONE is supported, and it is applied to all targets)
43
44
  *
44
45
  */
45
- export declare class SimpleScheduler implements TargetScheduler {
46
+ export declare class SimpleScheduler implements TargetScheduler<WorkerResult> {
46
47
  #private;
47
48
  private options;
48
49
  targetRuns: Map<string, WrappedTarget>;
@@ -64,7 +65,7 @@ export declare class SimpleScheduler implements TargetScheduler {
64
65
  * @param targetGraph
65
66
  * @returns
66
67
  */
67
- run(root: string, targetGraph: TargetGraph, shouldRerun?: boolean): Promise<SchedulerRunSummary>;
68
+ run(root: string, targetGraph: TargetGraph, shouldRerun?: boolean): Promise<SchedulerRunSummary<WorkerResult>>;
68
69
  /**
69
70
  * Used by consumers of the scheduler to notify that the inputs to the target has changed
70
71
  * @param targetId
@@ -95,9 +95,6 @@ class SimpleScheduler {
95
95
  onMessage: this.options.onMessage
96
96
  });
97
97
  }
98
- if (target.id === (0, _targetgraph.getStartTargetId)()) {
99
- targetRun.status = "success";
100
- }
101
98
  this.targetRuns.set(target.id, targetRun);
102
99
  }
103
100
  let results = "failed";
@@ -143,7 +140,7 @@ class SimpleScheduler {
143
140
  if (this.targetRuns.has(current)) {
144
141
  const targetRun = this.targetRuns.get(current);
145
142
  if (targetRun.status !== "pending") {
146
- targetRun.status = "pending";
143
+ targetRun.reset();
147
144
  this.rerunTargets.add(targetRun.target.id);
148
145
  const dependents = targetRun.target.dependents;
149
146
  for (const dependent of dependents){
@@ -259,9 +256,7 @@ class SimpleScheduler {
259
256
  }
260
257
  async function generateTargetRunPromise(target) {
261
258
  let runError;
262
- if (target.result && target.successful && !this.rerunTargets.has(target.target.id)) {
263
- await target.result;
264
- } else {
259
+ if (!target.successful || this.rerunTargets.has(target.target.id)) {
265
260
  // This do-while loop only runs again if something causes this target to rerun (asynchronously triggering a re-run)
266
261
  do {
267
262
  this.rerunTargets.delete(target.target.id);
@@ -2,7 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import type { Pool } from "@lage-run/worker-threads-pool";
4
4
  import type { TargetRun, TargetStatus } from "@lage-run/scheduler-types";
5
- import type { Target } from "@lage-run/target-graph";
5
+ import { type Target } from "@lage-run/target-graph";
6
6
  import type { Logger } from "@lage-run/logger";
7
7
  import type { TargetHasher } from "@lage-run/hasher";
8
8
  import type { MessagePort } from "worker_threads";
@@ -17,11 +17,12 @@ export interface WrappedTargetOptions {
17
17
  hasher: TargetHasher;
18
18
  onMessage?: (message: any, postMessage: MessagePort["postMessage"]) => void;
19
19
  }
20
- interface WorkerResult {
20
+ export interface WorkerResult {
21
21
  stdoutBuffer: string;
22
22
  stderrBuffer: string;
23
23
  skipped: boolean;
24
24
  hash: string;
25
+ value: unknown;
25
26
  }
26
27
  /**
27
28
  * Wraps a target with additional functionality:
@@ -30,15 +31,16 @@ interface WorkerResult {
30
31
  * 3. Abort signal
31
32
  * 4. Continue on error
32
33
  */
33
- export declare class WrappedTarget implements TargetRun {
34
+ export declare class WrappedTarget implements TargetRun<WorkerResult> {
35
+ #private;
34
36
  options: WrappedTargetOptions;
35
37
  queueTime: [number, number];
36
38
  startTime: [number, number];
37
39
  duration: [number, number];
38
40
  target: Target;
39
- status: TargetStatus;
40
41
  threadId: number;
41
- result: Promise<WorkerResult> | undefined;
42
+ get result(): WorkerResult | undefined;
43
+ get status(): TargetStatus;
42
44
  get abortController(): AbortController;
43
45
  set abortController(abortController: AbortController);
44
46
  get successful(): boolean;
@@ -63,5 +65,8 @@ export declare class WrappedTarget implements TargetRun {
63
65
  target: string;
64
66
  status: TargetStatus;
65
67
  };
68
+ /**
69
+ * Reset the state of this wrapped target.
70
+ */
71
+ reset(): void;
66
72
  }
67
- export {};
@@ -14,6 +14,47 @@ const _logger = require("@lage-run/logger");
14
14
  const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
15
15
  const _path = /*#__PURE__*/ _interop_require_default(require("path"));
16
16
  const _promises = require("fs/promises");
17
+ const _targetgraph = require("@lage-run/target-graph");
18
+ function _check_private_redeclaration(obj, privateCollection) {
19
+ if (privateCollection.has(obj)) {
20
+ throw new TypeError("Cannot initialize the same private elements twice on an object");
21
+ }
22
+ }
23
+ function _class_apply_descriptor_get(receiver, descriptor) {
24
+ if (descriptor.get) {
25
+ return descriptor.get.call(receiver);
26
+ }
27
+ return descriptor.value;
28
+ }
29
+ function _class_apply_descriptor_set(receiver, descriptor, value) {
30
+ if (descriptor.set) {
31
+ descriptor.set.call(receiver, value);
32
+ } else {
33
+ if (!descriptor.writable) {
34
+ throw new TypeError("attempted to set read only private field");
35
+ }
36
+ descriptor.value = value;
37
+ }
38
+ }
39
+ function _class_extract_field_descriptor(receiver, privateMap, action) {
40
+ if (!privateMap.has(receiver)) {
41
+ throw new TypeError("attempted to " + action + " private field on non-instance");
42
+ }
43
+ return privateMap.get(receiver);
44
+ }
45
+ function _class_private_field_get(receiver, privateMap) {
46
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
47
+ return _class_apply_descriptor_get(receiver, descriptor);
48
+ }
49
+ function _class_private_field_init(obj, privateMap, value) {
50
+ _check_private_redeclaration(obj, privateMap);
51
+ privateMap.set(obj, value);
52
+ }
53
+ function _class_private_field_set(receiver, privateMap, value) {
54
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
55
+ _class_apply_descriptor_set(receiver, descriptor, value);
56
+ return value;
57
+ }
17
58
  function _define_property(obj, key, value) {
18
59
  if (key in obj) {
19
60
  Object.defineProperty(obj, key, {
@@ -32,7 +73,14 @@ function _interop_require_default(obj) {
32
73
  default: obj
33
74
  };
34
75
  }
76
+ var _status = /*#__PURE__*/ new WeakMap(), _result = /*#__PURE__*/ new WeakMap();
35
77
  class WrappedTarget {
78
+ get result() {
79
+ return _class_private_field_get(this, _result);
80
+ }
81
+ get status() {
82
+ return _class_private_field_get(this, _status);
83
+ }
36
84
  get abortController() {
37
85
  return this.options.abortController;
38
86
  }
@@ -40,17 +88,17 @@ class WrappedTarget {
40
88
  this.options.abortController = abortController;
41
89
  }
42
90
  get successful() {
43
- return this.status === "skipped" || this.status === "success";
91
+ return _class_private_field_get(this, _status) === "skipped" || _class_private_field_get(this, _status) === "success";
44
92
  }
45
93
  get waiting() {
46
- return this.status === "pending" || this.status === "queued";
94
+ return _class_private_field_get(this, _status) === "pending" || _class_private_field_get(this, _status) === "queued";
47
95
  }
48
96
  onQueued() {
49
- this.status = "queued";
97
+ _class_private_field_set(this, _status, "queued");
50
98
  this.queueTime = process.hrtime();
51
99
  }
52
100
  onAbort() {
53
- this.status = "aborted";
101
+ _class_private_field_set(this, _status, "aborted");
54
102
  this.duration = process.hrtime(this.startTime);
55
103
  this.options.logger.info("", {
56
104
  target: this.target,
@@ -61,7 +109,7 @@ class WrappedTarget {
61
109
  onStart(threadId) {
62
110
  if (this.status !== "running") {
63
111
  this.threadId = threadId;
64
- this.status = "running";
112
+ _class_private_field_set(this, _status, "running");
65
113
  this.startTime = process.hrtime();
66
114
  this.options.logger.info("", {
67
115
  target: this.target,
@@ -71,7 +119,7 @@ class WrappedTarget {
71
119
  }
72
120
  }
73
121
  onComplete() {
74
- this.status = "success";
122
+ _class_private_field_set(this, _status, "success");
75
123
  this.duration = process.hrtime(this.startTime);
76
124
  this.options.logger.info("", {
77
125
  target: this.target,
@@ -81,7 +129,7 @@ class WrappedTarget {
81
129
  });
82
130
  }
83
131
  onFail() {
84
- this.status = "failed";
132
+ _class_private_field_set(this, _status, "failed");
85
133
  this.duration = process.hrtime(this.startTime);
86
134
  this.options.logger.info("", {
87
135
  target: this.target,
@@ -97,7 +145,7 @@ class WrappedTarget {
97
145
  if (this.startTime[0] !== 0 && this.startTime[1] !== 0) {
98
146
  this.duration = process.hrtime(this.startTime);
99
147
  }
100
- this.status = "skipped";
148
+ _class_private_field_set(this, _status, "skipped");
101
149
  if (hash) {
102
150
  this.options.logger.info("", {
103
151
  target: this.target,
@@ -117,23 +165,23 @@ class WrappedTarget {
117
165
  return;
118
166
  }
119
167
  try {
120
- const result = await this.runInPool();
121
- const cacheEnabled = target.cache && shouldCache && result.hash;
168
+ _class_private_field_set(this, _result, await this.runInPool());
169
+ const cacheEnabled = target.cache && shouldCache && _class_private_field_get(this, _result).hash;
122
170
  // Save output if cache is enabled & cache is hit
123
- if (!result.skipped && cacheEnabled) {
124
- const outputLocation = (0, _getLageOutputCacheLocation.getLageOutputCacheLocation)(root, result.hash);
171
+ if (!_class_private_field_get(this, _result).skipped && cacheEnabled) {
172
+ const outputLocation = (0, _getLageOutputCacheLocation.getLageOutputCacheLocation)(root, _class_private_field_get(this, _result).hash);
125
173
  const outputPath = _path.default.dirname(outputLocation);
126
174
  await (0, _promises.mkdir)(outputPath, {
127
175
  recursive: true
128
176
  });
129
- const output = `${result.stdoutBuffer}\n${result.stderrBuffer}`;
177
+ const output = `${_class_private_field_get(this, _result).stdoutBuffer}\n${_class_private_field_get(this, _result).stderrBuffer}`;
130
178
  await (0, _promises.writeFile)(outputLocation, output);
131
- logger.verbose(`>> Saved cache - ${result.hash}`, {
179
+ logger.verbose(`>> Saved cache - ${_class_private_field_get(this, _result).hash}`, {
132
180
  target
133
181
  });
134
182
  }
135
- if (result.skipped) {
136
- const { hash } = result;
183
+ if (_class_private_field_get(this, _result).skipped) {
184
+ const { hash } = _class_private_field_get(this, _result);
137
185
  const cachedOutputFile = (0, _getLageOutputCacheLocation.getLageOutputCacheLocation)(root, hash ?? "");
138
186
  const shouldShowCachedOutput = _fs.default.existsSync(cachedOutputFile);
139
187
  if (shouldShowCachedOutput) {
@@ -169,7 +217,7 @@ class WrappedTarget {
169
217
  const bufferStdout = (0, _bufferTransform.bufferTransform)();
170
218
  const bufferStderr = (0, _bufferTransform.bufferTransform)();
171
219
  let msgHandler;
172
- this.result = pool.exec({
220
+ const result = await pool.exec({
173
221
  target
174
222
  }, target.weight ?? 1, (worker, stdout, stderr)=>{
175
223
  const postMessage = worker.postMessage.bind(worker);
@@ -216,12 +264,12 @@ class WrappedTarget {
216
264
  releaseStdout();
217
265
  releaseStderr();
218
266
  }, abortSignal);
219
- const result = await this.result;
220
267
  return {
221
268
  stdoutBuffer: bufferStdout.buffer,
222
269
  stderrBuffer: bufferStderr.buffer,
223
270
  skipped: result?.skipped,
224
- hash: result?.hash
271
+ hash: result?.hash,
272
+ value: result?.value
225
273
  };
226
274
  }
227
275
  /**
@@ -236,16 +284,29 @@ class WrappedTarget {
236
284
  status: this.status
237
285
  };
238
286
  }
287
+ /**
288
+ * Reset the state of this wrapped target.
289
+ */ reset() {
290
+ _class_private_field_set(this, _result, undefined);
291
+ _class_private_field_set(this, _status, "pending");
292
+ }
239
293
  constructor(options){
240
294
  _define_property(this, "options", void 0);
295
+ _class_private_field_init(this, _status, {
296
+ writable: true,
297
+ value: void 0
298
+ });
299
+ _class_private_field_init(this, _result, {
300
+ writable: true,
301
+ value: void 0
302
+ });
241
303
  _define_property(this, "queueTime", void 0);
242
304
  _define_property(this, "startTime", void 0);
243
305
  _define_property(this, "duration", void 0);
244
306
  _define_property(this, "target", void 0);
245
- _define_property(this, "status", void 0);
246
307
  _define_property(this, "threadId", void 0);
247
- _define_property(this, "result", void 0);
248
308
  this.options = options;
309
+ _class_private_field_set(this, _status, "pending");
249
310
  this.queueTime = [
250
311
  0,
251
312
  0
@@ -259,7 +320,9 @@ class WrappedTarget {
259
320
  0
260
321
  ];
261
322
  this.threadId = 0;
262
- this.status = "pending";
263
323
  this.target = options.target;
324
+ if (this.target.id === (0, _targetgraph.getStartTargetId)()) {
325
+ _class_private_field_set(this, _status, "success");
326
+ }
264
327
  }
265
328
  }
@@ -43,6 +43,6 @@ export declare class WorkerRunner implements TargetRunner {
43
43
  static gracefulKillTimeout: number;
44
44
  constructor(options: WorkerRunnerOptions);
45
45
  shouldRun(target: Target): Promise<boolean>;
46
- run(runOptions: TargetRunnerOptions): Promise<void>;
46
+ run(runOptions: TargetRunnerOptions): Promise<any>;
47
47
  getScriptModule(target: Target): Promise<any>;
48
48
  }
@@ -38,7 +38,7 @@ class WorkerRunner {
38
38
  if (typeof runFn !== "function") {
39
39
  throw new Error("WorkerRunner: worker script must export a function; you likely need to use `module.exports = function() {...}`");
40
40
  }
41
- await runFn({
41
+ return await runFn({
42
42
  target,
43
43
  weight,
44
44
  taskArgs,
@@ -82,9 +82,10 @@ async function setup(options) {
82
82
  async function run(data, abortSignal) {
83
83
  const { hash , cacheHit } = await getCache(data.target);
84
84
  const cacheEnabled = data.target.cache && options.shouldCache && hash;
85
+ let value = undefined;
85
86
  if (!cacheHit || !cacheEnabled) {
86
87
  const runner = await runnerPicker.pick(data.target);
87
- await runner.run({
88
+ value = await runner.run({
88
89
  ...data,
89
90
  abortSignal
90
91
  });
@@ -92,7 +93,8 @@ async function setup(options) {
92
93
  }
93
94
  return {
94
95
  skipped: cacheHit,
95
- hash
96
+ hash,
97
+ value
96
98
  };
97
99
  }
98
100
  (0, _workerthreadspool.registerWorker)(run);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/scheduler",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Scheduler for Lage",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,12 +20,12 @@
20
20
  "@lage-run/target-graph": "^0.8.6",
21
21
  "@lage-run/logger": "^1.3.0",
22
22
  "@lage-run/cache": "^1.1.1",
23
- "@lage-run/config": "^0.3.0",
24
- "@lage-run/hasher": "^1.0.1",
23
+ "@lage-run/config": "^0.3.1",
24
+ "@lage-run/hasher": "^1.0.2",
25
25
  "@lage-run/worker-threads-pool": "^0.8.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@lage-run/scheduler-types": "^0.3.9",
28
+ "@lage-run/scheduler-types": "^0.3.10",
29
29
  "monorepo-scripts": "*"
30
30
  },
31
31
  "publishConfig": {