|
| 1 | + |
| 2 | + |
| 3 | +<h1>The ecron application</h1> |
| 4 | + |
| 5 | +The ecron application |
| 6 | +===================== |
| 7 | +The Ecron application. |
| 8 | + |
| 9 | +__Authors: __ Francesca Gangemi ( [`[email protected]`](mailto:[email protected])), Ulf Wiger ( [`[email protected]`](mailto:[email protected])). |
| 10 | + |
| 11 | +The Ecron application |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +The Ecron application executes scheduled functions. |
| 16 | +A list of functions to execute might be specified in the ecron application |
| 17 | +resource file as value of the `scheduled` environment variable. |
| 18 | + |
| 19 | +Each entry specifies a job and must contain the scheduled time and a MFA |
| 20 | +tuple `{Module, Function, Arguments}`. |
| 21 | +It's also possible to configure options for a retry algorithm to run in case |
| 22 | +MFA fails. |
| 23 | +<pre> |
| 24 | +Job = {{Date, Time}, MFA, Retry, Seconds} | |
| 25 | + {{Date, Time}, MFA} |
| 26 | +</pre> |
| 27 | + |
| 28 | + |
| 29 | +`Seconds = integer()` is the retry interval. |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +`Retry = integer() | infinity` is the number of times to retry. |
| 34 | + |
| 35 | + |
| 36 | +Example of ecron.app |
| 37 | +<pre> |
| 38 | +... |
| 39 | +{env,[{scheduled, |
| 40 | + [{{{ '*', '*', '*'}, {0 ,0,0}}, {my_mod, my_fun1, Args}}, |
| 41 | + {{{ '*', 12 , 25}, {0 ,0,0}}, {my_mod, my_fun2, Args}}, |
| 42 | + {{{ '*', 1 , 1 }, {0 ,0,0}}, {my_mod, my_fun3, Args}, infinity, 60}, |
| 43 | + {{{2010, 1 , 1 }, {12,0,0}}, {my_mod, my_fun3, Args}}, |
| 44 | + {{{ '*', 12 ,last}, {0 ,0,0}}, {my_mod, my_fun4, Args}]}]}, |
| 45 | +... |
| 46 | +</pre> |
| 47 | + |
| 48 | + |
| 49 | +Once the ecron application is started, it's possible to dynamically add new |
| 50 | +jobs using the `ecron:insert/2` or `ecron:insert/4` |
| 51 | +API. |
| 52 | + |
| 53 | + |
| 54 | + |
| 55 | +The MFA is executed when a task is set to run. |
| 56 | +The MFA has to return `ok`, `{ok, Data}`, `{apply, fun()}` |
| 57 | +or `{error, Reason}`. |
| 58 | +If `{error, Reason}` is returned and the job was defined with retry options |
| 59 | +(Retry and Seconds were specified together with the MFA) then ecron will try |
| 60 | +to execute MFA later according to the given configuration. |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +The MFA may return `{apply, fun()}` where `fun()` has arity zero. |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | +`fun` will be immediately executed after MFA execution. |
| 69 | +The `fun` has to return `ok`, `{ok, Data}` or `{error, Reason}`. |
| 70 | + |
| 71 | + |
| 72 | + |
| 73 | +If the MFA or `fun` terminates abnormally or returns an invalid |
| 74 | +data type (not `ok`, `{ok, Data}` or `{error, Reason}`), an event |
| 75 | +is forwarded to the event manager and no retries are executed. |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +If the return value of the fun is `{error, Reason}` and retry |
| 80 | +options were given in the job specification then the `fun` is |
| 81 | +rescheduled to be executed after the configurable amount of time. |
| 82 | + |
| 83 | + |
| 84 | + |
| 85 | +Data which does not change between retries of the `fun` |
| 86 | +must be calculated outside the scope of the `fun`. |
| 87 | +Data which changes between retries has to be calculated within the scope |
| 88 | +of the `fun`. |
| 89 | +<br></br> |
| 90 | + |
| 91 | +In the following example, ScheduleTime will change each time the function is |
| 92 | +scheduled, while ExecutionTime will change for every retry. If static data |
| 93 | +has to persist across calls or retries, this is done through a function in |
| 94 | +the MFA or the fun. |
| 95 | + |
| 96 | +<pre> |
| 97 | +print() -> |
| 98 | + ScheduledTime = time(), |
| 99 | + {apply, fun() -> |
| 100 | + ExecutionTime = time(), |
| 101 | + io:format("Scheduled:~p~n",[ScheduledTime]), |
| 102 | + io:format("Execution:~p~n",[ExecutionTime]), |
| 103 | + {error, retry} |
| 104 | + end}. |
| 105 | +</pre> |
| 106 | + |
| 107 | + |
| 108 | +Event handlers may be configured in the application resource file specifying |
| 109 | +for each of them, a tuple as the following: |
| 110 | + |
| 111 | +<pre>{Handler, Args} |
| 112 | + |
| 113 | +Handler = Module | {Module,Id} |
| 114 | +Module = atom() |
| 115 | +Id = term() |
| 116 | +Args = term() |
| 117 | +</pre> |
| 118 | +`Module:init/1` will be called to initiate the event handler and |
| 119 | +its internal state |
| 120 | +<br></br> |
| 121 | + |
| 122 | +<br></br> |
| 123 | + |
| 124 | +Example of ecron.app |
| 125 | +<pre> |
| 126 | +... |
| 127 | +{env, [{event_handlers, [{ecron_event, []}]}]}, |
| 128 | +... |
| 129 | +</pre> |
| 130 | + |
| 131 | + |
| 132 | +The API `add_event_handler/2` and |
| 133 | +`delete_event_handler/1` |
| 134 | +allow user to dynamically add and remove event handlers. |
| 135 | + |
| 136 | + |
| 137 | + |
| 138 | +All the configured event handlers will receive the following events: |
| 139 | + |
| 140 | + |
| 141 | + |
| 142 | +`{mfa_result, Result, {Schedule, {M, F, A}}, DueDateTime, ExecutionDateTime}` |
| 143 | +when MFA is executed. |
| 144 | + |
| 145 | + |
| 146 | + |
| 147 | +`{fun_result, Result, {Schedule, {M, F, A}}, DueDateTime, ExecutionDateTime}` |
| 148 | +when `fun` is executed. |
| 149 | + |
| 150 | + |
| 151 | + |
| 152 | +`{retry, {Schedule, MFA}, Fun, DueDateTime}` |
| 153 | +when MFA, or `fun`, is rescheduled to be executed later after a failure. |
| 154 | + |
| 155 | + |
| 156 | + |
| 157 | +`{max_retry, {Schedule, MFA}, Fun, DueDateTime}` when MFA, |
| 158 | +or `fun` has reached maximum number of retry specified when |
| 159 | +the job was inserted. |
| 160 | + |
| 161 | + |
| 162 | + |
| 163 | +`Result` is the return value of MFA or `fun`. |
| 164 | + If an exception occurs during evaluation of MFA, or `fun`, then |
| 165 | +it's caught and sent in the event. |
| 166 | +(E.g. `Result = {'EXIT',{Reason,Stack}}`). |
| 167 | + |
| 168 | + |
| 169 | + |
| 170 | +`Schedule = {Date, Time}` as given when the job was inserted, E.g. |
| 171 | +`{{'*','*','*'}, {0,0,0}}` |
| 172 | +<br></br> |
| 173 | + |
| 174 | +`DueDateTime = {Date, Time}` is the exact Date and Time when the MFA, |
| 175 | +or the `fun`, was supposed to run. |
| 176 | + E.g. `{{2010,1,1}, {0,0,0}}` |
| 177 | +<br></br> |
| 178 | + |
| 179 | +`ExecutionDateTime = {Date, Time}` is the exact Date and Time |
| 180 | +when the MFA, or the `fun`, was executed. |
| 181 | +<br></br> |
| 182 | + |
| 183 | +<br></br> |
| 184 | + |
| 185 | +<br></br> |
| 186 | + |
| 187 | +If a node is restarted while there are jobs in the list then these jobs are |
| 188 | +not lost. When Ecron starts it takes a list of scheduled MFA from the |
| 189 | +environment variable `scheduled` and inserts them into a persistent table |
| 190 | +(mnesia). If an entry of the scheduled MFA specifies the same parameters |
| 191 | +values of a job already present in the table then the entry won't be inserted |
| 192 | +avoiding duplicated jobs. |
| 193 | +<br></br> |
| 194 | + |
| 195 | +No duplicated are removed from the MFA list configured in the `scheduled` variable. |
| 196 | + |
| 197 | +<pre> |
| 198 | +Copyright (c) 2009-2011 Erlang Solutions Ltd |
| 199 | +All rights reserved. |
| 200 | + |
| 201 | +Redistribution and use in source and binary forms, with or without |
| 202 | +modification, are permitted provided that the following conditions are met: |
| 203 | +* Redistributions of source code must retain the above copyright |
| 204 | + notice, this list of conditions and the following disclaimer. |
| 205 | +* Redistributions in binary form must reproduce the above copyright |
| 206 | + notice, this list of conditions and the following disclaimer in the |
| 207 | + documentation and/or other materials provided with the distribution. |
| 208 | +* Neither the name of the Erlang Solutions nor the names of its |
| 209 | + contributors may be used to endorse or promote products |
| 210 | + derived from this software without specific prior written permission. |
| 211 | + |
| 212 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 213 | +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 214 | +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 215 | +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS |
| 216 | +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 217 | +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 218 | +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| 219 | +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 220 | +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 221 | +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 222 | +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 223 | +</pre> |
| 224 | + |
| 225 | + |
| 226 | +<h2 class="indextitle">Modules</h2> |
| 227 | + |
| 228 | + |
| 229 | + |
| 230 | +<table width="100%" border="0" summary="list of modules"> |
| 231 | +<tr><td><a href="ecron.md" class="module">ecron</a></td></tr> |
| 232 | +<tr><td><a href="ecron_app.md" class="module">ecron_app</a></td></tr> |
| 233 | +<tr><td><a href="ecron_event.md" class="module">ecron_event</a></td></tr> |
| 234 | +<tr><td><a href="ecron_event_handler_controller.md" class="module">ecron_event_handler_controller</a></td></tr> |
| 235 | +<tr><td><a href="ecron_event_sup.md" class="module">ecron_event_sup</a></td></tr> |
| 236 | +<tr><td><a href="ecron_sup.md" class="module">ecron_sup</a></td></tr> |
| 237 | +<tr><td><a href="ecron_time.md" class="module">ecron_time</a></td></tr></table> |
| 238 | + |
0 commit comments