-
-
Notifications
You must be signed in to change notification settings - Fork 181
/
action.ex
149 lines (142 loc) · 4.17 KB
/
action.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
defmodule Ash.Reactor.Dsl.Action do
@moduledoc """
The `action` entity for the `Ash.Reactor` reactor extension.
"""
defstruct __identifier__: nil,
action_step?: true,
action: nil,
actor: [],
async?: true,
authorize?: nil,
description: nil,
domain: nil,
inputs: [],
name: nil,
resource: nil,
tenant: [],
transform: nil,
type: :action,
undo_action: nil,
undo: :never,
wait_for: []
@type t :: %__MODULE__{
__identifier__: any,
action_step?: true,
action: atom,
actor: [Ash.Reactor.Dsl.Actor.t()],
async?: boolean,
authorize?: boolean | nil,
description: String.t() | nil,
domain: Ash.Domain.t(),
inputs: [Ash.Reactor.Dsl.Inputs.t()],
name: atom,
resource: module,
tenant: [Ash.Reactor.Dsl.Tenant.t()],
type: :action,
undo_action: atom,
undo: :always | :never | :outside_transaction,
wait_for: [Reactor.Dsl.WaitFor.t()]
}
@doc false
def __entity__,
do: %Spark.Dsl.Entity{
name: :action,
describe: """
Declares a step that will call a generic action on a resource.
#{Ash.Reactor.Dsl.Action.__shared_undo_docs__()}
""",
no_depend_modules: [:domain, :resource],
target: __MODULE__,
args: [:name, :resource, {:optional, :action}],
identifier: :name,
imports: [Reactor.Dsl.Argument],
entities: [
actor: [Ash.Reactor.Dsl.Actor.__entity__()],
inputs: [Ash.Reactor.Dsl.Inputs.__entity__()],
tenant: [Ash.Reactor.Dsl.Tenant.__entity__()],
wait_for: [Reactor.Dsl.WaitFor.__entity__()]
],
singleton_entity_keys: [:actor, :tenant],
recursive_as: :steps,
schema: __shared_action_option_schema__()
}
@doc false
def __shared_action_option_schema__(include_undo? \\ true) do
[
action: [
type: :atom,
required: false,
doc: """
The name of the action to call on the resource.
"""
],
domain: [
type: {:spark, Ash.Domain},
required: false,
doc:
"The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section."
],
async?: [
type: :boolean,
required: false,
default: true,
doc:
"When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`."
],
authorize?: [
type: {:or, [:boolean, nil]},
required: false,
default: nil,
doc: "Explicitly enable or disable authorization for the action."
],
description: [
type: :string,
required: false,
doc: "A description for the step"
],
name: [
type: :atom,
required: true,
doc: "A unique name for the step."
],
resource: [
type: {:spark, Ash.Resource},
required: true,
doc: """
The resource to call the action on.
"""
]
]
|> maybe_concat(
[
undo_action: [
type: :atom,
required: false,
doc: """
The name of the action to call on the resource when the step is to be undone.
"""
],
undo: [
type: {:in, [:always, :never, :outside_transaction]},
required: false,
default: :never,
doc: "How to handle undoing this action"
]
],
include_undo?
)
end
def __shared_undo_docs__ do
"""
> #### Undo behaviour {: .tip}
>
> This step has three different modes of undo.
>
> * `never` - The result of the action is never undone. This is the default.
> * `always` - The `undo_action` will always be called.
> * `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise.
"""
end
defp maybe_concat(left, right, true), do: Enum.concat(left, right)
defp maybe_concat(left, _right, _falsy), do: left
end