diff --git a/lib/ash.ex b/lib/ash.ex index 040e0e613..b2642cee0 100644 --- a/lib/ash.ex +++ b/lib/ash.ex @@ -4242,6 +4242,12 @@ defmodule Ash do end @transaction_opts_schema [ + tenant: [ + type: {:protocol, Ash.ToTenant}, + doc: """ + The tenant, placed on the transaction reason for data layers that select a connection per tenant. + """ + ], timeout: [ type: :timeout, doc: """ @@ -4328,7 +4334,7 @@ defmodule Ash do resource_or_resources, func, opts[:timeout], - %{type: :custom, metadata: %{}} + %{type: :custom, metadata: %{}, tenant: opts[:tenant]} ) do if opts[:return_notifications?] do notifications = Process.delete(:ash_notifications) || [] @@ -4431,7 +4437,7 @@ defmodule Ash do resource_or_resources, func, opts[:timeout], - %{type: :custom, metadata: %{}}, + %{type: :custom, metadata: %{}, tenant: opts[:tenant]}, rollback_on_error?: true ) do if opts[:return_notifications?] do diff --git a/lib/ash/actions/action.ex b/lib/ash/actions/action.ex index 3cf66c8d2..da39da93a 100644 --- a/lib/ash/actions/action.ex +++ b/lib/ash/actions/action.ex @@ -216,6 +216,7 @@ defmodule Ash.Actions.Action do input: input, actor: opts[:actor] }, + tenant: input.tenant, data_layer_context: input.context[:data_layer] || %{} }, rollback_on_error?: false diff --git a/lib/ash/actions/create/bulk.ex b/lib/ash/actions/create/bulk.ex index 4ab563fe0..3fb6fb6ca 100644 --- a/lib/ash/actions/create/bulk.ex +++ b/lib/ash/actions/create/bulk.ex @@ -80,6 +80,7 @@ defmodule Ash.Actions.Create.Bulk do action: action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || %{} }, rollback_on_error?: false @@ -671,6 +672,7 @@ defmodule Ash.Actions.Create.Bulk do action: action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || context }, rollback_on_error?: false diff --git a/lib/ash/actions/destroy/bulk.ex b/lib/ash/actions/destroy/bulk.ex index 2cd52cff6..e8b1027bf 100644 --- a/lib/ash/actions/destroy/bulk.ex +++ b/lib/ash/actions/destroy/bulk.ex @@ -356,6 +356,7 @@ defmodule Ash.Actions.Destroy.Bulk do action: atomic_changeset.action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || %{} }, rollback_on_error?: false @@ -539,6 +540,7 @@ defmodule Ash.Actions.Destroy.Bulk do action: action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || %{} }, rollback_on_error?: false @@ -1644,6 +1646,7 @@ defmodule Ash.Actions.Destroy.Bulk do action: action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || context }, rollback_on_error?: false diff --git a/lib/ash/actions/read/read.ex b/lib/ash/actions/read/read.ex index 9cfdd29c9..318260653 100644 --- a/lib/ash/actions/read/read.ex +++ b/lib/ash/actions/read/read.ex @@ -1599,6 +1599,7 @@ defmodule Ash.Actions.Read do resource: query.resource, action: query.action.name }, + tenant: query.tenant, data_layer_context: query.context[:data_layer] }, rollback_on_error?: false diff --git a/lib/ash/actions/update/bulk.ex b/lib/ash/actions/update/bulk.ex index 763b12e1a..e0503bb44 100644 --- a/lib/ash/actions/update/bulk.ex +++ b/lib/ash/actions/update/bulk.ex @@ -368,6 +368,7 @@ defmodule Ash.Actions.Update.Bulk do action: atomic_changeset.action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || %{} }, rollback_on_error?: false @@ -594,6 +595,7 @@ defmodule Ash.Actions.Update.Bulk do action: action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || %{} }, rollback_on_error?: false @@ -2021,6 +2023,7 @@ defmodule Ash.Actions.Update.Bulk do action: action.name, actor: opts[:actor] }, + tenant: opts[:tenant], data_layer_context: opts[:data_layer_context] || context }, rollback_on_error?: false diff --git a/lib/ash/actions/update/update_many.ex b/lib/ash/actions/update/update_many.ex index cf234f90b..26d29f060 100644 --- a/lib/ash/actions/update/update_many.ex +++ b/lib/ash/actions/update/update_many.ex @@ -122,7 +122,12 @@ defmodule Ash.Actions.Update.UpdateMany do atomic_notifications ++ manual_notifications} end, nil, - %{type: :bulk_update, metadata: %{resource: resource, action: action.name}} + %{ + type: :bulk_update, + metadata: %{resource: resource, action: action.name}, + tenant: opts[:tenant], + data_layer_context: opts[:data_layer_context] || %{} + } ) |> case do {:ok, {records, errors, notifications}} -> {records, errors, notifications} diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index f0016a9ba..27d37d9f2 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -4685,11 +4685,9 @@ defmodule Ash.Changeset do end end, changeset.timeout || :infinity, - Map.put( - opts[:transaction_metadata], - :data_layer_context, - changeset.context[:data_layer] || %{} - ), + opts[:transaction_metadata] + |> Map.put(:data_layer_context, changeset.context[:data_layer] || %{}) + |> Map.put(:tenant, changeset.tenant), rollback_on_error?: false ) |> case do diff --git a/lib/ash/data_layer/data_layer.ex b/lib/ash/data_layer/data_layer.ex index fb9b280f6..47631a301 100644 --- a/lib/ash/data_layer/data_layer.ex +++ b/lib/ash/data_layer/data_layer.ex @@ -16,6 +16,7 @@ defmodule Ash.DataLayer do %{ required(:type) => :create, required(:metadata) => %{resource: Ash.Resource.t(), action: atom}, + optional(:tenant) => term(), optional(:data_layer_context) => %{} } | %{ @@ -26,6 +27,7 @@ defmodule Ash.DataLayer do record: Ash.Resource.Record.t(), actor: term() }, + optional(:tenant) => term(), optional(:data_layer_context) => %{} } | %{ @@ -36,6 +38,7 @@ defmodule Ash.DataLayer do record: Ash.Resource.Record.t(), actor: term() }, + optional(:tenant) => term(), optional(:data_layer_context) => %{} } | %{ @@ -45,6 +48,7 @@ defmodule Ash.DataLayer do query: Ash.Query.t(), actor: term() }, + optional(:tenant) => term(), optional(:data_layer_context) => %{} } | %{ @@ -55,6 +59,7 @@ defmodule Ash.DataLayer do action: atom, actor: term() }, + optional(:tenant) => term(), optional(:data_layer_context) => %{} } | %{ @@ -64,10 +69,19 @@ defmodule Ash.DataLayer do flow: module(), actor: term() }, + optional(:tenant) => term(), optional(:data_layer_context) => %{} } - | %{required(:type) => :custom, required(:metadata) => map()} - | %{required(:type) => atom, required(:metadata) => map()} + | %{ + required(:type) => :custom, + required(:metadata) => map(), + optional(:tenant) => term() + } + | %{ + required(:type) => atom, + required(:metadata) => map(), + optional(:tenant) => term() + } @type combination_type :: :union | :union_all | :intersection