2020-12-02 13:33:15 +00:00
|
|
|
let src = Logs.Src.create "builder-web.model" ~doc:"Builder_web model"
|
|
|
|
module Log = (val Logs.src_log src : Logs.LOG)
|
|
|
|
|
|
|
|
open Rresult.R.Infix
|
|
|
|
|
2020-12-07 14:43:54 +00:00
|
|
|
module RunMap = Map.Make(struct
|
|
|
|
type t = Fpath.t * Fpath.t
|
|
|
|
let compare (j1,r1) (j2,r2) =
|
|
|
|
let jcmp = Fpath.compare j1 j2 in
|
|
|
|
if jcmp <> 0
|
|
|
|
then jcmp
|
|
|
|
else Fpath.compare r1 r2
|
|
|
|
end)
|
|
|
|
|
|
|
|
type job_run_meta = {
|
|
|
|
job_info : Builder.job;
|
|
|
|
uuid : Uuidm.t;
|
|
|
|
start : Ptime.t;
|
|
|
|
finish : Ptime.t;
|
|
|
|
result : Builder.execution_result;
|
|
|
|
}
|
|
|
|
|
|
|
|
type job_run_info = {
|
|
|
|
meta : job_run_meta;
|
|
|
|
out : (int * string) list;
|
|
|
|
data : (Fpath.t * string) list
|
|
|
|
}
|
|
|
|
|
2020-12-02 13:33:15 +00:00
|
|
|
type t = {
|
|
|
|
dir : Fpath.t;
|
2020-12-07 14:43:54 +00:00
|
|
|
mutable cache : job_run_meta RunMap.t
|
2020-12-02 13:33:15 +00:00
|
|
|
}
|
|
|
|
|
2020-12-07 14:43:54 +00:00
|
|
|
let init dir = { dir; cache = RunMap.empty; }
|
|
|
|
|
2020-12-02 13:33:15 +00:00
|
|
|
type job = {
|
2020-12-07 09:17:49 +00:00
|
|
|
path : Fpath.t;
|
2020-12-07 14:43:54 +00:00
|
|
|
runs : job_run_meta list;
|
2020-12-02 13:33:15 +00:00
|
|
|
}
|
|
|
|
|
2020-12-07 09:17:49 +00:00
|
|
|
let job_name { path; _ } = Fpath.to_string path
|
2020-12-02 13:33:15 +00:00
|
|
|
|
2020-12-07 09:17:49 +00:00
|
|
|
let read_full t path run =
|
|
|
|
let f = Fpath.(t.dir // path // run / "full") in
|
2020-12-02 13:33:15 +00:00
|
|
|
Bos.OS.File.read f >>= fun s ->
|
|
|
|
Builder.Asn.exec_of_cs (Cstruct.of_string s)
|
|
|
|
>>| fun (job_info, uuid, out, start, finish, result, data) ->
|
2020-12-07 20:20:24 +00:00
|
|
|
let meta = { job_info; uuid; start; finish; result } in
|
|
|
|
t.cache <- RunMap.add (path, run) meta t.cache;
|
|
|
|
{ meta; out; data }
|
2020-12-07 14:43:54 +00:00
|
|
|
|
|
|
|
let read_full_meta t path run =
|
|
|
|
match RunMap.find_opt (path, run) t.cache with
|
2020-12-07 20:20:24 +00:00
|
|
|
| Some meta ->
|
|
|
|
Bos.OS.File.exists Fpath.(t.dir // path // run / "full") >>= fun exists ->
|
|
|
|
if exists
|
|
|
|
then Ok meta
|
|
|
|
else
|
|
|
|
(t.cache <- RunMap.remove (path, run) t.cache;
|
|
|
|
Error (`Msg "no such file"))
|
2020-12-07 14:43:54 +00:00
|
|
|
| None ->
|
|
|
|
read_full t path run >>| fun { meta; out = _; data = _ } ->
|
|
|
|
meta
|
2020-12-02 13:33:15 +00:00
|
|
|
|
2020-12-07 09:17:49 +00:00
|
|
|
let job t job =
|
2020-12-07 14:43:54 +00:00
|
|
|
let path = Fpath.(t.dir // job) in
|
|
|
|
Bos.OS.Dir.contents ~rel:true path >>= fun runs ->
|
|
|
|
let runs =
|
|
|
|
List.filter_map (fun run ->
|
|
|
|
match read_full_meta t job run with
|
|
|
|
| Error (`Msg e) ->
|
|
|
|
Log.warn (fun m -> m "error reading job run file %a: %s"
|
|
|
|
Fpath.pp Fpath.(path // run) e);
|
|
|
|
None
|
|
|
|
| Ok meta -> Some meta)
|
|
|
|
runs
|
|
|
|
in
|
|
|
|
Ok { path = job; runs }
|
2020-12-02 13:33:15 +00:00
|
|
|
|
|
|
|
let jobs t =
|
|
|
|
Bos.OS.Dir.contents ~rel:true t.dir >>|
|
|
|
|
List.filter (fun f -> not (Fpath.equal (Fpath.v "state") f)) >>|
|
2020-12-07 09:17:49 +00:00
|
|
|
List.filter_map (fun f ->
|
2020-12-07 20:21:01 +00:00
|
|
|
match Bos.OS.Dir.exists Fpath.(t.dir // f) with
|
|
|
|
| Ok true -> Some f
|
|
|
|
| Ok false ->
|
|
|
|
Log.warn (fun m -> m "dir %a doesn't exist" Fpath.pp
|
|
|
|
Fpath.(t.dir // f));
|
|
|
|
None
|
2020-12-02 13:33:15 +00:00
|
|
|
| Error (`Msg e) ->
|
2020-12-07 20:21:01 +00:00
|
|
|
Log.warn (fun m -> m "error reading job dir %a: %s" Fpath.pp
|
2020-12-07 09:17:49 +00:00
|
|
|
Fpath.(t.dir // f) e);
|
2020-12-02 13:33:15 +00:00
|
|
|
None)
|