-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Perhaps the best place to put catchAsync would be in questionable, since it seems to be the most useful when combining without/if and await. Normally, using catch with await will catch all CatchableErrors, including CancelledError, which would prevent cancellation propagation, for example:
without collateral =?
await sales.context.market.slotCollateral(data.requestId, data.slotIndex).catch:In this example, slotCollateral return ?UInt256, so we use the binding features of questionable, here, and want to also catch any errors in the process.
This is where something like catchAsync could come into play, which could be used without fear of swallowing CancelledError, for example:
without collateral =?
await sales.context.market.slotCollateral(data.requestId, data.slotIndex).catchAsync:catchAsync could be implemented like this (tested inside of nim-codex):
template catchAsync*(body: typed): Result[type(body), ref CatchableError] =
## Catch exceptions for `body` containing `await` and store them in the
## Result, propagating cancellations.
##
## ```
## let r = catchAsync: await someAsyncFuncThatMayRaise()
## ```
type R = Result[type(body), ref CatchableError]
try:
when type(body) is void:
body
R.ok()
else:
R.ok(body)
except CancelledError as eCancelled:
raise eCancelled
except CatchableError as eResultPrivate:
R.err(eResultPrivate)It was determined not to be suited for nim-results (arnetheduck/nim-results#54), and as a possibility might eventually be included as a feature set to using Result with nim-chronos.