We will have 'pre' and 'post' functions.
How to deal with stuck / long-running jobs?
How to deal with stuck / long-running jobs?
+ pre() and post()
+ (instead of cleanup)
+
- We should have instance/timeout settings that allows us to deal
with jobs that run too long:
- We should have instance/timeout settings that allows us to deal
with jobs that run too long:
let job, dir, serial, time = IntMap.find pid !runningmap in
runningmap := IntMap.remove pid !runningmap;
serialmap := BigIntMap.remove serial !serialmap;
let job, dir, serial, time = IntMap.find pid !runningmap in
runningmap := IntMap.remove pid !runningmap;
serialmap := BigIntMap.remove serial !serialmap;
- cleanup_job job dir serial time status
+ post_job job dir serial time status
)
with Unix_error _ | Not_found -> ()
)
with Unix_error _ | Not_found -> ()
-and cleanup_job job dir serial time status =
- (* If there is a cleanup function, run it. *)
- (match job.job_cleanup with
+and post_job job dir serial time status =
+ (* If there is a post function, run it. *)
+ (match job.job_post with
let code =
match status with
| WEXITED c -> c
let code =
match status with
| WEXITED c -> c
res_output = dir // "output.txt";
res_start_time = time
} in
res_output = dir // "output.txt";
res_start_time = time
} in
- Syslog.error "job %s cleanup function failed: %s" job.job_name msg
+ Syslog.error "job %s post function failed: %s" job.job_name msg
- Syslog.error "job %s cleanup function exception: %s"
+ Syslog.error "job %s post function exception: %s"
job.job_name (Printexc.to_string exn)
);
job.job_name (Printexc.to_string exn)
);
let lift_expr = M.Expr.meta_expr
(* Handle a top level statement. *)
let lift_expr = M.Expr.meta_expr
(* Handle a top level statement. *)
-let rec call_stmt name cleanup (_loc, stmt, sh) =
+let rec call_stmt name pre post (_loc, stmt, sh) =
let name =
match name with
| None -> let name = unique_job_name () in <:expr< $str:name$ >>
| Some name -> name in
let name =
match name with
| None -> let name = unique_job_name () in <:expr< $str:name$ >>
| Some name -> name in
- let cleanup = expr_of_option _loc cleanup in
+ let pre = expr_of_option _loc pre in
+ let post = expr_of_option _loc post in
- | `When e -> when_stmt _loc name cleanup e sh
- | `Every p -> every_stmt _loc name cleanup p sh
+ | `When e -> when_stmt _loc name pre post e sh
+ | `Every p -> every_stmt _loc name pre post p sh
(* Handle a top level "when" statement.
* e -> when expression
(* Handle a top level "when" statement.
* e -> when expression
* Returns a top level statement (str_item) which when executed just
* adds the statement to a global list.
*)
* Returns a top level statement (str_item) which when executed just
* adds the statement to a global list.
*)
-and when_stmt _loc name cleanup e sh =
+and when_stmt _loc name pre post e sh =
let loc = expr_of_loc _loc _loc in
let e = lift_expr _loc e in
<:str_item<
open Camlp4.PreCast
let loc = expr_of_loc _loc _loc in
let e = lift_expr _loc e in
<:str_item<
open Camlp4.PreCast
- Whenfile.add_when_job $loc$ $name$ $cleanup$ $e$ $sh$
+ Whenfile.add_when_job $loc$ $name$ $pre$ $post$ $e$ $sh$
>>
(* Handle a top level "every" statement. *)
>>
(* Handle a top level "every" statement. *)
-and every_stmt _loc name cleanup period sh =
+and every_stmt _loc name pre post period sh =
let loc = expr_of_loc _loc _loc in
<:str_item<
open Camlp4.PreCast
let loc = expr_of_loc _loc _loc in
<:str_item<
open Camlp4.PreCast
- Whenfile.add_every_job $loc$ $name$ $cleanup$ $period$ $sh$
+ Whenfile.add_every_job $loc$ $name$ $pre$ $post$ $period$ $sh$
| [ e = period_parser -> e ]
];
| [ e = period_parser -> e ]
];
- (* Cleanup function. *)
- cleanup: [
- [ "cleanup"; f = expr -> f ]
- ];
+ (* Pre and post functions. *)
+ pre: [[ "pre"; f = expr -> f ]];
+ post: [[ "post"; f = expr -> f ]];
(* Top level statements. *)
statement: [
(* Top level statements. *)
statement: [
(* "str_item" is a top level statement in an OCaml program. *)
str_item: LEVEL "top" [
(* "str_item" is a top level statement in an OCaml program. *)
str_item: LEVEL "top" [
- [ s = statement -> call_stmt None None s ]
+ [ s = statement -> call_stmt None None None s ]
+ pre = OPT pre;
+ post = OPT post;
- call_stmt (Some name) cleanup s ]
+ call_stmt (Some name) pre post s ]
+type preinfo = {
+ pi_job_name : string;
+ pi_serial : Big_int.big_int;
+}
+
type result = {
res_job_name : string;
res_serial : Big_int.big_int;
type result = {
res_job_name : string;
res_serial : Big_int.big_int;
res_start_time : float;
}
res_start_time : float;
}
-type cleanup = result -> unit
+type pre = preinfo -> bool
+type post = result -> unit
type job = {
job_loc : Loc.t;
job_name : string;
type job = {
job_loc : Loc.t;
job_name : string;
- job_cleanup : cleanup option;
+ job_pre : pre option;
+ job_post : post option;
job_cond : job_cond;
job_script : shell_script;
}
job_cond : job_cond;
job_script : shell_script;
}
+type preinfo = {
+ pi_job_name : string; (** Job name. *)
+ pi_serial : Big_int.big_int; (** Job serial number. *)
+}
+(** Information available to pre function before the job runs. *)
+
type result = {
res_job_name : string; (** Job name. *)
res_serial : Big_int.big_int; (** Job serial number. *)
type result = {
res_job_name : string; (** Job name. *)
res_serial : Big_int.big_int; (** Job serial number. *)
}
(** Result of the run of a job. *)
}
(** Result of the run of a job. *)
-type cleanup = result -> unit
-(** A cleanup function. *)
+type pre = preinfo -> bool
+type post = result -> unit
+(** Pre and post functions. *)
type job = {
job_loc : Camlp4.PreCast.Loc.t;
job_name : string;
type job = {
job_loc : Camlp4.PreCast.Loc.t;
job_name : string;
- job_cleanup : cleanup option;
+ job_pre : pre option;
+ job_post : post option;
job_cond : job_cond;
job_script : shell_script;
}
job_cond : job_cond;
job_script : shell_script;
}
-let add_when_job _loc name cleanup e sh =
+let add_when_job _loc name pre post e sh =
let e = expr_of_ast _loc e in
let e = expr_of_ast _loc e in
- let job = { job_loc = _loc; job_name = name; job_cleanup = cleanup;
+ let job = { job_loc = _loc; job_name = name;
+ job_pre = pre; job_post = post;
job_cond = When_job e; job_script = sh } in
state := Whenstate.add_job !state job
job_cond = When_job e; job_script = sh } in
state := Whenstate.add_job !state job
-let add_every_job _loc name cleanup e sh =
- let job = { job_loc = _loc; job_name = name; job_cleanup = cleanup;
+let add_every_job _loc name pre post e sh =
+ let job = { job_loc = _loc; job_name = name;
+ job_pre = pre; job_post = post;
job_cond = Every_job e; job_script = sh } in
state := Whenstate.add_job !state job
job_cond = Every_job e; job_script = sh } in
state := Whenstate.add_job !state job
val get_state : unit -> Whenstate.t
(** Return the updated state. Call this after parsing the file. *)
val get_state : unit -> Whenstate.t
(** Return the updated state. Call this after parsing the file. *)
-val add_when_job : Camlp4.PreCast.Loc.t -> string -> Whenexpr.cleanup option -> Camlp4.PreCast.Ast.expr -> Whenexpr.shell_script -> unit
+val add_when_job : Camlp4.PreCast.Loc.t -> string -> Whenexpr.pre option -> Whenexpr.post option -> Camlp4.PreCast.Ast.expr -> Whenexpr.shell_script -> unit
(** When a 'when' macro appears as a toplevel statement in an
input file, it causes this function to be called.
(** When a 'when' macro appears as a toplevel statement in an
input file, it causes this function to be called.
[name] is the name of the job.
[name] is the name of the job.
- [cleanup] is the optional cleanup function.
+ [pre] and [post] are the optional pre and post functions.
[expr] is the expression, as an OCaml abstract syntax tree.
[sh] is the shell script fragment (basically location + a big string). *)
[expr] is the expression, as an OCaml abstract syntax tree.
[sh] is the shell script fragment (basically location + a big string). *)
-val add_every_job : Camlp4.PreCast.Loc.t -> string -> Whenexpr.cleanup option -> Whenexpr.periodexpr -> Whenexpr.shell_script -> unit
+val add_every_job : Camlp4.PreCast.Loc.t -> string -> Whenexpr.pre option -> Whenexpr.post option -> Whenexpr.periodexpr -> Whenexpr.shell_script -> unit
(** When an 'every' macro appears as a toplevel statement in an
input file, it causes this function to be called.
(** When an 'every' macro appears as a toplevel statement in an
input file, it causes this function to be called.
[name] is the name of the job.
[name] is the name of the job.
- [cleanup] is the optional cleanup function.
+ [pre] and [post] are the optional pre and post functions.
[periodexpr] is the period, eg. 30 seconds.
[periodexpr] is the period, eg. 30 seconds.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
-(* Test cleanup functions. *)
+(* Test post functions (used to be called "cleanup functions"). *)
-job "with cleanup"
-cleanup (Whentools.mailto "you@example.com")
+job "with post"
+post (Whentools.mailto "you@example.com")
As well as simple "every" and "when" expressions, advanced users may
want to use arbitrary OCaml expressions, functions, etc in the jobs
script. These are useful for factoring common code or strings, for
As well as simple "every" and "when" expressions, advanced users may
want to use arbitrary OCaml expressions, functions, etc in the jobs
script. These are useful for factoring common code or strings, for
-setting the initial values of variables, or for defining cleanup
+setting the initial values of variables, or for defining pre and post
functions.
A simple example of an OCaml expression is:
functions.
A simple example of an OCaml expression is:
Whentools.set_variable "name" "Richard";
Whentools.set_variable_int "counter" 0
Whentools.set_variable "name" "Richard";
Whentools.set_variable_int "counter" 0
-=head3 CLEANUP FUNCTIONS
After a job runs, you can control what happens to its output by
After a job runs, you can control what happens to its output by
-writing a cleanup function. To write a cleanup function you have to
-name the job (ie. have an explicit C<job> statement). Put C<cleanup ...>
+writing a C<post> function. To write a post function you have to
+name the job (ie. have an explicit C<job> statement). Put C<post ...>
after the job name like this:
job "poll source"
after the job name like this:
job "poll source"
- cleanup (Whentools.mailto "you@example.com")
+ post (Whentools.mailto "you@example.com")
every 10 seconds :
<<
# ...
>>
every 10 seconds :
<<
# ...
>>
-A number of cleanup functions are available in the library; see below.
+A number of post functions are available in the library; see below.
-You can also write your own cleanup functions (in OCaml). The
+You can also write your own post functions (in OCaml). The
function is passed one argument which is a C<Whentools.result> struct,
defined below.
function is passed one argument which is a C<Whentools.result> struct,
defined below.
Here are some examples of using the mailto function:
job "ex.1"
Here are some examples of using the mailto function:
job "ex.1"
- cleanup (Whentools.mailto "you@example.com")
+ post (Whentools.mailto "you@example.com")
every 10 seconds :
<<
# do something
>>
job "ex.2"
every 10 seconds :
<<
# do something
>>
job "ex.2"
- cleanup (Whentools.mailto ~only_on_failure:true
- "you@example.com")
+ post (Whentools.mailto ~only_on_failure:true
+ "you@example.com")
every 10 seconds :
<<
# do something
every 10 seconds :
<<
# do something
let to_addr = "you@example.com"
job "ex.3"
let to_addr = "you@example.com"
job "ex.3"
- cleanup (Whentools.mailto ~from to_addr)
+ post (Whentools.mailto ~from to_addr)
every 10 seconds :
<<
# do something
every 10 seconds :
<<
# do something
=item B<Whentools.result>
=item B<Whentools.result>
-This structure is passed to cleanup functions. It has the following
+This structure is passed to post functions. It has the following