gpt4 book ai didi

Erlang:成功案例和错误处理作为事务

转载 作者:行者123 更新时间:2023-12-01 01:55:57 24 4
gpt4 key购买 nike

(我想引用另一个问题作为引用:How do I elegantly check many conditions in Erlang?)

“与错误处理分离的成功案例代码”的通用形式似乎是:

try
ok = do_x(),
...
ok = do_y()
catch
error:{badmatch, x_failure} -> do_something1();
...
error:{badmatch, y_failure} -> do_something2();

当 try 子句中的函数执行具有副作用的操作(例如写入文件、发送网络数据包、将一行写入数据库等)时,如何使用此模式? catch 子句中是否有“回滚”的通用模式?例子:
try
%How to make this whole block a transaction?
ok = step_1_write_file(),
ok = step_2_write_database(),
ok = step_3_send_packet(),
...
catch
error:{badmatch, database_failure} -> clean_up_step_1() %delete file?
error:{badmatch, sendpacket_failure} -> clean_up_step_1_and_2() %??

似乎错误处理变得繁重,需要执行的清理取决于 try 中的步骤。失败的块。

是否有一种通用的编程模式将其视为事务,而在 failed 子句之前的 try 块中的成功步骤是“unwound”?

最佳答案

我个人通过将“验证器”列表和可选的“终结器”列表传递给某个通用迭代函数来学习对此类算法进行编程。

所以,你的案例可能是这样编程的:

noop() -> ok.

transaction([{Fun, Rollback} | Rest]) ->
try
{ok, Result} = Fun(),
[Result | transaction(Rest)]
catch Type:Reason ->
Rollback(),
erlang:raise(Type, Reason, erlang:get_stacktrace())
end;
transaction([Fun | Rest]) ->
% not every action require cleanup on error
transaction([{Fun, fun noop/0} | Rest]);
transaction([]) -> [].


main() ->
Actions = [
{fun write_file/0, fun cleanup_file/0},
{fun write_database/0, fun cleanup_database/0},
fun do_safe_thing/0,
{fun send_packet/0, fun cancel_send_packet/0},
],
transaction(Actions).

如您所见,由于此列表使用主体递归进行评估,因此通过此列表进行迭代将形成调用堆栈,如果在某些步骤中这些函数中的一个失败,堆栈将展开,每个清理函数将按相反顺序调用.

例如,如果 do_safe_ting/0会掉,清理功能 noop/0 , cleanup_database/0cleanup_file/0将按此顺序调用。

当然,这可以用不同的方式编程,不是通过重新抛出异常,而是通过例如返回 {ok, Result}{error, Reason} .这只是实现细节。

关于Erlang:成功案例和错误处理作为事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40664069/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com