Skip to content

Instantly share code, notes, and snippets.

@tswaters
Last active May 19, 2020 02:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tswaters/74483b1b87a6bf6ba06b42fb31d85be3 to your computer and use it in GitHub Desktop.
Save tswaters/74483b1b87a6bf6ba06b42fb31d85be3 to your computer and use it in GitHub Desktop.
'use strict'
// error-prone work function
const _work = (name, failure_rate) => (thing) =>
new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < failure_rate) {
console.log(`${name} failed - ${JSON.stringify(thing)}`)
reject(new Error(`${name} hit above ${failure_rate}`))
} else {
console.log(`${name} succeeded - ${JSON.stringify(thing)}`)
resolve(`${name} succeeded`)
}
}, Math.random() * 1000)
})
// credit cart example,
// charge a series of preuaths, and roll them all back if one failed.
const complete = _work('charge', 0.25)
const refund = _work('refund', 0.25)
const settle = async (charges) => {
const chargeResults = await Promise.allSettled(
charges.map((charge) =>
complete(charge)
.then((res) => ({ res, charge }))
.catch((err) => {
throw { err, charge }
})
)
)
const successes = chargeResults
.filter(({ status }) => status === 'fulfilled')
.map(({ value: { charge } }) => charge)
const failed = chargeResults
.filter(({ status }) => status === 'rejected')
.map(({ reason: { charge } }) => charge)
const charged = new Set(successes)
const refunded = new Set()
while (
successes.length !== chargeResults.length &&
refunded.size !== successes.length
)
(
await Promise.allSettled(
[...charged].map((charge) =>
refund(charge).then((res) => ({ res, charge }))
)
)
)
.filter(({ status }) => status === 'fulfilled')
.forEach(({ value: { charge } }) => {
charged.delete(charge)
refunded.add(charge)
})
return { failed, charged, refunded }
}
;(async () => {
const { failed, charged, refunded } = await settle(
['Alice', 'Bob', 'Claire', 'Doug'].map((name) => ({
name,
charge: (Math.random() * 1000).toFixed(2),
}))
)
console.log('failed: ', failed)
console.log('charged: ', charged)
console.log('refunded: ', refunded)
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment