mirror of
https://github.com/thumbsup/thumbsup
synced 2024-11-15 18:12:46 +00:00
refactor(components): bring ListrWorkQueue into this repo to simplify the build process
- This component was not published to the rpm registry anyway - We depended on the repo’s master branch which can break things for everyone - Its repo was not getting much attention which meant * no tests, no coverage report * no linting * no package linting (e.g. had 2 dependencies that weren’t actually used) It will be simpler to manage this way
This commit is contained in:
parent
90cb3994eb
commit
bf60ae4677
14
package-lock.json
generated
14
package-lock.json
generated
@ -2886,20 +2886,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"listr-work-queue": {
|
|
||||||
"version": "git+https://github.com/thumbsup/listr-work-queue.git#867d499747af33a36b2c7c722239e1cbbee21986",
|
|
||||||
"requires": {
|
|
||||||
"async": "2.6.1",
|
|
||||||
"zen-observable": "0.6.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"zen-observable": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.6.1.tgz",
|
|
||||||
"integrity": "sha512-DKjFTL7siVLIUMZOFZ0alqMEdTsXPUxoCZzrvB2tdWEVN/6606Qh1nCfSTCAOZMrtcPzzFI3BXmwBKLAew52NA=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
"insight": "^0.10.1",
|
"insight": "^0.10.1",
|
||||||
"less": "^3.0.4",
|
"less": "^3.0.4",
|
||||||
"listr": "^0.14.1",
|
"listr": "^0.14.1",
|
||||||
"listr-work-queue": "https://github.com/thumbsup/listr-work-queue.git",
|
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"micromatch": "^3.1.10",
|
"micromatch": "^3.1.10",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
|
56
src/components/listr-work-queue/index.js
Normal file
56
src/components/listr-work-queue/index.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
const _ = require('lodash')
|
||||||
|
const Listr = require('listr')
|
||||||
|
|
||||||
|
class ListrWorkQueue extends Listr {
|
||||||
|
constructor (jobs, options) {
|
||||||
|
options = _.defaults(options, {
|
||||||
|
concurrent: 1,
|
||||||
|
exitOnError: true
|
||||||
|
})
|
||||||
|
const threads = _.times(options.concurrent, i => {
|
||||||
|
return {
|
||||||
|
title: 'Waiting',
|
||||||
|
task: (ctx, task) => {
|
||||||
|
task.id = i
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.createWorker(task, jobs, err => {
|
||||||
|
err ? reject(err) : resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
super(threads, options)
|
||||||
|
this.options = options
|
||||||
|
this.jobsTotal = jobs.length
|
||||||
|
this.jobsDone = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
createWorker (task, jobs, done) {
|
||||||
|
task.title = 'Finished'
|
||||||
|
const job = jobs.shift()
|
||||||
|
if (!job) {
|
||||||
|
return done()
|
||||||
|
} else {
|
||||||
|
task.title = job.title
|
||||||
|
}
|
||||||
|
const nextJob = () => {
|
||||||
|
setImmediate(() => this.createWorker(task, jobs, done))
|
||||||
|
}
|
||||||
|
job.task(null, task).then(() => {
|
||||||
|
++this.jobsDone
|
||||||
|
if (this.options.update) {
|
||||||
|
this.options.update(this.jobsDone, this.jobsTotal)
|
||||||
|
}
|
||||||
|
nextJob()
|
||||||
|
}).catch(err => {
|
||||||
|
if (this.exitOnError) {
|
||||||
|
done(new Error(`Error: ${err}`))
|
||||||
|
} else {
|
||||||
|
nextJob()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ListrWorkQueue
|
@ -2,7 +2,7 @@ const debug = require('debug')('thumbsup:debug')
|
|||||||
const error = require('debug')('thumbsup:error')
|
const error = require('debug')('thumbsup:error')
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const info = require('debug')('thumbsup:info')
|
const info = require('debug')('thumbsup:info')
|
||||||
const ListrWorkQueue = require('listr-work-queue')
|
const ListrWorkQueue = require('../components/listr-work-queue/index')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const actions = require('./actions')
|
const actions = require('./actions')
|
||||||
|
|
||||||
|
43
test/components/listr-work-queue/listr-test-renderer.js
Normal file
43
test/components/listr-work-queue/listr-test-renderer.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
Special Listr renderer that
|
||||||
|
- on every change, renders the whole task list in memory
|
||||||
|
- accumulates all rendered data into an array
|
||||||
|
- has this array available as `listr._renderer.output`
|
||||||
|
*/
|
||||||
|
module.exports = class ListrTestRenderer {
|
||||||
|
static get nonTTY () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
constructor (tasks) {
|
||||||
|
this._tasks = tasks
|
||||||
|
this.output = []
|
||||||
|
}
|
||||||
|
render () {
|
||||||
|
for (let task of this._tasks) {
|
||||||
|
this.subscribe(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subscribe (task) {
|
||||||
|
task.subscribe(
|
||||||
|
event => {
|
||||||
|
if (event.type === 'SUBTASKS') {
|
||||||
|
// new subtasks: subscribe to them too
|
||||||
|
task.subtasks.forEach(sub => this.subscribe(sub))
|
||||||
|
} else {
|
||||||
|
// something else happened, capture all titles
|
||||||
|
const titles = this.allTitles(this._tasks, 0)
|
||||||
|
this.output.push(titles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
allTitles (tasks, indent) {
|
||||||
|
return tasks.map(task => {
|
||||||
|
const subTitles = this.allTitles(task.subtasks, indent + 1)
|
||||||
|
return ' '.repeat(indent) + task.title + '\n' + subTitles
|
||||||
|
}).join('')
|
||||||
|
}
|
||||||
|
end () {
|
||||||
|
}
|
||||||
|
}
|
90
test/components/listr-work-queue/listr-work-queue.spec.js
Normal file
90
test/components/listr-work-queue/listr-work-queue.spec.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
const _ = require('lodash')
|
||||||
|
const Listr = require('listr')
|
||||||
|
const should = require('should/as-function')
|
||||||
|
const ListrWorkQueue = require('../../../src/components/listr-work-queue/index')
|
||||||
|
const ListrTestRenderer = require('./listr-test-renderer.js')
|
||||||
|
|
||||||
|
describe('Listr work queue', function () {
|
||||||
|
this.slow(2000)
|
||||||
|
this.timeout(2000)
|
||||||
|
|
||||||
|
it('processes all jobs in parallel', done => {
|
||||||
|
const jobs = makeJobs(10)
|
||||||
|
const listr = createWorkQueue(jobs, 3, null)
|
||||||
|
listr.run().then(() => {
|
||||||
|
const output = listr._renderer.output
|
||||||
|
for (let i = 1; i <= 10; ++i) {
|
||||||
|
hasItemMatching(output, `Job ${i}`)
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders thread-like entries which keep changing title', done => {
|
||||||
|
const jobs = makeJobs(10)
|
||||||
|
const listr = createWorkQueue(jobs, 3, null)
|
||||||
|
listr.run().then(() => {
|
||||||
|
const output = listr._renderer.output
|
||||||
|
// At some point a thread should have been waiting
|
||||||
|
hasItemMatching(output, `Waiting`)
|
||||||
|
// And a thread should have finished
|
||||||
|
hasItemMatching(output, `Finished`)
|
||||||
|
// And every single render should conform to a particular format
|
||||||
|
const regex = /^Running jobs\n((\s\s(Waiting|Finished|Job \d+)\n){3})?$/
|
||||||
|
for (let line of output) {
|
||||||
|
if (!regex.test(line)) {
|
||||||
|
should.fail(`Listr output does not match expected format: ${line}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reports progress', done => {
|
||||||
|
const jobs = makeJobs(10)
|
||||||
|
const listr = createWorkQueue(jobs, 3, (done, total) => {
|
||||||
|
const progress = done === total ? '' : ` (${done}/${total})`
|
||||||
|
return `Running jobs${progress}`
|
||||||
|
})
|
||||||
|
listr.run().then(() => {
|
||||||
|
const output = listr._renderer.output
|
||||||
|
for (let i = 1; i < 10; ++i) {
|
||||||
|
hasItemMatching(output, `Running jobs (${i}/10)`)
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function createWorkQueue (jobs, concurrency, updater) {
|
||||||
|
const task = {
|
||||||
|
title: 'Running jobs',
|
||||||
|
task: (ctx, task) => new ListrWorkQueue(jobs, {
|
||||||
|
concurrent: concurrency,
|
||||||
|
update: (done, total) => {
|
||||||
|
if (updater) {
|
||||||
|
task.title = updater(done, total)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return new Listr([task], {
|
||||||
|
renderer: ListrTestRenderer
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeJobs (count) {
|
||||||
|
return _.times(count, i => {
|
||||||
|
return {
|
||||||
|
title: `Job ${i + 1}`,
|
||||||
|
task: () => new Promise(resolve => setTimeout(resolve, 100))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasItemMatching (list, substring) {
|
||||||
|
const match = _.some(list, item => item.includes(substring))
|
||||||
|
if (!match) {
|
||||||
|
should.fail(`Excepted ${substring} to be present in ${list}`)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user