Skip to content

Instantly share code, notes, and snippets.

@hugosenari
Created September 17, 2019 21:24
Show Gist options
  • Save hugosenari/ee18f739bce8f96c41b5904d731184fb to your computer and use it in GitHub Desktop.
Save hugosenari/ee18f739bce8f96c41b5904d731184fb to your computer and use it in GitHub Desktop.
Laconia High Order Function Adapter
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);
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