私は記録をmnesiaに書き込んでいますが、それは許可された時間(24時間)だけそこに保持する必要があります。24時間後、ユーザーがそれらの一部を変更する前に、システムはそれらを自動的に削除する必要があります。たとえば、ユーザーには、特定の時間に使用する必要のある無料の通話時間(音声通話用)が与えられます。使用しない場合は、24時間後に、システムはこれらのリソース予約をユーザーレコードから削除する必要があります。
さて、これはタイマーをもたらしました。レコード構造の例は次のとおりです。
-record(free_airtime、 {{ reference_no、 timer_object、timer:apply_after/4によって返される%%値 額 })。
レコード内のタイマーオブジェクトは重要です。ユーザーがタイムアウトする前に予約されたリソースを最終的に使用した場合(またはタイムアウトした場合)、システムはtimer:cancel/1
このオブジェクトからタイマーサーバーを解放するために呼び出すことができます。問題は、これらのレコードのタイマーを処理する2つの方法があります。
オプション1:トランザクション内で処理されるタイマー
reserved_resources(Reference_no、Amnt)-> F = fun(Ref_no、Amount)-> ケースmnesia:read({free_airtime、Ref_no})of []-> case mnesia:write(#free_airtime {reference_no = Ref_no、amount = Amount})== ok of true-> ケース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}) 終わり; 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:トランザクション外で処理されるタイマー
reserved_resources(Reference_no、Amnt)-> F = fun(Ref_no、Amount)-> ケース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}) 終わり 終わり、 結果=mnesia:activity(transaction、F、[Reference_no、Amnt]、mnesia_frag)を試してください 任意->任意 キャッチ exit:{aborted、{error、exists、XX}}-> {exists、XX} E1:E2-> {エラー、{E1、E2}} 終わり、 on_reservation(結果)。 on_reservation(#free_airtime {reference_no = Some_Ref})-> ケース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} 終わり; on_reservation(Any)->Any。
予約のタイムアウトを処理するためのコード:
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がトランザクションを再実行した場合でも、タイマー処理コードを除外する方が安全だと思いました。このコードは2回実行されません(同じものに対して複数のタイマーオブジェクトを使用しないようにします)。記録)。
質問1:これら2つの実装のどちらが正しいですか?および/または間違っていますか?(また)両方が間違っているかどうか教えてください
質問2:モジュールタイマー、本番環境で多数のタイマージョブを処理するのに適していますか?
質問3: mnesia上で実行されるSean Hindeのtimer_mn-1.1と比較して、タイマーモジュール(おそらくEtsテーブル上で実行される)は本番環境で(実際には)機能が劣っていますか?(それ自体がmnesiaを使用しているシステムでSean Hindeのtimer_mnを使用することは、スキーマの変更、ノードの問題などの点で問題があるように見えるため、これを求めています)
誰かがmnesiaのタイマー関連の問題を処理する別の方法を持っているなら、私に更新してくださいありがとうみんな...