@lage-run/scheduler 1.4.2 → 1.4.3

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,22 @@
2
2
  "name": "@lage-run/scheduler",
3
3
  "entries": [
4
4
  {
5
- "date": "Sun, 08 Dec 2024 00:07:13 GMT",
5
+ "date": "Thu, 19 Dec 2024 15:53:33 GMT",
6
+ "version": "1.4.3",
7
+ "tag": "@lage-run/scheduler_v1.4.3",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "author": "1581488+christiango@users.noreply.github.com",
12
+ "package": "@lage-run/scheduler",
13
+ "commit": "684d1b6f3686b38d198541850345485b14bea318",
14
+ "comment": "Report the correct percentage for progress logger up front instead of only adding tasks after they start running"
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Sun, 08 Dec 2024 00:07:28 GMT",
6
21
  "version": "1.4.2",
7
22
  "tag": "@lage-run/scheduler_v1.4.2",
8
23
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,20 @@
1
1
  # Change Log - @lage-run/scheduler
2
2
 
3
- <!-- This log was last generated on Sun, 08 Dec 2024 00:07:13 GMT and should not be manually modified. -->
3
+ <!-- This log was last generated on Thu, 19 Dec 2024 15:53:33 GMT and should not be manually modified. -->
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.4.3
8
+
9
+ Thu, 19 Dec 2024 15:53:33 GMT
10
+
11
+ ### Patches
12
+
13
+ - Report the correct percentage for progress logger up front instead of only adding tasks after they start running (1581488+christiango@users.noreply.github.com)
14
+
7
15
  ## 1.4.2
8
16
 
9
- Sun, 08 Dec 2024 00:07:13 GMT
17
+ Sun, 08 Dec 2024 00:07:28 GMT
10
18
 
11
19
  ### Patches
12
20
 
@@ -96,6 +96,10 @@ class WrappedTarget {
96
96
  onQueued() {
97
97
  _class_private_field_set(this, _status, "queued");
98
98
  this.queueTime = process.hrtime();
99
+ this.options.logger.info("", {
100
+ target: this.target,
101
+ status: "queued"
102
+ });
99
103
  }
100
104
  onAbort() {
101
105
  _class_private_field_set(this, _status, "aborted");
@@ -328,5 +332,9 @@ class WrappedTarget {
328
332
  if (this.target.id === (0, _targetgraph.getStartTargetId)()) {
329
333
  _class_private_field_set(this, _status, "success");
330
334
  }
335
+ this.options.logger.info("", {
336
+ target: this.target,
337
+ status: this.status
338
+ });
331
339
  }
332
340
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/WrappedTarget.ts"],"sourcesContent":["import { bufferTransform } from \"./bufferTransform.js\";\nimport { getLageOutputCacheLocation } from \"./getLageOutputCacheLocation.js\";\nimport { type LogEntry, LogLevel } from \"@lage-run/logger\";\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport { mkdir, writeFile } from \"fs/promises\";\n\nimport type { Pool } from \"@lage-run/worker-threads-pool\";\nimport type { TargetRun, TargetStatus } from \"@lage-run/scheduler-types\";\nimport { getStartTargetId, type Target } from \"@lage-run/target-graph\";\nimport type { Logger } from \"@lage-run/logger\";\nimport type { TargetHasher } from \"@lage-run/hasher\";\nimport type { MessagePort } from \"worker_threads\";\n\nexport interface WrappedTargetOptions {\n root: string;\n target: Target;\n logger: Logger;\n shouldCache: boolean;\n continueOnError: boolean;\n abortController: AbortController;\n pool: Pool;\n hasher: TargetHasher;\n onMessage?: (message: any, postMessage: MessagePort[\"postMessage\"]) => void;\n}\n\nexport interface WorkerResult {\n stdoutBuffer: string;\n stderrBuffer: string;\n skipped: boolean;\n hash: string;\n value: unknown;\n id: string;\n}\n\n/**\n * Wraps a target with additional functionality:\n * 1. Caching\n * 2. Logging\n * 3. Abort signal\n * 4. Continue on error\n */\nexport class WrappedTarget implements TargetRun<WorkerResult> {\n #status: TargetStatus = \"pending\";\n #result: WorkerResult | undefined;\n queueTime: [number, number] = [0, 0];\n startTime: [number, number] = [0, 0];\n duration: [number, number] = [0, 0];\n target: Target;\n threadId = 0;\n\n get result() {\n return this.#result;\n }\n\n get status() {\n return this.#status;\n }\n\n get abortController() {\n return this.options.abortController;\n }\n\n set abortController(abortController: AbortController) {\n this.options.abortController = abortController;\n }\n\n get successful() {\n return this.#status === \"skipped\" || this.#status === \"success\";\n }\n\n get waiting() {\n return this.#status === \"pending\" || this.#status === \"queued\";\n }\n\n constructor(public options: WrappedTargetOptions) {\n this.target = options.target;\n\n if (this.target.id === getStartTargetId()) {\n this.#status = \"success\";\n }\n }\n\n onQueued() {\n this.#status = \"queued\";\n this.queueTime = process.hrtime();\n }\n\n onAbort() {\n this.#status = \"aborted\";\n this.duration = process.hrtime(this.startTime);\n this.options.logger.info(\"\", { target: this.target, status: \"aborted\", threadId: this.threadId });\n }\n\n onStart(threadId: number) {\n if (this.status !== \"running\") {\n this.threadId = threadId;\n this.#status = \"running\";\n this.startTime = process.hrtime();\n this.options.logger.info(\"\", { target: this.target, status: \"running\", threadId });\n }\n }\n\n onComplete() {\n this.#status = \"success\";\n this.duration = process.hrtime(this.startTime);\n this.options.logger.info(\"\", {\n target: this.target,\n status: \"success\",\n duration: this.duration,\n threadId: this.threadId,\n });\n }\n\n onFail() {\n this.#status = \"failed\";\n this.duration = process.hrtime(this.startTime);\n this.options.logger.info(\"\", {\n target: this.target,\n status: \"failed\",\n duration: this.duration,\n threadId: this.threadId,\n });\n\n if (!this.options.continueOnError && this.options.abortController) {\n this.options.abortController.abort();\n }\n }\n\n onSkipped(hash?: string | undefined) {\n if (this.startTime[0] !== 0 && this.startTime[1] !== 0) {\n this.duration = process.hrtime(this.startTime);\n }\n\n this.#status = \"skipped\";\n\n if (hash) {\n this.options.logger.info(\"\", {\n target: this.target,\n status: \"skipped\",\n duration: this.duration,\n hash,\n threadId: this.threadId,\n });\n }\n }\n\n async run() {\n const { target, logger, shouldCache, abortController, root } = this.options;\n\n const abortSignal = abortController.signal;\n\n if (abortSignal.aborted) {\n this.onStart(0);\n this.onAbort();\n return;\n }\n\n try {\n this.#result = await this.runInPool();\n\n const cacheEnabled = target.cache && shouldCache && this.#result.hash;\n // Save output if cache is enabled & cache is hit\n if (!this.#result.skipped && cacheEnabled) {\n const outputLocation = getLageOutputCacheLocation(root, this.#result.hash);\n const outputPath = path.dirname(outputLocation);\n await mkdir(outputPath, { recursive: true });\n\n const output = `${this.#result.stdoutBuffer}\\n${this.#result.stderrBuffer}`;\n\n await writeFile(outputLocation, output);\n\n logger.verbose(`>> Saved cache - ${this.#result.hash}`, { target });\n }\n\n if (this.#result.skipped) {\n const { hash } = this.#result;\n\n const cachedOutputFile = getLageOutputCacheLocation(root, hash ?? \"\");\n\n const shouldShowCachedOutput = fs.existsSync(cachedOutputFile);\n if (shouldShowCachedOutput) {\n const cachedOutput = fs.readFileSync(cachedOutputFile, \"utf8\");\n logger.verbose(\">> Replaying cached output\", { target });\n logger.verbose(cachedOutput.trim(), { target });\n }\n\n this.onSkipped(hash);\n } else {\n this.onComplete();\n }\n\n return this.#result;\n } catch (e) {\n if (e instanceof Error) {\n logger.error(String(e), { target });\n }\n\n if (abortSignal.aborted) {\n this.onAbort();\n } else {\n this.onFail();\n }\n\n throw e;\n }\n }\n\n private async runInPool(): Promise<WorkerResult> {\n const { target, logger, abortController, pool } = this.options;\n const abortSignal = abortController.signal;\n\n let releaseStdout: any;\n let releaseStderr: any;\n\n const bufferStdout = bufferTransform();\n const bufferStderr = bufferTransform();\n\n let msgHandler: (data: LogEntry<any> & { type: string }) => void;\n\n const result = await (pool.exec(\n { target },\n target.weight ?? 1,\n (worker, stdout, stderr) => {\n const postMessage = worker.postMessage.bind(worker);\n\n msgHandler = (data) => {\n if (data.type === \"log\") {\n logger.log(data.level, data.msg, { target, threadId: worker.threadId });\n } else if (data.type === \"hash\") {\n this.options.hasher.hash(target).then((hash) => {\n worker.postMessage({ type: \"hash\", hash });\n });\n } else if (this.options.onMessage) {\n this.options.onMessage(data, postMessage);\n }\n };\n\n worker.on(\"message\", msgHandler);\n\n const threadId = worker.threadId;\n\n this.onStart(threadId);\n\n stdout.pipe(bufferStdout.transform);\n stderr.pipe(bufferStderr.transform);\n\n const releaseStdoutStream = logger.stream(LogLevel.verbose, stdout, { target, threadId });\n\n releaseStdout = () => {\n releaseStdoutStream();\n stdout.unpipe(bufferStdout.transform);\n };\n\n const releaseStderrStream = logger.stream(LogLevel.verbose, stderr, { target, threadId });\n\n releaseStderr = () => {\n releaseStderrStream();\n stderr.unpipe(bufferStderr.transform);\n };\n },\n (worker) => {\n worker.off(\"message\", msgHandler);\n releaseStdout();\n releaseStderr();\n },\n abortSignal\n ) as Promise<{ value?: unknown; skipped: boolean; hash: string; id: string }>);\n\n return {\n stdoutBuffer: bufferStdout.buffer,\n stderrBuffer: bufferStderr.buffer,\n skipped: result?.skipped,\n hash: result?.hash,\n value: result?.value,\n id: result?.id,\n };\n }\n\n /**\n * A JSON representation of this wrapped target, suitable for serialization in tests.\n *\n * Skips the unpredictable properties of the wrapped target like the startTime and duration.\n *\n * @returns\n */\n toJSON() {\n return {\n target: this.target.id,\n status: this.status,\n };\n }\n\n /**\n * Reset the state of this wrapped target.\n */\n reset() {\n this.#result = undefined;\n this.#status = \"pending\";\n }\n}\n"],"names":["WrappedTarget","result","status","abortController","options","successful","waiting","onQueued","queueTime","process","hrtime","onAbort","duration","startTime","logger","info","target","threadId","onStart","onComplete","onFail","continueOnError","abort","onSkipped","hash","run","shouldCache","root","abortSignal","signal","aborted","runInPool","cacheEnabled","cache","skipped","outputLocation","getLageOutputCacheLocation","outputPath","path","dirname","mkdir","recursive","output","stdoutBuffer","stderrBuffer","writeFile","verbose","cachedOutputFile","shouldShowCachedOutput","fs","existsSync","cachedOutput","readFileSync","trim","e","Error","error","String","pool","releaseStdout","releaseStderr","bufferStdout","bufferTransform","bufferStderr","msgHandler","exec","weight","worker","stdout","stderr","postMessage","bind","data","type","log","level","msg","hasher","then","onMessage","on","pipe","transform","releaseStdoutStream","stream","LogLevel","unpipe","releaseStderrStream","off","buffer","value","id","toJSON","reset","undefined","constructor","getStartTargetId"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/WrappedTarget.ts"],"sourcesContent":["import { bufferTransform } from \"./bufferTransform.js\";\nimport { getLageOutputCacheLocation } from \"./getLageOutputCacheLocation.js\";\nimport { type LogEntry, LogLevel } from \"@lage-run/logger\";\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport { mkdir, writeFile } from \"fs/promises\";\n\nimport type { Pool } from \"@lage-run/worker-threads-pool\";\nimport type { TargetRun, TargetStatus } from \"@lage-run/scheduler-types\";\nimport { getStartTargetId, type Target } from \"@lage-run/target-graph\";\nimport type { Logger } from \"@lage-run/logger\";\nimport type { TargetHasher } from \"@lage-run/hasher\";\nimport type { MessagePort } from \"worker_threads\";\n\nexport interface WrappedTargetOptions {\n root: string;\n target: Target;\n logger: Logger;\n shouldCache: boolean;\n continueOnError: boolean;\n abortController: AbortController;\n pool: Pool;\n hasher: TargetHasher;\n onMessage?: (message: any, postMessage: MessagePort[\"postMessage\"]) => void;\n}\n\nexport interface WorkerResult {\n stdoutBuffer: string;\n stderrBuffer: string;\n skipped: boolean;\n hash: string;\n value: unknown;\n id: string;\n}\n\n/**\n * Wraps a target with additional functionality:\n * 1. Caching\n * 2. Logging\n * 3. Abort signal\n * 4. Continue on error\n */\nexport class WrappedTarget implements TargetRun<WorkerResult> {\n #status: TargetStatus = \"pending\";\n #result: WorkerResult | undefined;\n queueTime: [number, number] = [0, 0];\n startTime: [number, number] = [0, 0];\n duration: [number, number] = [0, 0];\n target: Target;\n threadId = 0;\n\n get result() {\n return this.#result;\n }\n\n get status() {\n return this.#status;\n }\n\n get abortController() {\n return this.options.abortController;\n }\n\n set abortController(abortController: AbortController) {\n this.options.abortController = abortController;\n }\n\n get successful() {\n return this.#status === \"skipped\" || this.#status === \"success\";\n }\n\n get waiting() {\n return this.#status === \"pending\" || this.#status === \"queued\";\n }\n\n constructor(public options: WrappedTargetOptions) {\n this.target = options.target;\n\n if (this.target.id === getStartTargetId()) {\n this.#status = \"success\";\n }\n\n this.options.logger.info(\"\", { target: this.target, status: this.status });\n }\n\n onQueued() {\n this.#status = \"queued\";\n this.queueTime = process.hrtime();\n this.options.logger.info(\"\", { target: this.target, status: \"queued\" });\n }\n\n onAbort() {\n this.#status = \"aborted\";\n this.duration = process.hrtime(this.startTime);\n this.options.logger.info(\"\", { target: this.target, status: \"aborted\", threadId: this.threadId });\n }\n\n onStart(threadId: number) {\n if (this.status !== \"running\") {\n this.threadId = threadId;\n this.#status = \"running\";\n this.startTime = process.hrtime();\n this.options.logger.info(\"\", { target: this.target, status: \"running\", threadId });\n }\n }\n\n onComplete() {\n this.#status = \"success\";\n this.duration = process.hrtime(this.startTime);\n this.options.logger.info(\"\", {\n target: this.target,\n status: \"success\",\n duration: this.duration,\n threadId: this.threadId,\n });\n }\n\n onFail() {\n this.#status = \"failed\";\n this.duration = process.hrtime(this.startTime);\n this.options.logger.info(\"\", {\n target: this.target,\n status: \"failed\",\n duration: this.duration,\n threadId: this.threadId,\n });\n\n if (!this.options.continueOnError && this.options.abortController) {\n this.options.abortController.abort();\n }\n }\n\n onSkipped(hash?: string | undefined) {\n if (this.startTime[0] !== 0 && this.startTime[1] !== 0) {\n this.duration = process.hrtime(this.startTime);\n }\n\n this.#status = \"skipped\";\n\n if (hash) {\n this.options.logger.info(\"\", {\n target: this.target,\n status: \"skipped\",\n duration: this.duration,\n hash,\n threadId: this.threadId,\n });\n }\n }\n\n async run() {\n const { target, logger, shouldCache, abortController, root } = this.options;\n\n const abortSignal = abortController.signal;\n\n if (abortSignal.aborted) {\n this.onStart(0);\n this.onAbort();\n return;\n }\n\n try {\n this.#result = await this.runInPool();\n\n const cacheEnabled = target.cache && shouldCache && this.#result.hash;\n // Save output if cache is enabled & cache is hit\n if (!this.#result.skipped && cacheEnabled) {\n const outputLocation = getLageOutputCacheLocation(root, this.#result.hash);\n const outputPath = path.dirname(outputLocation);\n await mkdir(outputPath, { recursive: true });\n\n const output = `${this.#result.stdoutBuffer}\\n${this.#result.stderrBuffer}`;\n\n await writeFile(outputLocation, output);\n\n logger.verbose(`>> Saved cache - ${this.#result.hash}`, { target });\n }\n\n if (this.#result.skipped) {\n const { hash } = this.#result;\n\n const cachedOutputFile = getLageOutputCacheLocation(root, hash ?? \"\");\n\n const shouldShowCachedOutput = fs.existsSync(cachedOutputFile);\n if (shouldShowCachedOutput) {\n const cachedOutput = fs.readFileSync(cachedOutputFile, \"utf8\");\n logger.verbose(\">> Replaying cached output\", { target });\n logger.verbose(cachedOutput.trim(), { target });\n }\n\n this.onSkipped(hash);\n } else {\n this.onComplete();\n }\n\n return this.#result;\n } catch (e) {\n if (e instanceof Error) {\n logger.error(String(e), { target });\n }\n\n if (abortSignal.aborted) {\n this.onAbort();\n } else {\n this.onFail();\n }\n\n throw e;\n }\n }\n\n private async runInPool(): Promise<WorkerResult> {\n const { target, logger, abortController, pool } = this.options;\n const abortSignal = abortController.signal;\n\n let releaseStdout: any;\n let releaseStderr: any;\n\n const bufferStdout = bufferTransform();\n const bufferStderr = bufferTransform();\n\n let msgHandler: (data: LogEntry<any> & { type: string }) => void;\n\n const result = await (pool.exec(\n { target },\n target.weight ?? 1,\n (worker, stdout, stderr) => {\n const postMessage = worker.postMessage.bind(worker);\n\n msgHandler = (data) => {\n if (data.type === \"log\") {\n logger.log(data.level, data.msg, { target, threadId: worker.threadId });\n } else if (data.type === \"hash\") {\n this.options.hasher.hash(target).then((hash) => {\n worker.postMessage({ type: \"hash\", hash });\n });\n } else if (this.options.onMessage) {\n this.options.onMessage(data, postMessage);\n }\n };\n\n worker.on(\"message\", msgHandler);\n\n const threadId = worker.threadId;\n\n this.onStart(threadId);\n\n stdout.pipe(bufferStdout.transform);\n stderr.pipe(bufferStderr.transform);\n\n const releaseStdoutStream = logger.stream(LogLevel.verbose, stdout, { target, threadId });\n\n releaseStdout = () => {\n releaseStdoutStream();\n stdout.unpipe(bufferStdout.transform);\n };\n\n const releaseStderrStream = logger.stream(LogLevel.verbose, stderr, { target, threadId });\n\n releaseStderr = () => {\n releaseStderrStream();\n stderr.unpipe(bufferStderr.transform);\n };\n },\n (worker) => {\n worker.off(\"message\", msgHandler);\n releaseStdout();\n releaseStderr();\n },\n abortSignal\n ) as Promise<{ value?: unknown; skipped: boolean; hash: string; id: string }>);\n\n return {\n stdoutBuffer: bufferStdout.buffer,\n stderrBuffer: bufferStderr.buffer,\n skipped: result?.skipped,\n hash: result?.hash,\n value: result?.value,\n id: result?.id,\n };\n }\n\n /**\n * A JSON representation of this wrapped target, suitable for serialization in tests.\n *\n * Skips the unpredictable properties of the wrapped target like the startTime and duration.\n *\n * @returns\n */\n toJSON() {\n return {\n target: this.target.id,\n status: this.status,\n };\n }\n\n /**\n * Reset the state of this wrapped target.\n */\n reset() {\n this.#result = undefined;\n this.#status = \"pending\";\n }\n}\n"],"names":["WrappedTarget","result","status","abortController","options","successful","waiting","onQueued","queueTime","process","hrtime","logger","info","target","onAbort","duration","startTime","threadId","onStart","onComplete","onFail","continueOnError","abort","onSkipped","hash","run","shouldCache","root","abortSignal","signal","aborted","runInPool","cacheEnabled","cache","skipped","outputLocation","getLageOutputCacheLocation","outputPath","path","dirname","mkdir","recursive","output","stdoutBuffer","stderrBuffer","writeFile","verbose","cachedOutputFile","shouldShowCachedOutput","fs","existsSync","cachedOutput","readFileSync","trim","e","Error","error","String","pool","releaseStdout","releaseStderr","bufferStdout","bufferTransform","bufferStderr","msgHandler","exec","weight","worker","stdout","stderr","postMessage","bind","data","type","log","level","msg","hasher","then","onMessage","on","pipe","transform","releaseStdoutStream","stream","LogLevel","unpipe","releaseStderrStream","off","buffer","value","id","toJSON","reset","undefined","constructor","getStartTargetId"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/scheduler",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Scheduler for Lage",
5
5
  "repository": {
6
6
  "type": "git",