@@ -19,17 +19,54 @@ defmodule Quantum do
1919
2020 ## Configuration:
2121
22- * `:timeout` - Sometimes, you may come across GenServer
23- timeout errors esp. when you have too many jobs or high
24- load. The default GenServer.call timeout is 5000.
22+ * `:clock_broadcaster_name` - GenServer name of clock broadcaster \\
23+ *(unstable, may break without major release until declared stable)*
24+
25+ * `:execution_broadcaster_name` - GenServer name of execution broadcaster \\
26+ *(unstable, may break without major release until declared stable)*
27+
28+ * `:executor_supervisor_name` - GenServer name of execution supervisor \\
29+ *(unstable, may break without major release until declared stable)*
30+
31+ * `:debug_logging` - Turn on debug logging
2532
2633 * `:jobs` - list of cron jobs to execute
2734
28- * `:schedule` - Default schedule of new Job
35+ * `:job_broadcaster_name` - GenServer name of job broadcaster \\
36+ *(unstable, may break without major release until declared stable)*
37+
38+ * `:name` - GenServer name of scheduler \\
39+ *(unstable, may break without major release until declared stable)*
40+
41+ * `:node_selector_broadcaster_name` - GenServer name of node selector broadcaster \\
42+ *(unstable, may break without major release until declared stable)*
43+
44+ * `:overlap` - Default overlap of new Job
45+
46+ * `:otp_app` - Application where scheduler runs
2947
3048 * `:run_strategy` - Default Run Strategy of new Job
3149
32- * `:overlap` - Default overlap of new Job,
50+ * `:schedule` - Default schedule of new Job
51+
52+ * `:storage` - Storage to use for persistence
53+
54+ * `:storage_name` - GenServer name of storage \\
55+ *(unstable, may break without major release until declared stable)*
56+
57+ * `:supervisor_module` - Module to supervise scheduler \\
58+ Can be overwritten to supervise processes differently (for example for clustering) \\
59+ *(unstable, may break without major release until declared stable)*
60+
61+ * `:task_registry_name` - GenServer name of task registry \\
62+ *(unstable, may break without major release until declared stable)*
63+
64+ * `:task_supervisor_name` - GenServer name of task supervisor \\
65+ *(unstable, may break without major release until declared stable)*
66+
67+ * `:timeout` - Sometimes, you may come across GenServer timeout errors
68+ esp. when you have too many jobs or high load. The default `GenServer.call/3`
69+ timeout is `5_000`.
3370
3471 * `:timezone` - Default timezone of new Job
3572
@@ -45,7 +82,6 @@ defmodule Quantum do
4582 @ type t :: module
4683
4784 @ defaults [
48- cron: [ ] ,
4985 timeout: 5_000 ,
5086 schedule: nil ,
5187 overlap: true ,
@@ -56,8 +92,6 @@ defmodule Quantum do
5692 storage: Noop
5793 ]
5894
59- @ optional_callbacks init: 1
60-
6195 # Returns the configuration stored in the `:otp_app` environment.
6296 @ doc false
6397 @ callback config ( Keyword . t ( ) ) :: Keyword . t ( )
@@ -66,7 +100,7 @@ defmodule Quantum do
66100 Starts supervision and return `{:ok, pid}`
67101 or just `:ok` if nothing needs to be done.
68102
69- Returns `{:error, {:already_started, pid}}` if the repo is already
103+ Returns `{:error, {:already_started, pid}}` if the scheduler is already
70104 started or `{:error, term}` in case anything else goes wrong.
71105
72106 ## Options
@@ -136,16 +170,58 @@ defmodule Quantum do
136170
137171 @ doc false
138172 # Retrieves only scheduler related configuration.
139- def scheduler_config ( scheduler , otp_app , custom ) do
173+ def scheduler_config ( opts , scheduler , otp_app ) do
140174 @ defaults
141175 |> Keyword . merge ( Application . get_env ( otp_app , scheduler , [ ] ) )
142- |> Keyword . merge ( custom )
143- |> Keyword . merge ( otp_app: otp_app , scheduler: scheduler )
176+ |> Keyword . merge ( opts )
177+ |> Keyword . put_new ( :otp_app , otp_app )
178+ |> Keyword . put_new ( :scheduler , scheduler )
179+ |> Keyword . put_new ( :name , scheduler )
144180 |> update_in ( [ :schedule ] , & Normalizer . normalize_schedule / 1 )
181+ |> Keyword . put_new ( :task_supervisor_name , Module . concat ( scheduler , TaskSupervisor ) )
182+ |> Keyword . put_new ( :storage_name , Module . concat ( scheduler , Storage ) )
183+ |> Keyword . put_new ( :task_registry_name , Module . concat ( scheduler , TaskRegistry ) )
184+ |> Keyword . put_new ( :clock_broadcaster_name , Module . concat ( scheduler , ClockBroadcaster ) )
185+ |> Keyword . put_new ( :job_broadcaster_name , Module . concat ( scheduler , JobBroadcaster ) )
186+ |> Keyword . put_new (
187+ :execution_broadcaster_name ,
188+ Module . concat ( scheduler , ExecutionBroadcaster )
189+ )
190+ |> Keyword . put_new (
191+ :node_selector_broadcaster_name ,
192+ Module . concat ( scheduler , NodeSelectorBroadcaster )
193+ )
194+ |> Keyword . put_new ( :executor_supervisor_name , Module . concat ( scheduler , ExecutorSupervisor ) )
195+ |> ( fn config ->
196+ Keyword . update ( config , :jobs , [ ] , fn jobs ->
197+ jobs
198+ |> Enum . map ( & Normalizer . normalize ( scheduler . new_job ( config ) , & 1 ) )
199+ |> remove_jobs_with_duplicate_names ( scheduler )
200+ end )
201+ end ) . ( )
202+ |> Keyword . put_new ( :supervisor_module , Quantum.Supervisor )
203+ |> Keyword . put_new ( :name , Quantum.Supervisor )
204+ end
205+
206+ defp remove_jobs_with_duplicate_names ( job_list , scheduler ) do
207+ job_list
208+ |> Enum . reduce ( % { } , fn % Job { name: name } = job , acc ->
209+ if Enum . member? ( Map . keys ( acc ) , name ) do
210+ Logger . warn (
211+ "Job with name '#{ name } ' of scheduler '#{ scheduler } ' not started due to duplicate job name"
212+ )
213+
214+ acc
215+ else
216+ Map . put_new ( acc , name , job )
217+ end
218+ end )
219+ |> Map . values ( )
145220 end
146221
147222 defmacro __using__ ( opts ) do
148- quote bind_quoted: [ behaviour: __MODULE__ , opts: opts , moduledoc: @ moduledoc ] do
223+ quote bind_quoted: [ behaviour: __MODULE__ , opts: opts , moduledoc: @ moduledoc ] ,
224+ location: :keep do
149225 @ otp_app Keyword . fetch! ( opts , :otp_app )
150226 @ moduledoc moduledoc
151227 |> String . replace ( ~r/ MyApp\. Scheduler/ , Enum . join ( Module . split ( __MODULE__ ) , "." ) )
@@ -155,27 +231,25 @@ defmodule Quantum do
155231
156232 @ doc false
157233 @ impl behaviour
158- def config ( custom \\ [ ] ) do
159- Quantum . scheduler_config ( __MODULE__ , @ otp_app , custom )
234+ def config ( opts \\ [ ] ) do
235+ Quantum . scheduler_config ( opts , __MODULE__ , @ otp_app )
160236 end
161237
162238 defp __job_broadcaster__ do
163- __job_broadcaster__ (
164- config ( ) |> Keyword . fetch! ( :scheduler ) |> Module . concat ( JobBroadcaster ) ,
165- config ( )
166- )
167- end
168-
169- defp __job_broadcaster__ ( job_broadcaster , configuration ) do
170- GenServer . whereis ( job_broadcaster )
239+ config ( ) |> Keyword . fetch! ( :job_broadcaster_name )
171240 end
172241
173242 defp __timeout__ , do: Keyword . fetch! ( config ( ) , :timeout )
174243
175244 @ impl behaviour
176245 def start_link ( opts \\ [ ] ) do
177- opts = Keyword . put_new ( opts , :name , __MODULE__ )
178- Quantum.Supervisor . start_link ( __MODULE__ , @ otp_app , opts )
246+ opts = config ( opts )
247+ Keyword . fetch! ( opts , :supervisor_module ) . start_link ( __MODULE__ , opts )
248+ end
249+
250+ @ impl behaviour
251+ def init ( opts ) do
252+ opts
179253 end
180254
181255 @ impl behaviour
@@ -249,7 +323,7 @@ defmodule Quantum do
249323 % { unquote_splicing ( spec ) }
250324 end
251325
252- defoverridable child_spec: 1
326+ defoverridable child_spec: 1 , config: 0 , config: 1 , init: 1
253327 end
254328 end
255329end
0 commit comments