%%%------------------------------------------------------------------- %%% @doc Small shared helpers for wrapping `try ... catch ... end' idioms %%% that recur across barrel_docdb, so the pattern lives in one place. %%% @end %%%------------------------------------------------------------------- -module(barrel_lib). -export([safe_fold/1, safe/2, safe_apply/1]). %% @doc Run a fold that early-terminates by throwing `{stop, Result}'. %% The fold's callback throws `{stop, Acc}' to stop iteration; this returns %% either the fold's normal result or the thrown accumulator. -spec safe_fold(fun(() -> Result)) -> Result. safe_fold(Fun) -> try Fun() catch throw:{stop, Result} -> Result end. %% @doc Run `Fun', returning `Default' on any exception. Best-effort calls %% where a failure should fall back to a fixed value. -spec safe(fun(() -> Result), Default) -> Result | Default. safe(Fun, Default) -> try Fun() catch _:_ -> Default end. %% @doc Run `Fun', capturing any failure as `{error, {Class, Reason, Stack}}'. %% Used to ship worker results back without crashing the caller. -spec safe_apply(fun(() -> Result)) -> {ok, Result} | {error, {atom(), term(), list()}}. safe_apply(Fun) -> try {ok, Fun()} catch Class:Reason:Stack -> {error, {Class, Reason, Stack}} end.