I have the given Mnesia domain
defmodule MnesiaPendingContracts do
require Logger
use Memento.Table,
attributes: [:pubkey, :last_attempt, :attempts, :time_limit, :ok_trys, :failed_retrys],
type: :ordered_set
end
defmodule Testespay.DataLayer.MnesiaPendingContractsDomain do
require Logger
alias Memento.Query
@time_limit Application.get_env(:testespay, :transaction_seconds_time_limit)
def insert_record(pk) do
Memento.transaction(fn ->
record = %MnesiaPendingContracts{
pubkey: pk,
last_attempt: 0,
attempts: 0,
time_limit: @time_limit,
ok_trys: 0,
failed_retrys: 0
}
Query.write(record)
end)
end
def att_ok_trys(pk) do
Memento.transaction!(fn ->
case Memento.Query.read(MnesiaPendingContracts, pk) do
nil ->
Logger.debug("Registro nĂŁo encontrado para: #{pk}")
:not_found
record ->
Logger.debug("enter ------------------------------------------------------------------------------------------------------------")
updated = %{record |
ok_trys: record.ok_trys + 1,
last_attempt: DateTime.utc_now()
}
Logger.debug("------------------------------------------------------------------------------------------------------------")
Logger.debug(updated)
Memento.Query.write(updated)
end
end)
end
def att_failed_retrys(pk) do
Memento.transaction!(fn ->
case Memento.Query.read(MnesiaPendingContracts, pk) do
nil ->
Logger.debug("Registro nĂŁo encontrado para: #{pk}")
:not_found
record ->
updated = %{record |
failed_retrys: record.failed_retrys + 1,
last_attempt: DateTime.utc_now()
}
Memento.Query.write(updated)
end
end)
end
I can call att_ok_trys from iex
iex(1)> Testespay.DataLayer.MnesiaPendingContractsDomain.insert_record("A")
{:ok,
%MnesiaPendingContracts{
__meta__: Memento.Table,
pubkey: "A",
last_attempt: 0,
attempts: 0,
time_limit: 100,
ok_trys: 0,
failed_retrys: 0
}}
[debug] enter ------------------------------------------------------------------------------------------------------------
[debug] ------------------------------------------------------------------------------------------------------------
[debug] [__struct__: MnesiaPendingContracts, __meta__: Memento.Table, pubkey: "A", last_attempt: ~U[2025-02-26 01:15:21.442310Z], attempts: 0, time_limit: 100, ok_trys: 1, failed_retrys: 0]
%MnesiaPendingContracts{
__meta__: Memento.Table,
pubkey: "A",
last_attempt: ~U[2025-02-26 01:15:21.442310Z],
attempts: 0,
time_limit: 100,
ok_trys: 1,
failed_retrys: 0
}
and it works
I can call from a gen server init callback
defmodule Testespay.Backgroundjobs.FetchAwaitingContracts do
alias Testespay.Oban.PubkeyCheckWorker
use GenServer
require Logger
alias Testespay.DataLayer.MnesiaDomain
alias Oban
alias Testespay.DataLayer.MnesiaPendingContractsDomain
@interval 5_000 # 5 segundos
def start_link(_) do
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
end
@impl true
def init(state) do
MnesiaPendingContractsDomain.insert_record("address")
MnesiaPendingContractsDomain.att_ok_trys("address")
schedule_work()
{:ok, state}
end
[debug] enter ------------------------------------------------------------------------------------------------------------
[debug] ------------------------------------------------------------------------------------------------------------
[debug] [struct: MnesiaPendingContracts, pubkey: “address”, meta: Memento.Table, last_attempt: ~U[2025-02-26 01:31:20.746365Z], attempts: 0, time_limit: 100, ok_trys: 1, failed_retrys: 0]
Interactive Elixir (1.17.0) - press Ctrl+C to exit (type h() ENTER for help)
[info] Starting background task to fetch recent contracts
[debug] {:ok, [%MnesiaPendingContracts{meta: Memento.Table, pubkey: “address”, last_attempt: ~U[2025-02-26 01:31:20.746365Z], attempts: 0, time_limit: 100, ok_trys: 1, failed_retrys: 0}]}
[debug] Resultado fetching: [%MnesiaPendingContracts{meta: Memento.Table, pubkey: “address”, last_attempt: ~U[2025-02-26 01:31:20.746365Z], attempts: 0, time_limit: 100, ok_trys: 1, failed_retrys: 0}]
[debug] {:ok, }
[info] No unexpired contracts found in Mnesia.
on a handle info
def handle_info(:work, state) do
Logger.info("on handle info callback")
MnesiaPendingContractsDomain.insert_record("address")
MnesiaPendingContractsDomain.att_ok_trys("address")
[info] on handle info callback
[debug] enter ------------------------------------------------------------------------------------------------------------
[debug] ------------------------------------------------------------------------------------------------------------
[debug] [struct: MnesiaPendingContracts, pubkey: “address”, meta: Memento.Table, last_attempt: ~U[2025-02-26 01:36:58.362964Z], attempts: 0, time_limit: 100, ok_trys: 1, failed_retrys: 0]
but when I try to run it from an oban job, doesn’t work
def perform(%Oban.Job{attempt: attempt, meta: meta} = job) do
Logger.configure(level: :debug)
Logger.debug("initing job....")
contract_data = job.args["contract"]
address = contract_data["pubkey"]
target_value = contract_data["amount"]
case perform_request(address) do
{:ok, response_value}->
MnesiaPendingContractsDomain.insert_record(address)
MnesiaPendingContractsDomain.att_ok_trys(address)
case handle_check_balance(response_value, target_value) do
:paid -> :ok
{:snooze, @snooze_time} -> {:snooze, @snooze_time}
end
{:error, :rate_limit} ->
MnesiaPendingContractsDomain.att_failed_retrys(address)
{:error, reason} -> {:snooze, @snooze_time}
end
end
[debug] initing job…
[debug] init request…
[debug] 35XeuP2xcB4KQ6EU3NVMenNMnVYQet84knezSoE2zzRY
[debug] https://rpc.ankr.com/solana_devnet/ae321adefbcd42cb37d0790c522ce876c7e9f19dbfece1d44b9e90845e855100
[debug] Resposta recebida: %Finch.Response{status: 200, body: “{"id":1,"jsonrpc":"2.0","result":{"context":{"apiVersion":"2.1.14","slot":363622841},"value":0}}”, headers: [{“date”, “Wed, 26 Feb 2025 01:39:45 GMT”}, {“content-type”, “application/json”}, {“content-length”, “96”}, {“connection”, “keep-alive”}, {“strict-transport-security”, “max-age=15724800; includeSubDomains”}, {“access-control-allow-origin”, “*”}, {“access-control-allow-credentials”, “true”}, {“access-control-allow-methods”, “GET, PUT, POST, DELETE, PATCH, OPTIONS”}, {“access-control-allow-headers”, “DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,solana-client”}, {“access-control-max-age”, “1728000”}], trailers: }
[debug] Resposta HTTP 200: {“id”:1,“jsonrpc”:“2.0”,“result”:{“context”:{“apiVersion”:“2.1.14”,“slot”:363622841},“value”:0}}
[debug] Saldo extraĂdo: 0