Mnesia: aborto inesperado, transacciones cíclicas
Tengo 5 procesos que insertan / actualizan los mismos 3 registros en una tabla de mnesia. Cada uno de estos procesos realiza su inserción / actualización dentro de una sola transacción.
Tengo otros 5 procesos que leen estos mismos 3 registros, también dentro de una sola transacción.
A menos que bloquee toda la tabla como parte de la transacción de registros múltiples, recibo un error {abortado, {cíclico, nodo ...}}. Mi intuición es que mi caso de uso es ordinario y no debería, en sí mismo, resultar en una transacción abortada. ¿Alguien puede ayudarme con mi pensamiento descabellado? Todo lo que estoy haciendo es insertar (o leer) varias filas en un caché (tabla de mnesia) en una transacción.
Insertando los 3 registros se ve así
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: reemplazar, insertar y buscar son los siguientes:
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.