Skip to content

Commit 013a07d

Browse files
author
Ulf Wiger
committed
reformatted + added edown & overview.edoc
1 parent 0ce3cdd commit 013a07d

File tree

5 files changed

+268
-50
lines changed

5 files changed

+268
-50
lines changed

LICENSE

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
Copyright (c) 2009-2010 Erlang Solutions
1+
Copyright (c) 2009-2011 Erlang Solutions Ltd
22
All rights reserved.
33

44
Redistribution and use in source and binary forms, with or without
55
modification, are permitted provided that the following conditions are met:
66
* Redistributions of source code must retain the above copyright
7-
notice, this list of conditions and the following disclaimer.
7+
notice, this list of conditions and the following disclaimer.
88
* Redistributions in binary form must reproduce the above copyright
99
notice, this list of conditions and the following disclaimer in the
1010
documentation and/or other materials provided with the distribution.

doc/overview.edoc

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

rebar.config

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
%% -*- erlang -*-
22
{erl_opts, [debug_info]}.
33
{deps, [
4-
{meck, ".*", {git, "git://github.com/esl/meck.git", "HEAD"}}
4+
{meck, ".*", {git, "git://github.com/esl/meck.git", "HEAD"}},
5+
{edown, ".*",
6+
{git, "git://github.com/esl/edown.git", "HEAD"}}
57
]}.
68
{dialyzer_opts, [{warnings, [no_unused,
79
no_improper_lists, no_fun_app, no_match,
810
no_opaque, no_fail_call,
911
error_handling, no_match,
1012
unmatched_returns,
1113
behaviours, underspecs]}]}.
14+
{edoc_opts, [{doclet, edown_doclet},
15+
{top_level_readme,
16+
{"./README.md",
17+
"http://github.com/esl/ecron"}}]}.

src/ecron.app.src

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
%% -*- mode: erlang; -*-
2+
{application, ecron,
3+
[
4+
{description, ""},
5+
{vsn, git},
6+
{registered, []},
7+
{mod, {ecron_app, []}},
8+
{applications, [kernel, stdlib, mnesia]},
9+
{build_dependencies, []},
10+
{env, [{event_handlers,[{ecron_event, []}]}]}
11+
]}.

0 commit comments

Comments
 (0)