{@thread.name}

.adamharris
2023-06-06

.adamharris:

Hi, I’m trying to upgrade to the latest version of Ash (2.9.21) and my tests are failing after the upgrade.

In particular, I have code like this:

MyApi.load!(record, :some_calculation, tenant: t)

which previously worked, but now is giving an error of the form:

%Ash.Error.Invalid{
  errors: [%Ash.Error.Invalid.TenantRequired{
    resource: MyApi.MyParentResource, changeset: nil, query: nil, error_context: [], vars: [], path: [], stacktrace: #Stacktrace<>, class: :invalid}], stacktraces?: true, changeset: nil, query: #Ash.Query}, errors: [%Ash.Error.Invalid{errors: [%Ash.Error.Invalid.TenantRequired{resource: MyApi.MyParentResource, changeset: nil, query: nil, error_context: [], vars: [], path: [], stacktrace: #Stacktrace<>, class: :invalid}], stacktraces?: true, changeset: nil, query: #Ash.Query, errors: [%Ash.Error.Invalid.TenantRequired{resource: MyApi.MyParentResource, changeset: nil, query: nil, error_context: [], vars: [], path: [], stacktrace: #Stacktrace<>, class: :invalid}], select: [:id, :inserted_at, :updated_at, ... :MyParentResource_type, ...]>, error_context: [], vars: [], path: [], stacktrace: #Stacktrace<>, class: :invalid}, %Ash.Error.Invalid.TenantRequired{resource: MyApi.MyParentResource, changeset: nil, query: nil, error_context: [], vars: [], path: [], stacktrace: #Stacktrace<>, class: :invalid}]>, error_context: [nil], vars: [], path: [], stacktrace: #Stacktrace<>, class: :invalid}

Basically I’m trying to load a calculation on a resource that has a related parent - and now it’s not picking the tenant up. The API of the load function seems the same after the version bump - Any ideas what has changed here?

kernel_io:

random but can you try setting the tenant with Ash.set_tenant/1 beforehand?

.adamharris:

<@891520354802106389> thanks for the suggestion! If I call Ash.set_tenant(t) at the start of the test I get the following:

** (RuntimeError) Engine Deadlock! No async tasks and state is the same after iteration.

kernel_io:

🙀

kernel_io:

crazy, I didn’t actually think you would need to add tenant as an opt for the load to begin with (as your record should have the tenant set in the metadata field)

.adamharris:

<@197905764424089601> could this be a bug?

zachdaniel:

an engine deadlock is 100% a bug

zachdaniel:

What version did you upgrade from?

.adamharris:

2.6.21

zachdaniel:

oh damn

zachdaniel:

😆

.adamharris:

it looks like the tenant id is not being passed from a child to parent in a query for a calculation…? could this be causing a bug, that then manifests in the deadlock?

zachdaniel:

Okay, so when you say it has a related parent, do you mean the calculation depends on the parent record?

zachdaniel:

yeah, that is the likely cause

zachdaniel:

I’m thinking it should be a relatively simple change to get the tenant where it needs to be here

.adamharris:

yes - the calculation in the child depends on the parent. it has the following code at the top of the calculation:

...
  @impl true
  def load(_query, _opts, _context), do: [:parent]

  @impl true
  def calculate(records, _opts, _) do
    Enum.map(records, fn child ->
      p = child.parent
...

zachdaniel:

can you try main?

zachdaniel:

actually…I’m still not 100% sure. That might fix it, lemme konw

.adamharris:

<@197905764424089601> it didn’t fix it - still getting the TenantRequired error

zachdaniel:

Okay, thought that might happen

zachdaniel:

is there a stacktrace?

.adamharris:

** (Ash.Error.Invalid) Input Invalid

     * Queries against the MyApi.MyParentResource resource require a tenant to be specified
       (ash 2.9.21) lib/ash/actions/read.ex:612: Ash.Actions.Read.validate_multitenancy/1
       (ash 2.9.21) lib/ash/actions/read.ex:325: anonymous fn/12 in Ash.Actions.Read.as_requests/5
       (ash 2.9.21) lib/ash/engine/request.ex:1063: Ash.Engine.Request.do_try_resolve_local/4
       (ash 2.9.21) lib/ash/engine/request.ex:932: Ash.Engine.Request.do_try_resolve/5
       (elixir 1.14.5) lib/enum.ex:4751: Enumerable.List.reduce/3
       (elixir 1.14.5) lib/enum.ex:2514: Enum.reduce_while/3
       (ash 2.9.21) lib/ash/engine/request.ex:998: Ash.Engine.Request.do_try_resolve_local/4
       (ash 2.9.21) lib/ash/engine/request.ex:282: Ash.Engine.Request.do_next/1
       (ash 2.9.21) lib/ash/engine/request.ex:211: Ash.Engine.Request.next/1
       (ash 2.9.21) lib/ash/engine/engine.ex:712: Ash.Engine.advance_request/2
       (ash 2.9.21) lib/ash/engine/engine.ex:637: Ash.Engine.fully_advance_request/2
       (ash 2.9.21) lib/ash/engine/engine.ex:578: Ash.Engine.do_run_iteration/2
       (elixir 1.14.5) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
       (ash 2.9.21) lib/ash/engine/engine.ex:307: Ash.Engine.run_to_completion/1
       (ash 2.9.21) lib/ash/engine/engine.ex:252: Ash.Engine.do_run/2
       (ash 2.9.21) lib/ash/engine/engine.ex:148: Ash.Engine.run/2
       (ash 2.9.21) lib/ash/actions/read.ex:173: Ash.Actions.Read.do_run/3
       (ash 2.9.21) lib/ash/actions/read.ex:96: Ash.Actions.Read.run/3

.adamharris:

     stacktrace:
       (ash 2.9.21) lib/ash/error/error.ex:461: Ash.Error.choose_error/2
       (ash 2.9.21) lib/ash/error/error.ex:218: Ash.Error.to_error_class/2
       (ash 2.9.21) lib/ash/actions/read.ex:184: Ash.Actions.Read.do_run/3
       (ash 2.9.21) lib/ash/actions/read.ex:96: Ash.Actions.Read.run/3
       (ash 2.9.21) lib/ash/actions/load.ex:783: anonymous fn/11 in Ash.Actions.Load.calc_dep_data/12
       (ash 2.9.21) lib/ash/engine/request.ex:1048: Ash.Engine.Request.do_try_resolve_local/4
       (ash 2.9.21) lib/ash/engine/request.ex:282: Ash.Engine.Request.do_next/1
       (ash 2.9.21) lib/ash/engine/request.ex:211: Ash.Engine.Request.next/1
       (ash 2.9.21) lib/ash/engine/engine.ex:712: Ash.Engine.advance_request/2
       (ash 2.9.21) lib/ash/engine/engine.ex:637: Ash.Engine.fully_advance_request/2
       (ash 2.9.21) lib/ash/engine/engine.ex:578: Ash.Engine.do_run_iteration/2
       (elixir 1.14.5) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
       (ash 2.9.21) lib/ash/engine/engine.ex:307: Ash.Engine.run_to_completion/1
       (ash 2.9.21) lib/ash/engine/engine.ex:252: Ash.Engine.do_run/2
       (ash 2.9.21) lib/ash/engine/engine.ex:148: Ash.Engine.run/2
       (ash 2.9.21) lib/ash/actions/read.ex:173: Ash.Actions.Read.do_run/3
       (ash 2.9.21) lib/ash/actions/read.ex:96: Ash.Actions.Read.run/3
       (ash 2.9.21) lib/ash/api/api.ex:1657: Ash.Api.load/4

zachdaniel:

okay, pushed something up again that might do it

zachdaniel:

if this doesn’t work then we’re going to need to get a test reproduction in ash

.adamharris:

no, I’m getting the same error unfortunately

zachdaniel:

damn. Okay, so the best way for me to fix this would be a test file that defines two multitenant resources and has a similar calculation.

.adamharris:

I’ll try and sort one for you tomorrow morning and stick it in a pull request if that would help?

zachdaniel:

That would help immensely 🙂

zachdaniel:

Got a lot of plates spinning at the moment, that will make things much easier

.adamharris:

<@197905764424089601>

https://github.com/ash-project/ash/pull/606

.adamharris:

Sorry it’s a bit messy and brief - I had very little time this morning so put it together in a rush

.adamharris:

I edited one of the test files relating to calculations, adding a failing test fro accessing a calculation on a parent from a child, in a multitenant context

zachdaniel:

Beautiful, thanks!