Skip to content

Commit

Permalink
chore: Make code for error monitoring more flexible with functional p…
Browse files Browse the repository at this point in the history
…atterns
  • Loading branch information
Iku-turso committed Feb 10, 2022
1 parent d0fd4ef commit e4b6f18
Showing 1 changed file with 62 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { isEmpty } from 'lodash/fp';
import get from 'lodash/fp/get';
import conforms from 'lodash/fp/conforms';
import filter from 'lodash/fp/filter';
Expand Down Expand Up @@ -36,7 +35,7 @@ export default (...listOfGetRequireContexts) => {
alias,
instantiationParameter,
context = [],
reportError = reportErrorFor(privateDi),
withErrorMonitoringFor = withErrorMonitoringForFor(privateDi),
) => {
const originalInjectable = getRelatedInjectable({
injectables,
Expand All @@ -62,22 +61,21 @@ export default (...listOfGetRequireContexts) => {
`Tried to inject "${injectable.id}" when side-effects are prevented.`,
);
}

return getInstance({
injectable,
instantiationParameter,
di: privateDi,
injectableMap,
context,
reportError,
withErrorMonitoringFor,
});
},

injectMany: (
alias,
instantiationParameter,
context = [],
reportError = reportErrorFor(privateDi),
withErrorMonitoringFor = withErrorMonitoringForFor(privateDi),
) =>
pipeline(
getRelatedInjectables({ injectables, alias }),
Expand All @@ -87,7 +85,7 @@ export default (...listOfGetRequireContexts) => {
injectable,
instantiationParameter,
context,
reportError,
withErrorMonitoringFor,
),
),
),
Expand Down Expand Up @@ -294,30 +292,13 @@ const getRelatedInjectables = ({ injectables, alias }) =>
const getOverridingInjectable = ({ overridingInjectables, alias }) =>
pipeline(overridingInjectables, findLast(isRelatedTo(alias)));

const reportErrorFor = di => {
const reportedErrorSet = new Set();

return (error, newContext) => {
if (!reportedErrorSet.has(error)) {
di.injectMany(errorMonitorToken).forEach(errorMonitor =>
errorMonitor({
error,
context: newContext,
}),
);

reportedErrorSet.add(error);
}
};
};

const getInstance = ({
di,
injectable,
instantiationParameter,
context: oldContext,
injectableMap,
reportError,
withErrorMonitoringFor,
}) => {
if (!injectable.instantiate) {
throw new Error(
Expand All @@ -344,10 +325,10 @@ const getInstance = ({

const minimalDi = {
inject: (alias, parameter) =>
di.inject(alias, parameter, newContext, reportError),
di.inject(alias, parameter, newContext, withErrorMonitoringFor),

injectMany: (alias, parameter) =>
di.injectMany(alias, parameter, newContext, reportError),
di.injectMany(alias, parameter, newContext, withErrorMonitoringFor),
};

const instanceKey = injectable.lifecycle.getInstanceKey(
Expand All @@ -361,34 +342,71 @@ const getInstance = ({
return existingInstance;
}

let newInstance;
const withErrorMonitoring = withErrorMonitoringFor(newContext);

try {
newInstance = injectable.instantiate(
minimalDi,
...(isUndefined(instantiationParameter) ? [] : [instantiationParameter]),
);
} catch (error) {
reportError(error, newContext);
const instantiateWithErrorMonitoring = pipeline(
injectable.instantiate,
withErrorMonitoring,
);

throw error;
}
const newInstance = instantiateWithErrorMonitoring(
minimalDi,
...(isUndefined(instantiationParameter) ? [] : [instantiationParameter]),
);

if (instanceKey !== nonStoredInstanceKey) {
instanceMap.set(instanceKey, newInstance);
}

if (isPromise(newInstance)) {
newInstance = newInstance.catch(error => {
reportError(error, newContext);

throw error;
});
}

return newInstance;
};

export const errorMonitorToken = getInjectionToken({
id: 'error-monitor-token',
});

const withErrorMonitoringForFor = di => {
const reportErrorFor = reportErrorForFor(di);

return context => {
const reportError = reportErrorFor(context);

return toBeDecorated =>
(...args) => {
let result;

try {
result = toBeDecorated(...args);
} catch (error) {
reportError(error);

throw error;
}

if (isPromise(result)) {
result.catch(error => {
reportError(error);
});
}

return result;
};
};
};

const reportErrorForFor = di => {
const reportedErrorSet = new Set();

return context => error => {
if (!reportedErrorSet.has(error)) {
di.injectMany(errorMonitorToken).forEach(errorMonitor =>
errorMonitor({
error,
context,
}),
);

reportedErrorSet.add(error);
}
};
};

0 comments on commit e4b6f18

Please sign in to comment.