@lage-run/scheduler
Advanced tools
Comparing version 0.7.3 to 0.8.0
@@ -5,3 +5,24 @@ { | ||
{ | ||
"date": "Thu, 05 Jan 2023 00:40:39 GMT", | ||
"date": "Wed, 18 Jan 2023 18:18:13 GMT", | ||
"tag": "@lage-run/scheduler_v0.8.0", | ||
"version": "0.8.0", | ||
"comments": { | ||
"minor": [ | ||
{ | ||
"author": "kchau@microsoft.com", | ||
"package": "@lage-run/scheduler", | ||
"commit": "71b5b1452ee25148a637894d1bf99cf1cc6a80a7", | ||
"comment": "Using lage for prune and clear on cache and get reporter in shape for ADO" | ||
}, | ||
{ | ||
"author": "beachball", | ||
"package": "@lage-run/scheduler", | ||
"comment": "Bump @lage-run/scheduler-types to v0.3.0", | ||
"commit": "71b5b1452ee25148a637894d1bf99cf1cc6a80a7" | ||
} | ||
] | ||
} | ||
}, | ||
{ | ||
"date": "Thu, 05 Jan 2023 00:40:50 GMT", | ||
"tag": "@lage-run/scheduler_v0.7.3", | ||
@@ -8,0 +29,0 @@ "version": "0.7.3", |
# Change Log - @lage-run/scheduler | ||
This log was last generated on Thu, 05 Jan 2023 00:40:39 GMT and should not be manually modified. | ||
This log was last generated on Wed, 18 Jan 2023 18:18:13 GMT and should not be manually modified. | ||
<!-- Start content --> | ||
## 0.8.0 | ||
Wed, 18 Jan 2023 18:18:13 GMT | ||
### Minor changes | ||
- Using lage for prune and clear on cache and get reporter in shape for ADO (kchau@microsoft.com) | ||
- Bump @lage-run/scheduler-types to v0.3.0 | ||
## 0.7.3 | ||
Thu, 05 Jan 2023 00:40:39 GMT | ||
Thu, 05 Jan 2023 00:40:50 GMT | ||
@@ -11,0 +20,0 @@ ### Patches |
@@ -10,2 +10,5 @@ "use strict"; | ||
const NoOpRunner = { | ||
async shouldRun () { | ||
return true; | ||
}, | ||
async run () { | ||
@@ -12,0 +15,0 @@ // pass |
import type { TargetRunner, TargetRunnerOptions } from "@lage-run/scheduler-types"; | ||
import type { Target } from "@lage-run/target-graph"; | ||
export interface NpmScriptRunnerOptions { | ||
@@ -32,3 +33,4 @@ taskArgs: string[]; | ||
private validateOptions; | ||
shouldRun(target: Target): Promise<boolean>; | ||
run(runOptions: TargetRunnerOptions): Promise<void>; | ||
} |
@@ -29,3 +29,3 @@ "use strict"; | ||
const packageJson = JSON.parse(await (0, _promises.readFile)(packageJsonPath, "utf8")); | ||
return packageJson.scripts?.[task]; | ||
return !!packageJson.scripts?.[task]; | ||
} | ||
@@ -37,2 +37,6 @@ validateOptions(options) { | ||
} | ||
async shouldRun(target) { | ||
// By convention, do not run anything if there is no script for this task defined in package.json (counts as "success") | ||
return await this.hasNpmScript(target); | ||
} | ||
async run(runOptions) { | ||
@@ -43,6 +47,2 @@ const { target , weight , abortSignal } = runOptions; | ||
let childProcess; | ||
// By convention, do not run anything if there is no script for this task defined in package.json (counts as "success") | ||
if (!await this.hasNpmScript(target)) { | ||
return; | ||
} | ||
/** | ||
@@ -49,0 +49,0 @@ * Handling abort signal from the abort controller. Gracefully kills the process, |
import type { TargetRunner, TargetRunnerOptions } from "@lage-run/scheduler-types"; | ||
import type { Target } from "@lage-run/target-graph"; | ||
export interface WorkerRunnerOptions { | ||
@@ -44,3 +45,5 @@ taskArgs: string[]; | ||
constructor(options: WorkerRunnerOptions); | ||
shouldRun(target: Target): Promise<boolean>; | ||
run(runOptions: TargetRunnerOptions): Promise<void>; | ||
getScriptModule(target: Target): Promise<any>; | ||
} |
@@ -11,15 +11,14 @@ "use strict"; | ||
class WorkerRunner { | ||
async shouldRun(target) { | ||
const scriptModule = await this.getScriptModule(target); | ||
if (typeof scriptModule.shouldRun === "function") { | ||
return await scriptModule.shouldRun(target); | ||
} | ||
return true; | ||
} | ||
async run(runOptions) { | ||
const { target , weight , abortSignal } = runOptions; | ||
const { taskArgs } = this.options; | ||
const scriptFile = target.options?.worker ?? target.options?.script; | ||
if (!scriptFile) { | ||
throw new Error('WorkerRunner: "script" configuration is required - e.g. { type: "worker", script: "./worker.js" }'); | ||
} | ||
let importScript = scriptFile; | ||
if (!importScript.startsWith("file://")) { | ||
importScript = (0, _url.pathToFileURL)(importScript).toString(); | ||
} | ||
const scriptModule = await import(importScript); | ||
const runFn = typeof scriptModule.default === "function" ? scriptModule.default : scriptModule; | ||
const scriptModule = await this.getScriptModule(target); | ||
const runFn = typeof scriptModule.run === "function" ? scriptModule.run : typeof scriptModule.default === "function" ? scriptModule.default : scriptModule; | ||
if (typeof runFn !== "function") { | ||
@@ -35,2 +34,13 @@ throw new Error("WorkerRunner: worker script must export a function; you likely need to use `module.exports = function() {...}`"); | ||
} | ||
async getScriptModule(target) { | ||
const scriptFile = target.options?.worker ?? target.options?.script; | ||
if (!scriptFile) { | ||
throw new Error('WorkerRunner: "script" configuration is required - e.g. { type: "worker", script: "./worker.js" }'); | ||
} | ||
let importScript = scriptFile; | ||
if (!importScript.startsWith("file://")) { | ||
importScript = (0, _url.pathToFileURL)(importScript).toString(); | ||
} | ||
return await import(importScript); | ||
} | ||
constructor(options){ | ||
@@ -37,0 +47,0 @@ this.options = options; |
/// <reference types="node" /> | ||
/// <reference types="global" /> | ||
import { WrappedTarget } from "./WrappedTarget.js"; | ||
import { TargetRunnerPicker } from "./runners/TargetRunnerPicker.js"; | ||
import type { CacheProvider, TargetHasher } from "@lage-run/cache"; | ||
@@ -43,2 +44,3 @@ import type { Logger } from "@lage-run/logger"; | ||
pool: Pool; | ||
runnerPicker: TargetRunnerPicker; | ||
runPromise: Promise<any>; | ||
@@ -45,0 +47,0 @@ constructor(options: SimpleSchedulerOptions); |
@@ -14,2 +14,3 @@ "use strict"; | ||
const _wrappedTargetJs = require("./WrappedTarget.js"); | ||
const _targetRunnerPickerJs = require("./runners/TargetRunnerPicker.js"); | ||
function _checkPrivateRedeclaration(obj, privateCollection) { | ||
@@ -140,4 +141,5 @@ if (privateCollection.has(obj)) { | ||
getReadyTargets() { | ||
const readyTargets = []; | ||
const readyTargets = new Set(); | ||
for (const target of this.getTargetsByPriority()){ | ||
// Skip the start target | ||
if (target.id === (0, _targetGraph.getStartTargetId)()) { | ||
@@ -147,13 +149,18 @@ continue; | ||
const targetRun = this.targetRuns.get(target.id); | ||
const targetDeps = targetRun.target.dependencies; | ||
// filter all dependencies for those that are "ready" | ||
const ready = targetDeps.every((dep)=>{ | ||
const fromTarget = this.targetRuns.get(dep); | ||
return fromTarget.successful || dep === (0, _targetGraph.getStartTargetId)(); | ||
}); | ||
if (ready && targetRun.status === "pending") { | ||
readyTargets.push(targetRun); | ||
// If the target is already running, then we can't run it again | ||
if (targetRun.status === "pending") { | ||
const targetDeps = targetRun.target.dependencies; | ||
// Target is only ready when all its deps are "successful" or that it is a root target | ||
const ready = targetDeps.every((dep)=>{ | ||
const fromTarget = this.targetRuns.get(dep); | ||
return fromTarget.successful || dep === (0, _targetGraph.getStartTargetId)(); | ||
}); | ||
if (ready) { | ||
readyTargets.add(targetRun); | ||
} | ||
} | ||
} | ||
return readyTargets; | ||
return [ | ||
...readyTargets | ||
]; | ||
} | ||
@@ -226,2 +233,3 @@ isAllDone() { | ||
}); | ||
this.runnerPicker = new _targetRunnerPickerJs.TargetRunnerPicker(options.runners); | ||
} | ||
@@ -237,6 +245,18 @@ } | ||
this.rerunTargets.delete(target.target.id); | ||
target.onQueued(); | ||
try { | ||
await target.run(); | ||
} catch (e) { | ||
runError = e; | ||
let shouldRun = true; | ||
try { | ||
const runner = await this.runnerPicker.pick(target.target); | ||
shouldRun = await runner.shouldRun(target.target); | ||
} catch (e) { | ||
// pass - default to run anyway | ||
} | ||
if (shouldRun) { | ||
await target.run(); | ||
} else { | ||
target.status = "skipped"; | ||
} | ||
} catch (e1) { | ||
runError = e1; | ||
} | ||
@@ -243,0 +263,0 @@ }while (this.rerunTargets.has(target.target.id)) |
@@ -123,3 +123,2 @@ "use strict"; | ||
const { target , logger , shouldCache , abortController } = this.options; | ||
this.onQueued(); | ||
const abortSignal = abortController.signal; | ||
@@ -126,0 +125,0 @@ if (abortSignal.aborted) { |
{ | ||
"name": "@lage-run/scheduler", | ||
"version": "0.7.3", | ||
"version": "0.8.0", | ||
"description": "Scheduler for Lage", | ||
@@ -24,3 +24,3 @@ "repository": { | ||
"devDependencies": { | ||
"@lage-run/scheduler-types": "^0.2.10", | ||
"@lage-run/scheduler-types": "^0.3.0", | ||
"monorepo-scripts": "*" | ||
@@ -27,0 +27,0 @@ }, |
101984
2659