Oban / Ecto / Jason error when trying to cancel_job using args map in where statement

UPDATE
Ok, I figured out that this is a Jason issue. Can someone tell me if this code will solve my problem (detailed below) of trying to search Oban args for a specific map. This is all way over my head. :frowning:

def cancel_reminders(event_id) do
    with {:ok, encoded_map} <- Jason.encode(%{"event_id" => event_id}) do
      Oban.Job
      |> Ecto.Query.where(queue: :reminder_scheduler)
      |> Ecto.Query.where(args: ^encoded_map)
      |> Oban.cancel_all_jobs()
    end
  end

My app sends reminders for events. If an event is cancelled, I need to delete the reminders from the Oban scheduler. I’ve written the code exactly like the example in Oban, but I keep getting an error. I think it’s an Ecto error but I can’t figure out why it can’t pattern match on that map value.

Can someone tell me what I need to do to search the Oban args for a specific map?

def cancel_reminders(event_id) do
    Oban.Job
    |> Ecto.Query.where(queue: :reminder_scheduler)
    |> Ecto.Query.where(args: %{"event_id" => ^event_id})
    |> Oban.cancel_all_jobs()
  end

Error:
Compilation error in file lib/myApp/reminder_scheduler.ex ==
** (Ecto.Query.CompileError) %{"event_id" => ^event_id} is not a valid query expression.

  • If you intended to call an Elixir function or introduce a value,
    you need to explicitly interpolate it with ^

  • If you intended to call a database function, please check the documentation
    for Ecto.Query.API to see the supported database expressions

  • If you intended to extend Ecto’s query DSL, make sure that you have required
    the module or imported the relevant function. Note that you need macros to
    extend Ecto’s querying capabilities

When using Ecto.Query.where without bindings, the second argument is expected to be a plain keyword list so you don’t need the ^.

I get this error when I remove the “^”:

Oban.Job
      |> Ecto.Query.where(queue: :reminder_scheduler)
      |> Ecto.Query.where(args: ^encoded_map)
      |> Oban.cancel_all_jobs()

ERROR:
unbound variable `encoded_map` in query. If you are attempting to interpolate a value, use ^var
    (ecto 3.8.4) expanding macro: Ecto.Query.where/2

There’s no need to encode the map. Instead, use a different form of where and bind the entire map:

  import Ecto.Query, only: [where: 3]

  Oban.Job
  |> where([j], j.queue == "reminder_scheduler")
  |> where([j], j.args == ^%{"event_id" => event_id})
  |> Oban.cancel_all_jobs()
1 Like

Yay! That compiles! I haven’t been able to test it yet, because I’m still fixing other run time errors, but I should be able to test it soon. Thank you so much!