我正在将记录写入 mnesia,这些记录应仅在允许的时间(24 小时)内保存。24 小时后,在用户修改其中的一部分之前,系统应自动删除它们。例如,为用户提供免费通话时间(用于语音通话),他们应该在给定时间内使用这些通话时间。如果他们不使用它,24 小时后,系统应该从用户记录中删除这些资源预留。
现在,这引入了计时器。记录结构的一个示例是:
-记录(免费通话时间, { 参考编号, timer_object,定时器返回的%%值:apply_after/4 数量 })。
记录中的计时器对象很重要,因为万一用户在超时(或超时)之前最终使用了保留的资源,系统可以调用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 真-> case timer:apply_after(timer:hours(24),?MODULE,reference_no_timed_out,[Ref_no]) 的 {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}) 结尾; false -> mnesia:abort({error,write_failed}) 结尾; [_] -> mnesia:abort({error,exists,Ref_no}) 结尾 结尾, 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), 磷; [_] -> mnesia:abort({error,exists,Ref_no}) 结尾 结尾, 结果 = 尝试 mnesia:activity(transaction,F,[Reference_no,Amnt],mnesia_frag) 的 任何 -> 任何 抓住 退出:{中止,{错误,存在,XX}} - > {存在,XX} E1:E2 -> {错误,{E1,E2}} 结尾, on_reservation(结果)。 on_reservation(#free_airtime{reference_no = Some_Ref})-> case timer:apply_after(timer:hours(24),?MODULE,reference_no_timed_out,[Some_Ref]) {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), {错误,failed_to_time_object} 结尾; on_reservation(任何)-> 任何。
处理预订超时的代码:
reference_no_timed_out(Ref_no)-> do_somethings_here..... 然后稍后从数据库中删除此保留..在下面.. ok = mnesia:activity(transaction,fun(XX) -> mnesia:delete({free_airtime,XX}) end,[Ref_no],mnesia_frag)。
现在我认为在选项 2 中,通过将计时器处理代码排除在外,我会更安全,即使 mnesia_tm 由于其原因重新执行事务,这段代码也不会运行两次(我避免有多个计时器对象针对同一个记录)。
问题1:这两种实现中哪一种是正确的?和/或错误?告诉我(也)他们俩是否都错了
问题 2:模块定时器,它是否非常适合处理生产中的大量定时器作业?
问题 3:与运行在 mnesia 之上的 Sean Hinde 的timer_mn-1.1相比,timer 模块(可能在 Ets 表之上运行)在生产中的能力(实际上)是否更弱?(我问这个是因为在本身使用 mnesia 的系统上使用 Sean Hinde 的 timer_mn 在架构更改、节点问题等方面似乎是一个问题)
如果有人有另一种方法来处理与 mnesia 相关的计时器问题,请告诉我thanx 伙计们......