я пишу записи в мнезию, которые должны храниться там
только на разрешенное время (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 повторно выполняет транзакцию по причинам
этот кусок кода не запускается дважды (я избегаю иметь несколько объектов таймера
против той же записи).
Вопрос 1: Какая из этих двух реализаций верна? и / или неправильно? Скажи мне (также)
не правы ли они оба
Вопрос 2: Модуль таймера, хорошо ли он подходит для обработки большого количества таймеров
рабочие места на производстве?
Вопрос 3: По сравнению с * 1036 Шона Хинда * timer_mn-1.1 ,
который работает поверх mnesia, является модулем таймера (возможно, работает поверх таблиц Ets) меньше
способен (реально) на производство?
(Я спрашиваю это, потому что появляется использование timer_mn Шона Хинда в системе, которая сама использует mnesia
быть проблемой в терминах изменений схемы, проблем узлов e.t.c)
Если у кого-то есть другой способ решения связанных с таймером проблем с mnesia, сообщите мне
спасибо, ребята ...