Created
September 17, 2019 21:24
-
-
Save hugosenari/ee18f739bce8f96c41b5904d731184fb to your computer and use it in GitHub Desktop.
Laconia High Order Function Adapter
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
const identity = value => value; | |
const mappingAdapter = (mappings = []) => fn => (event, laconiaContext) => { | |
const args = [ | |
...mappings.reduce( | |
(actual, mapping) => mapping( | |
actual, event, laconiaContext | |
), | |
[] | |
), | |
event, | |
laconiaContext | |
]; | |
return fn(...args); | |
}; | |
class PreTimeoutError extends Error { | |
constructor(message, millisBeforeTimeout) { | |
super(message); | |
this.millisBeforeTimeout = millisBeforeTimeout; | |
} | |
} | |
const timeoutAdapter = (throwMillisBeforeTimeout = 500) => fn => (event, laconiaContext) => { | |
const timeout = new Promise((resolve, reject) => setTimeout( | |
() => reject(new PreTimeoutError('PreTimeoutError', throwMillisBeforeTimeout)), | |
laconiaContext.context.getRemainingTimeInMillis() - throwMillisBeforeTimeout) | |
); | |
return Promise.race([fn(event, laconiaContext), timeout]); | |
}; | |
const successAdapter = (onSuccess = identity) => fn => (event, laconiaContext) => onSuccess( | |
fn(event, laconiaContext) | |
); | |
const errorAdapter = (onError = error => { throw error; }) => fn => (event, laconiaContext) => { | |
try { | |
return Promise.resolve(fn(event, laconiaContext)) | |
.catch(error => onError(error, event, laconiaContext)); | |
} catch (error) { | |
return onError(error, event, laconiaContext); | |
} | |
}; | |
const finallyAddapter = (onEnd = identity) => fn => (event, laconiaContext) => { | |
try { | |
return fn(event, laconiaContext); | |
} finally { | |
onEnd(event, laconiaContext); | |
} | |
}; | |
const hofAdapter = ({ | |
mappings = [], | |
onEnd = identity, | |
onSuccess = identity, | |
throwMillisBeforeTimeout = 500, | |
onError = error => { throw error; } | |
}) => fn => [ | |
mappingAdapter(mappings || []), | |
timeoutAdapter(throwMillisBeforeTimeout || 500), | |
successAdapter(onSuccess || identity), | |
errorAdapter(onError || (error => { throw error; })), | |
finallyAddapter(onEnd || identity) | |
].reduce((handler, adapter) => handler(adapter), fn); |
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
const hofAdapter = ({ | |
onEnd = () => {}, | |
onMapping = (actual, event, laconiaContext) => [...actual, event, laconiaContext], | |
onSuccess = result => result, | |
onError = error => { throw error; }, | |
throwMillisBeforeTimeout = 500 | |
}) => fn => (event, laconiaContext) => { | |
try { | |
return Promise.race([ | |
onSuccess(fn(...onMapping(event, laconiaContext))), | |
new Promise((resolve, reject) => setTimeout( | |
() => reject(new Error('TimeoutError')), | |
laconiaContext.context.getRemainingTimeInMillis() - throwMillisBeforeTimeout) | |
) | |
]).catch(error => onError(error, event, laconiaContext)); | |
} catch (error) { | |
return onError(error, event, laconiaContext); | |
} finally { | |
onEnd(event, laconiaContext); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment