Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ spark_locals_without_parens = [
not_found_error?: 1,
not_found_message: 1,
notification_metadata: 1,
notification_metadata: 2,
notifiers: 1,
notify?: 1,
offset?: 1,
Expand Down
162 changes: 160 additions & 2 deletions documentation/dsls/DSL-Ash.Reactor.md
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ Caveats/differences from `Ash.bulk_create/4`:
* [guard](#reactor-bulk_create-guard)
* [where](#reactor-bulk_create-where)
* [load](#reactor-bulk_create-load)
* [notification_metadata](#reactor-bulk_create-notification_metadata)
* [tenant](#reactor-bulk_create-tenant)
* [wait_for](#reactor-bulk_create-wait_for)

Expand Down Expand Up @@ -703,7 +704,6 @@ end
| [`authorize_query_with`](#reactor-bulk_create-authorize_query_with){: #reactor-bulk_create-authorize_query_with } | `:filter \| :error` | `:filter` | If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error |
| [`batch_size`](#reactor-bulk_create-batch_size){: #reactor-bulk_create-batch_size } | `nil \| pos_integer` | | The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. |
| [`max_concurrency`](#reactor-bulk_create-max_concurrency){: #reactor-bulk_create-max_concurrency } | `non_neg_integer` | `0` | If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously. |
| [`notification_metadata`](#reactor-bulk_create-notification_metadata){: #reactor-bulk_create-notification_metadata } | `map \| Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value` | `%{}` | Metadata to be merged into the metadata field for all notifications sent from this operation. |
| [`notify?`](#reactor-bulk_create-notify?){: #reactor-bulk_create-notify? } | `boolean` | `false` | Whether or not to generate any notifications. This may be intensive for large bulk actions. |
| [`read_action`](#reactor-bulk_create-read_action){: #reactor-bulk_create-read_action } | `atom` | | The action to use when building the read query. |
| [`return_errors?`](#reactor-bulk_create-return_errors?){: #reactor-bulk_create-return_errors? } | `boolean` | `true` | Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. |
Expand Down Expand Up @@ -917,6 +917,37 @@ Allows the addition of an Ash load statement to the action

Target: `Ash.Reactor.Dsl.ActionLoad`

### reactor.bulk_create.notification_metadata
```elixir
notification_metadata source
```


Specifies metadata to be merged into the metadata field for all notifications sent from this operation





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source`](#reactor-bulk_create-notification_metadata-source){: #reactor-bulk_create-notification_metadata-source .spark-required} | `Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value \| map \| nil` | | What to use as the source of the notification metadata. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`transform`](#reactor-bulk_create-notification_metadata-transform){: #reactor-bulk_create-notification_metadata-transform } | `(any -> any) \| module \| nil` | | An optional transformation function which can be used to modify the notification metadata before it is passed to the action. |





### Introspection

Target: `Ash.Reactor.Dsl.NotificationMetadata`

### reactor.bulk_create.tenant
```elixir
tenant source
Expand Down Expand Up @@ -1030,6 +1061,7 @@ Caveats/differences from `Ash.bulk_update/4`:
* [guard](#reactor-bulk_update-guard)
* [where](#reactor-bulk_update-where)
* [inputs](#reactor-bulk_update-inputs)
* [notification_metadata](#reactor-bulk_update-notification_metadata)
* [tenant](#reactor-bulk_update-tenant)
* [wait_for](#reactor-bulk_update-wait_for)

Expand Down Expand Up @@ -1067,7 +1099,6 @@ end
| [`filter`](#reactor-bulk_update-filter){: #reactor-bulk_update-filter } | `map \| keyword` | | A filter to apply to records. This is also applied to a stream of inputs. |
| [`lock`](#reactor-bulk_update-lock){: #reactor-bulk_update-lock } | `any` | | A lock statement to add onto the query. |
| [`max_concurrency`](#reactor-bulk_update-max_concurrency){: #reactor-bulk_update-max_concurrency } | `non_neg_integer` | `0` | If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously. |
| [`notification_metadata`](#reactor-bulk_update-notification_metadata){: #reactor-bulk_update-notification_metadata } | `map \| Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value` | `%{}` | Metadata to be merged into the metadata field for all notifications sent from this operation. |
| [`notify?`](#reactor-bulk_update-notify?){: #reactor-bulk_update-notify? } | `boolean` | `false` | Whether or not to generate any notifications. This may be intensive for large bulk actions. |
| [`page`](#reactor-bulk_update-page){: #reactor-bulk_update-page } | `keyword` | `[]` | Pagination options, see `Ash.read/2` for more. |
| [`read_action`](#reactor-bulk_update-read_action){: #reactor-bulk_update-read_action } | `atom` | | The action to use when building the read query. |
Expand Down Expand Up @@ -1298,6 +1329,37 @@ inputs(author: result(:get_user))

Target: `Ash.Reactor.Dsl.Inputs`

### reactor.bulk_update.notification_metadata
```elixir
notification_metadata source
```


Specifies metadata to be merged into the metadata field for all notifications sent from this operation





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source`](#reactor-bulk_update-notification_metadata-source){: #reactor-bulk_update-notification_metadata-source .spark-required} | `Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value \| map \| nil` | | What to use as the source of the notification metadata. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`transform`](#reactor-bulk_update-notification_metadata-transform){: #reactor-bulk_update-notification_metadata-transform } | `(any -> any) \| module \| nil` | | An optional transformation function which can be used to modify the notification metadata before it is passed to the action. |





### Introspection

Target: `Ash.Reactor.Dsl.NotificationMetadata`

### reactor.bulk_update.tenant
```elixir
tenant source
Expand Down Expand Up @@ -1554,6 +1616,7 @@ Declares a step that will call a create action on a resource.
* [where](#reactor-create-where)
* [inputs](#reactor-create-inputs)
* [load](#reactor-create-load)
* [notification_metadata](#reactor-create-notification_metadata)
* [tenant](#reactor-create-tenant)
* [wait_for](#reactor-create-wait_for)

Expand Down Expand Up @@ -1830,6 +1893,37 @@ Allows the addition of an Ash load statement to the action

Target: `Ash.Reactor.Dsl.ActionLoad`

### reactor.create.notification_metadata
```elixir
notification_metadata source
```


Specifies metadata to be merged into the metadata field for all notifications sent from this operation





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source`](#reactor-create-notification_metadata-source){: #reactor-create-notification_metadata-source .spark-required} | `Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value \| map \| nil` | | What to use as the source of the notification metadata. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`transform`](#reactor-create-notification_metadata-transform){: #reactor-create-notification_metadata-transform } | `(any -> any) \| module \| nil` | | An optional transformation function which can be used to modify the notification metadata before it is passed to the action. |





### Introspection

Target: `Ash.Reactor.Dsl.NotificationMetadata`

### reactor.create.tenant
```elixir
tenant source
Expand Down Expand Up @@ -1934,6 +2028,7 @@ Declares a step that will call a destroy action on a resource.
* [where](#reactor-destroy-where)
* [inputs](#reactor-destroy-inputs)
* [load](#reactor-destroy-load)
* [notification_metadata](#reactor-destroy-notification_metadata)
* [tenant](#reactor-destroy-tenant)
* [wait_for](#reactor-destroy-wait_for)

Expand Down Expand Up @@ -2206,6 +2301,37 @@ Allows the addition of an Ash load statement to the action

Target: `Ash.Reactor.Dsl.ActionLoad`

### reactor.destroy.notification_metadata
```elixir
notification_metadata source
```


Specifies metadata to be merged into the metadata field for all notifications sent from this operation





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source`](#reactor-destroy-notification_metadata-source){: #reactor-destroy-notification_metadata-source .spark-required} | `Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value \| map \| nil` | | What to use as the source of the notification metadata. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`transform`](#reactor-destroy-notification_metadata-transform){: #reactor-destroy-notification_metadata-transform } | `(any -> any) \| module \| nil` | | An optional transformation function which can be used to modify the notification metadata before it is passed to the action. |





### Introspection

Target: `Ash.Reactor.Dsl.NotificationMetadata`

### reactor.destroy.tenant
```elixir
tenant source
Expand Down Expand Up @@ -3487,6 +3613,7 @@ Declares a step that will call an update action on a resource.
* [where](#reactor-update-where)
* [inputs](#reactor-update-inputs)
* [load](#reactor-update-load)
* [notification_metadata](#reactor-update-notification_metadata)
* [tenant](#reactor-update-tenant)
* [wait_for](#reactor-update-wait_for)

Expand Down Expand Up @@ -3761,6 +3888,37 @@ Allows the addition of an Ash load statement to the action

Target: `Ash.Reactor.Dsl.ActionLoad`

### reactor.update.notification_metadata
```elixir
notification_metadata source
```


Specifies metadata to be merged into the metadata field for all notifications sent from this operation





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source`](#reactor-update-notification_metadata-source){: #reactor-update-notification_metadata-source .spark-required} | `Reactor.Template.Element \| Reactor.Template.Input \| Reactor.Template.Result \| Reactor.Template.Value \| map \| nil` | | What to use as the source of the notification metadata. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`transform`](#reactor-update-notification_metadata-transform){: #reactor-update-notification_metadata-transform } | `(any -> any) \| module \| nil` | | An optional transformation function which can be used to modify the notification metadata before it is passed to the action. |





### Introspection

Target: `Ash.Reactor.Dsl.NotificationMetadata`

### reactor.update.tenant
```elixir
tenant source
Expand Down
10 changes: 1 addition & 9 deletions lib/ash/actions/create/bulk.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1538,15 +1538,7 @@ defmodule Ash.Actions.Create.Bulk do
end

defp notification(changeset, result, opts) do
%Ash.Notifier.Notification{
resource: changeset.resource,
domain: changeset.domain,
actor: opts[:actor],
action: changeset.action,
for: Ash.Resource.Info.notifiers(changeset.resource) ++ changeset.action.notifiers,
data: result,
changeset: changeset
}
Ash.Actions.Helpers.resource_notification(changeset, result, opts)
end

defp templated_opts({:templated, opts}, _actor, _tenant, _arguments, _context, _changeset),
Expand Down
1 change: 1 addition & 0 deletions lib/ash/actions/create/create.ex
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ defmodule Ash.Actions.Create do
transaction?: Keyword.get(opts, :transaction?, true) && changeset.action.transaction?,
rollback_on_error?: opts[:rollback_on_error?],
tracer: opts[:tracer],
notification_metadata: opts[:notification_metadata],
return_notifications?: opts[:return_notifications?],
transaction_metadata: %{
type: :create,
Expand Down
10 changes: 1 addition & 9 deletions lib/ash/actions/destroy/bulk.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2282,14 +2282,6 @@ defmodule Ash.Actions.Destroy.Bulk do
end

defp notification(changeset, result, opts) do
%Ash.Notifier.Notification{
resource: changeset.resource,
domain: changeset.domain,
actor: opts[:actor],
action: changeset.action,
for: Ash.Resource.Info.notifiers(changeset.resource) ++ changeset.action.notifiers,
data: result,
changeset: changeset
}
Ash.Actions.Helpers.resource_notification(changeset, result, opts)
end
end
3 changes: 2 additions & 1 deletion lib/ash/actions/helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,8 @@ defmodule Ash.Actions.Helpers do

def notify(other, _changeset, _opts), do: other

defp resource_notification(changeset, result, opts) do
@doc false
def resource_notification(changeset, result, opts) do
# This gives notifications a view of what actually changed
changeset =
Enum.reduce(changeset.atomics, changeset, fn {key, value}, changeset ->
Expand Down
17 changes: 7 additions & 10 deletions lib/ash/actions/update/bulk.ex
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,11 @@ defmodule Ash.Actions.Update.Bulk do
stream,
action,
input,
Keyword.merge(opts, notify?: opts[:notify?], return_notifications?: opts[:notify?]),
Keyword.merge(opts,
notify?: opts[:notify?],
notification_metadata: opts[:notification_metadata],
return_notifications?: opts[:notify?]
),
metadata_key,
ref_metadata_key,
context_key,
Expand Down Expand Up @@ -1331,6 +1335,7 @@ defmodule Ash.Actions.Update.Bulk do
filter: opts[:filter],
return_notifications?: opts[:return_notifications?],
notify?: opts[:notify?],
notification_metadata: opts[:notification_metadata],
return_records?: opts[:return_records?],
allow_stream_with: opts[:allow_stream_with],
read_action: read_action,
Expand Down Expand Up @@ -3100,15 +3105,7 @@ defmodule Ash.Actions.Update.Bulk do
end

defp notification(changeset, result, opts) do
%Ash.Notifier.Notification{
resource: changeset.resource,
domain: changeset.domain,
actor: opts[:actor],
for: Ash.Resource.Info.notifiers(changeset.resource) ++ changeset.action.notifiers,
action: changeset.action,
data: result,
changeset: changeset
}
Ash.Actions.Helpers.resource_notification(changeset, result, opts)
end

def run_action_changes(
Expand Down
13 changes: 2 additions & 11 deletions lib/ash/reactor/builders/bulk_create.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,18 @@ defimpl Reactor.Dsl.Build, for: Ash.Reactor.Dsl.BulkCreate do
alias Reactor.{Argument, Builder}
alias Spark.{Dsl.Transformer, Error.DslError}
import Ash.Reactor.BuilderUtils
import Reactor.Template, only: :macros

@doc false
@impl true
def build(bulk_create, reactor) do
initial = %Argument{name: :initial, source: bulk_create.initial}

notification_metadata =
case bulk_create.notification_metadata do
template when is_template(template) ->
%Argument{name: :notification_metadata, source: template}

map when is_map(map) ->
Argument.from_value(:notification_metadata, map)
end

arguments =
[initial, notification_metadata]
[initial]
|> maybe_append(bulk_create.actor)
|> maybe_append(bulk_create.tenant)
|> maybe_append(bulk_create.load)
|> maybe_append(bulk_create.notification_metadata)
|> maybe_append(bulk_create.context)
|> Enum.concat(bulk_create.wait_for)

Expand Down
Loading