Mnesia: inesperadamente sendo abortada, transações cíclicas
Tenho 5 processos que inserem / atualizam os mesmos 3 registros em uma tabela de mnésia. Cada um desses processos faz suas inserções / atualizações em uma única transaçã
Tenho 5 outros processos que lêem esses mesmos 3 registros, também em uma única transaçã
A menos que eu trave a tabela inteira como parte da transação de vários registros, recebo um erro {abortado, {cyclic, node ....}}. Minha intuição é que meu caso de uso é comum e não deve, por si só, resultar em uma transação abortada. Alguém pode me ajudar com meu pensamento tonto? Tudo o que estou fazendo é inserir (ou ler) várias linhas em um cache (tabela de mnésia) em uma transaçã
Inserir os 3 registros é assim
insert_keylist(Keys) ->
F = fun() -> insert_iter(Keys) end,
transactional_execute(F).
insert_iter([]) ->
ok;
insert_iter([{Key, Value} | KVs]) ->
insert(Key, Value),
insert_iter(Kvs).
insert(Key, Value) ->
F =
fun() ->
case sc_store:lookup(Key) of
{ok, _Value} -> sc_store:replace(Key, Value);
{error, not_found} -> sc_store:insert(Key,Value)
end
end,
transactional_execute(F).
transactional_execute(F) ->
case mnesia:is_transaction() of
true -> F();
false ->
try mnesia:sync_transaction(F) of
{atomic, Result} -> Result;
{aborted, Reason} -> {aborted, Reason}
catch
ErrorCl:Error -> {error, {ErrorCl, Error}}
end
end.
sc_store: substituir, inserir e pesquisar são os seguintes:
replace(Key, Value) ->
try
case mnesia:wread({key_to_value, Key}) of
[#key_to_value{} = Rec] ->
mnesia:write(Rec#key_to_value{value = Value});
[] ->
{error, not_found}
end
catch
_Err:Reason ->
{error, Reason}
end.
insert(Key, Value, Type, Scope, TTL, TTLMessage, Ref) ->
try
NowDT = calendar:now_to_datetime(erlang:now()),
ok = mnesia:write(#key_to_value{key = Key,
type = Type,
scope = Scope,
value = Value,
create_time_dt = NowDT,
ttl_secs = TTL,
ttl_message = TTLMessage,
ref = Ref})
catch
_Error:Reason ->
{error, Reason}
end.
lookup(Key) ->
try
case mnesia:read(key_to_value, Key) of
[#key_to_value{type = Type, scope = Scope, value = Value}] ->
{ok, {Value, Type, Scope}};
[] ->
{error, not_found}
end
catch
_Err:Reason -> {error, Reason}
end.