我正在将记录写入mnesia,该记录应该保存在那里
仅在允许的时间(24 小时)内。 24小时后,在用户修改其中的一部分之前,
系统应该自动删除它们。例如,用户获得免费通话时间(用于语音通话)
他们应该在给定时间内使用它们。如果他们不使用它,24小时后,系统应该
从用户记录中删除这些资源预留。
现在,这引入了计时器。记录结构的一个示例是:
-record(free_airtime,
{
reference_no,
timer_object, %% value returned by timer:apply_after/4
amount
}).
记录中的计时器对象很重要,因为万一用户
最终在超时之前使用保留的资源
(或者如果超时),系统可以调用timer:cancel/1
从而缓解
来自该对象的计时器服务器。
现在的问题是,我有两种方法来处理这些记录上的计时器:
选项 1:在事务内处理计时器
reserve_resources(Reference_no,Amnt)->
F = fun(Ref_no,Amount) ->
case mnesia:read({free_airtime,Ref_no}) of
[] ->
case mnesia:write(#free_airtime{reference_no = Ref_no,amount = Amount}) == ok of
true ->
case timer:apply_after(timer:hours(24),?MODULE,reference_no_timed_out,[Ref_no]) of
{ok,Timer_obj} ->
[Obj] = mnesia:read({free_airtime,Ref_no}),
mnesia:write(Obj#free_airtime{timer_object = Timer_obj});
_ -> mnesia:abort({error,failed_to_time_object})
end;
false -> mnesia:abort({error,write_failed})
end;
[_] -> mnesia:abort({error,exists,Ref_no})
end
end,
mnesia:activity(transaction,F,[Reference_no,Amnt],mnesia_frag).
关于上面的选项。
Mnesia 文档说 tm 经理可能会重复交易(由于某种原因)
直到他们成功,所以当你输入代码时io:format/2
或任何其他与此无关的
写入或读取,它可能会被执行多次。这句话让我此时停了下来
并想出一种从事务本身处理计时器的方法,所以我将代码修改为
如下:
选项 2:在事务外处理计时器
reserve_resources(Reference_no,Amnt)->
F = fun(Ref_no,Amount) ->
case mnesia:read({free_airtime,Ref_no}) of
[] ->
P = #free_airtime{reference_no = Ref_no,amount = Amount},
ok = mnesia:write(P),
P;
[_] -> mnesia:abort({error,exists,Ref_no})
end
end,
Result = try mnesia:activity(transaction,F,[Reference_no,Amnt],mnesia_frag) of
Any -> Any
catch
exit:{aborted,{error,exists,XX}} -> {exists,XX}
E1:E2 -> {error,{E1,E2}}
end,
on_reservation(Result).
on_reservation(#free_airtime{reference_no = Some_Ref})->
case timer:apply_after(timer:hours(24),?MODULE,reference_no_timed_out,[Some_Ref]) of
{ok,Timer_obj} ->
[Obj] = mnesia:activity(transaction,fun(XX) -> mnesia:read({free_airtime,XX}) end,[Some_Ref],mnesia_frag),
ok = mnesia:activity(transaction,fun(XX) -> mnesia:write(XX) end,[Obj#free_airtime{timer_object = Timer_obj}],mnesia_frag);
_ ->
ok = mnesia:activity(transaction,fun(XX) -> mnesia:delete({free_airtime,XX}) end,[Some_Ref],mnesia_frag),
{error,failed_to_time_object}
end;
on_reservation(Any)-> Any.
处理预订超时的代码:
reference_no_timed_out(Ref_no)->
do_somethings_here.....
then later remove this reservation from the database....below..
ok = mnesia:activity(transaction,fun(XX) -> mnesia:delete({free_airtime,XX}) end,[Ref_no],mnesia_frag).
现在我认为在选项 2 中,保持计时器处理会更安全
代码输出,即使 mnesia_tm 由于其原因重新执行交易
,这段代码不会运行两次(我避免有几个计时器对象
反对相同的记录)。
问题一:这两种实现哪个是正确的?和/或错误?告诉我(也)
他们是否都错了
问题2:定时器模块,是否非常适合处理大量定时器
生产中的工作岗位?
问题3:与肖恩·辛德相比,
运行在 mnesia 之上,计时器模块(可能运行在 Ets 表之上)少
有能力(真正)生产吗?
(我问这个是因为在本身使用 mnesia 的系统上使用 Sean Hinde 的 time_mn 会出现
在模式更改、节点问题等方面成为问题)
如果有人有另一种方法来处理与 mnesia 计时器相关的问题,请更新我
谢谢大家...