Skip to content

Commit

Permalink
Catch errors in operation handlers
Browse files Browse the repository at this point in the history
This means we don't lose the results of the repositories that succeeded
and can continue to work on them if we like.

Closes #148
  • Loading branch information
ivomurrell committed Aug 20, 2021
1 parent 52f453e commit 4fe3521
Showing 1 changed file with 33 additions and 33 deletions.
66 changes: 33 additions & 33 deletions src/lib/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ module.exports = class State {
const message = `state file '${stateContainer.fileName}' doesn't exist`

const create = process.stdin.isTTY
? (await prompt({
name: 'create',
message: `${message}. create it?`,
type: 'confirm',
})).create
? (
await prompt({
name: 'create',
message: `${message}. create it?`,
type: 'confirm',
})
).create
: false

if (create) {
Expand All @@ -103,16 +105,18 @@ module.exports = class State {
file.endsWith(noriExtension),
)

return (await Promise.all(
stateFiles.map(async stateFile => {
const { mtime } = await fs.stat(path.join(workspacePath, stateFile))

return {
stateFile,
mtime, // time the file was last modified as a javascript Date
}
}),
)).sort(({ mtime: a }, { mtime: b }) => b - a)
return (
await Promise.all(
stateFiles.map(async stateFile => {
const { mtime } = await fs.stat(path.join(workspacePath, stateFile))

return {
stateFile,
mtime, // time the file was last modified as a javascript Date
}
}),
)
).sort(({ mtime: a }, { mtime: b }) => b - a)
}

constructor({ fileName, state = { data: {}, steps: [] } }) {
Expand Down Expand Up @@ -166,17 +170,14 @@ module.exports = class State {
async runStep(operation, args) {
// produce, from immer, lets handlers modify the state as a mutable
// object safely. the updated copy is then stored as the new state
try {
this.state.data = await produce(this.state.data, async draft => {
await operation.handler(args, draft)
})
this.state.steps.push({ name: operation.command, args })
return this.save()
} catch (error) {
// save on error so the state file is definitely up to date
await this.save()
throw error
}
this.state = await produce(this.state, async draft => {
try {
await operation.handler(args, draft.data)
} catch {}

draft.steps.push({ name: operation.command, args })
})
return await this.save()
}

async undo(args) {
Expand All @@ -187,20 +188,19 @@ module.exports = class State {
operations[step.name].output === operations[undoneStep.name].output,
)

this.state.data = await produce(this.state.data, async draft => {
this.state = await produce(this.state, async draft => {
for (const step of stepsToUndo.slice().reverse()) {
const operation = operations[step.name]
if (operation.undo) {
await operation.undo(Object.assign({}, step.args, args), draft)
await operation.undo(Object.assign({}, step.args, args), draft.data)
}
}
draft.steps.splice(
this.state.steps.length - stepsToUndo.length,
stepsToUndo.length,
)
})

this.state.steps.splice(
this.state.steps.length - stepsToUndo.length,
stepsToUndo.length,
)

await this.save()

// replay all but the last undone step
Expand Down

0 comments on commit 4fe3521

Please sign in to comment.