Mnesia Memento being update through iex and files except for oban jos

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

Running in an Oban job is the same as running in a Task. Is it running on a separate node or in a different environment?

We suggest that you try running it from iex in a task, e.g. with Task.start/1

It turns out this was related to an issue in the code. Oban rescues and records all exceptions and it wasn’t apparent that an error was happening.

1 Like

Hello! Thanks for the answer. i’m still working on this and having those issues of code silence breaking and not revealing its outputs, do you now any workaround?
example

 def job_should_continue(pubkey, target_value) do
   
    with  {:ok, mnesia_data} <- MnesiaPendingContractsDomain.get_record_by_pk(pubkey) do
      Logger.debug(mnesia_data.ok_trys)
      Logger.debug(mnesia_data.target_max_retrys)
      Logger.debug("resultado dessa porra de banco #{inspect(mnesia_data)}")
      if mnesia_data.ok_trys < mnesia_data.target_max_retrys do
         target_value = mnesia_data.amount
        main_function(pubkey, target_value)
      else
        Logger.debug("Limite de ok_trys atingido para pubkey #{pubkey}. Desenfileirando job.")
        :ok
      end

    else
      {:error, reason} ->
        Logger.debug("coudlt fetch job record #{reason}")
        :ok
    end
  end

on this code example, my structure doesnt have the “amount” field, and when I ran the job I didnt see any ouput revealing that, the job simple stops at this point

It was a problem in the code, the problem is that the job was just stoping at the breaking code without showing me the braking output on the console and it has been kind of hard bcs the job keeps doing this, so i’m having to look errors by eyes. Do you now how to work around this?

I followed the answer on the github and added the Oban.telemetry on my app

 def start(_type, _args) do
    Oban.Telemetry.attach_default_logger(encode: false, level: :debug)
    Memento.Table.create(MnesiaContract)
    Memento.Table.create(MnesiaPendingContracts)

still, when my job process breaking code, it stops without outputing

 with  {:ok, mnesia_data} <- MnesiaPendingContractsDomain.get_record_by_pk(pubkey) do
      Logger.debug(mnesia_data.ok_trys)
      Logger.debug(mnesia_data.target_max_retrys)
      Logger.debug("resultado dessa porra de banco #{inspect(mnesia_data)}")
      if mnesia_data.ok_trys < mnesia_data.target_max_retrys do
        Logger.debug("line before breaking ----}")
        mnesia_data.properror
        main_function(pubkey, target_value)
      else
        Logger.debug("Limite de ok_trys atingido para pubkey #{pubkey}. Desenfileirando job.")
        :ok
      end

[debug] 0
[debug] 15
[debug] resultado dessa porra de banco %MnesiaPendingContracts{__meta__: Memento.Table, pubkey: "6F7noaKZBa4W3D62qLu6sjJcVPKrkUGYmLfYK53FbvNm", last_attempt: 0, attempts: 0, time_limit: 100, job_id: 1, ok_trys: 0, failed_retrys: 0, target_max_retrys: 15}
[debug] line before breaking ----}

do I need extra config?