Run into problems with Ash Postgress 2.0 RC (Ash.Error.Framework) Framework Error

Hello → I am working through some of the Getting Started guides for the Ash Framework 3.0.0-rc.27.

This worked just fine but now I have moved on to the Ash Postres 2.0.0-rc.10 Getting Started with Postgres.

I am getting errors with the update script as it is described. The ‘representative’ is created but only one ticket is created and the script fails with the following error:

** (Ash.Error.Framework) Framework Error

* Helpdesk.Support.Ticket.assign must be performed atomically, but it could not be

Reason: cannot atomically manage relationships

See https://hexdocs.pm/ash/3.0.0-rc.15/update-actions.html#atomic-updates for more on atomics.

There is also a compiler warning:

warning: [Helpdesk.Support.Ticket]
 actions -> assign:
  `Helpdesk.Support.Ticket.assign` cannot be done atomically, because the changes `[Ash.Resource.Change.ManageRelationship]` cannot be done atomically

You must either address the issue or set `require_atomic? false` on `Helpdesk.Support.Ticket.assign`.

  lib/helpdesk/support/ticket.ex:1: Helpdesk.Support.Ticket.__verify_spark_dsl__/1

If I modify the Helpdesk.Support.Ticket.assign as suggested it fixes the first update in the script.

    update :assign do
      # No attributes should be accepted
      accept []

      # We accept a representative's id as input here
      argument :representative_id, :uuid do
        # This action requires representative_id
        allow_nil? false
      end

      require_atomic? false ## ADDED THIS 

      # We use a change here to replace the related Representative
      # If there is a different representative for this Ticket, it will be changed to the new one
      # The Representative itself is not modified in any way
      change manage_relationship(:representative_id, :representative, type: :append_and_remove)
    end
  end

But the second part of the script fails on the update to the call to Helpdesk.Support.Ticket.close with a similar error:

** (Ash.Error.Invalid) Invalid Error

* Invalid value provided for id: Ticket is already closed.

"closed"

  (elixir 1.16.2) lib/process.ex:860: Process.info/2
  (ash 3.0.0-rc.27) lib/ash/error/changes/invalid_attribute.ex:5: Ash.Error.Changes.InvalidAttribute.exception/1
  (ash_postgres 2.0.0-rc.8) lib/data_layer.ex:1966: AshPostgres.DataLayer.handle_raised_error/4
  (ash 3.0.0-rc.27) lib/ash/actions/update/bulk.ex:342: Ash.Actions.Update.Bulk.do_atomic_update/5
  (ash 3.0.0-rc.27) lib/ash/actions/update/bulk.ex:175: Ash.Actions.Update.Bulk.run/6
  (ash 3.0.0-rc.27) lib/ash/actions/update/update.ex:121: Ash.Actions.Update.run/4
  (ash 3.0.0-rc.27) lib/ash.ex:2351: Ash.update/2
  (ash 3.0.0-rc.27) lib/ash.ex:2329: Ash.update!/2
    (elixir 1.16.2) lib/process.ex:860: Process.info/2
    (ash 3.0.0-rc.27) lib/ash/error/invalid.ex:5: Ash.Error.Invalid.exception/1
    (ash 3.0.0-rc.27) /home/michael_intandem/src/elixir_src/learning/ash_framework/helpdesk/deps/splode/lib/splode.ex:211: Ash.Error.to_class/2
    (ash 3.0.0-rc.27) lib/ash/error/error.ex:33: Ash.Error.to_error_class/2
    (ash 3.0.0-rc.27) lib/ash/actions/update/bulk.ex:460: Ash.Actions.Update.Bulk.do_atomic_update/5
    (ash 3.0.0-rc.27) lib/ash/actions/update/bulk.ex:175: Ash.Actions.Update.Bulk.run/6
    (ash 3.0.0-rc.27) lib/ash/actions/update/update.ex:121: Ash.Actions.Update.run/4
    (ash 3.0.0-rc.27) lib/ash.ex:2351: Ash.update/2

Not sure about the first part, but

This might be related to Atomic changes are incorrectly carried over during atomic upgrade · Issue #1042 · ash-project/ash · GitHub
which Zach has fixed in main. Can you try the main branch?

{:ash, git: "https://github.com/ash-project/ash.git", branch: "main", override: true},
{:picosat_elixir, "~> 0.2"},
{:ash_postgres, "~> 2.0.0-rc"}
2 Likes

Thank you for the quick reply!

And the solution! This fixed my problem for the second update in the script.

The first update still requires me to add the “require_atomic? false” to assign Helpdesk.Support.Ticket.assign call though. If that is a requirement then the tutorial should be updated to add that line in there.

require Ash.Query

representative = (
  Helpdesk.Support.Representative
  |> Ash.Changeset.for_create(:create, %{name: "Joe Armstrong"})
  |> Helpdesk.Support.create!()
)

for i <- 0..5 do
  ticket =
    Helpdesk.Support.Ticket
    |> Ash.Changeset.for_create(:open, %{subject: "Issue #{i}"})
    |> Helpdesk.Support.create!()
    |> Ash.Changeset.for_update(:assign, %{representative_id: representative.id})
    |> Helpdesk.Support.update!() # THIS STILL REQUIRES "require_atomic? false" in the Helpdesk.Support.Ticket.assign call 

  if rem(i, 2) == 0 do
    ticket
    |> Ash.Changeset.for_update(:close)
    |> Helpdesk.Support.update!() # UPDATING MY DEPENDENCY TO "main" FIXED THIS.
  end
end
1 Like

Ah, right, because currently manage_relationship can’t be done atomically. I will update the assign action in the tutorial to just accept [:representative_id], to avoid having to introduce atomics in an introductory setting like that. Thank you for pointing this out :bowing_man: