Last active
May 19, 2020 02:09
-
-
Save tswaters/74483b1b87a6bf6ba06b42fb31d85be3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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