Skip to content

Support catchAsync for using if/without and await #64

@emizzle

Description

@emizzle

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions