Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passive watch mode for tests #4678

Merged
merged 31 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9706fd9
[RPC] fix result of dune rpc status
rgrinberg Jun 2, 2021
4629232
[RPC] use correct socket type
rgrinberg Jun 2, 2021
77f1f50
[RPC] destroy thread after connecting
rgrinberg Jun 2, 2021
588ac52
separate poll iteration into a separate function, introduce a standin…
aalekseyev Jun 1, 2021
5f039a2
add server-side support for passive watch mode
aalekseyev Jun 1, 2021
d88b6c4
add initial version of [dune rpc build]
aalekseyev Jun 1, 2021
d939b8c
flush
aalekseyev Jun 1, 2021
5eea6ec
fix a test, fix inotify sync
aalekseyev Jun 2, 2021
1259e61
build_outcome
aalekseyev Jun 2, 2021
fa24455
add a test
aalekseyev Jun 2, 2021
0627881
fix the test
aalekseyev Jun 2, 2021
0078118
tidier inotify sync
aalekseyev Jun 4, 2021
4a22394
merge
aalekseyev Jun 4, 2021
eef8236
make fmt
aalekseyev Jun 4, 2021
61dc663
Merge branch 'main' into dune-build-rpc-for-tests
aalekseyev Jun 7, 2021
3f3c441
disable test on macos
aalekseyev Jun 7, 2021
f02858a
Merge branch 'dune-build-rpc-for-tests' of github.com:aalekseyev/dune…
aalekseyev Jun 7, 2021
cce431a
Doc + API unification
jeremiedimino Jun 7, 2021
80f799c
tweak test
aalekseyev Jun 7, 2021
2eec898
Merge branch 'dune-build-rpc-for-tests' of github.com:aalekseyev/dune…
aalekseyev Jun 7, 2021
6eb1548
add comment about the '@' exclusion limitation, fix the exclude patte…
aalekseyev Jun 7, 2021
8a3bf97
Unify [poll] and [poll_passive] into poll_gen
aalekseyev Jun 8, 2021
a4af217
add to comment
aalekseyev Jun 8, 2021
8823055
make --wait work for [dune rpc build]
aalekseyev Jun 8, 2021
84bc17e
make fmt
aalekseyev Jun 8, 2021
8f78ce0
make -wpfoo mean 'watching build package foo' for backwards-compatibi…
aalekseyev Jun 8, 2021
d29b2e1
simplify build_cmd.ml
aalekseyev Jun 8, 2021
00d552b
add docs to poll_passive, make fmt
aalekseyev Jun 8, 2021
9486337
merge with main
aalekseyev Jun 10, 2021
5f7424a
get rid of is_polling
aalekseyev Jun 10, 2021
43e5c2e
share the [step] type definition
aalekseyev Jun 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 57 additions & 19 deletions bin/build_cmd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,79 @@ let run_build_system ?report_error ~common ~(request : unit Action_builder.t) ()
]));
Fiber.return ())

let run_build_command_poll ~(common : Common.t) ~config ~request ~setup =
let run_build_command_poll_eager ~(common : Common.t) ~config ~request ~setup :
unit =
let open Fiber.O in
let every ~report_error () =
Cached_digest.invalidate_cached_timestamps ();
let* setup = setup () in
let* request =
match
let open Option.O in
let* rpc = Common.rpc common in
Dune_rpc_impl.Server.pending_build_action rpc
with
| None -> Fiber.return (request setup)
| Some (Build (targets, ivar)) ->
let+ () = Fiber.Ivar.fill ivar Accepted in
Target.interpret_targets (Common.root common) config setup targets
in
let request = request setup in
let+ () = run_build_system ~report_error ~common ~request () in
`Continue
in
Scheduler.poll ~common ~config ~every ~finally:Hooks.End_of_build.run
Import.Scheduler.go_with_rpc_server_and_console_status_reporting ~common
~config (fun () ->
Scheduler.Run.poll (fun ~report_error ->
Fiber.finalize (every ~report_error) ~finally:(fun () ->
Fiber.return (Hooks.End_of_build.run ()))))

let run_build_command_poll_passive ~(common : Common.t) ~config ~request ~setup
: unit =
let _ =
(* CR-someday aalekseyev: It would've been better to complain if request are
non-empty, but we can't check that here because [request] is a function.*)
ignore request
in
let open Fiber.O in
let run_build ~report_error request =
Fiber.of_thunk (fun () ->
Cached_digest.invalidate_cached_timestamps ();
let* setup = setup () in
let request = request setup in
let+ () = run_build_system ~report_error ~common ~request () in
`Continue)
in
match Common.rpc common with
| None ->
Code_error.raise
"Attempted to start a passive polling mode without an RPC server" []
| Some rpc ->
Import.Scheduler.go_with_rpc_server_and_console_status_reporting ~common
~config (fun () ->
Scheduler.Run.poll_passive
~get_build_request:
(let+ (Build (targets, ivar)) =
Dune_rpc_impl.Server.pending_build_action rpc
in
let targets setup =
Target.interpret_targets (Common.root common) config setup
targets
in
( (fun ~report_error ->
Fiber.of_thunk (fun () ->
Fiber.finalize
~finally:(fun () ->
Hooks.End_of_build.run ();
Fiber.return ())
(fun () -> run_build ~report_error targets)))
, ivar )))

let run_build_command_once ~(common : Common.t) ~config ~request ~setup =
let run_build_command_once ~(common : Common.t) ~config ~request
~(setup : unit -> Import.Main.build_system Fiber.t) =
let open Fiber.O in
let once () =
let* setup = setup () in
run_build_system ~common ~request:(request setup) ()
let request = request setup in
run_build_system ~common ~request ()
in
Scheduler.go ~common ~config once

let run_build_command ~(common : Common.t) ~config ~request =
let setup () = Import.Main.setup () in
(if Common.watch common then
run_build_command_poll
else
run_build_command_once)
(match Common.watch common with
| Yes Eager -> run_build_command_poll_eager
| Yes Passive -> run_build_command_poll_passive
| No -> run_build_command_once)
~setup ~common ~config ~request

let runtest =
Expand Down
43 changes: 32 additions & 11 deletions bin/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type t =
orig_args : string list
; rpc : Dune_rpc_impl.Server.t option
; default_target : Arg.Dep.t (* For build & runtest only *)
; watch : bool
; watch : Dune_engine.Watch_mode_config.t
; print_metrics : bool
; stats_trace_file : string option
; always_show_command_line : bool
Expand Down Expand Up @@ -799,12 +799,34 @@ let term =
"Force actions associated to aliases to be re-executed even\n\
\ if their dependencies haven't changed.")
and+ watch =
Arg.(
value & flag
& info [ "watch"; "w" ]
~doc:
"Instead of terminating build after completion, wait continuously \
for file changes.")
Term.ret
(let watch_arg_name = "watch" in
let passive_watch_mode_arg_name = "passive-watch-mode" in
let+ w_flag =
Arg.(
value & flag
& info [ watch_arg_name; "w" ]
~doc:
"Instead of terminating build after completion, wait \
continuously for file changes.")
and+ passive_watch_mode_flag =
Arg.(
value & flag
& info
[ passive_watch_mode_arg_name ]
~doc:
"Do not automatically start or re-start a build. Only do it \
when a build RPC is received.")
in
match (w_flag, passive_watch_mode_flag) with
| false, false -> `Ok Dune_engine.Watch_mode_config.No
| false, true ->
`Error
( true
, sprintf "Cannot use %s if %s was not passed"
passive_watch_mode_arg_name watch_arg_name )
| true, false -> `Ok (Dune_engine.Watch_mode_config.Yes Eager)
| true, true -> `Ok (Dune_engine.Watch_mode_config.Yes Passive))
aalekseyev marked this conversation as resolved.
Show resolved Hide resolved
and+ print_metrics =
Arg.(
value & flag
Expand Down Expand Up @@ -928,10 +950,9 @@ let term =
let build_dir = Option.value ~default:default_build_dir build_dir in
let root = Workspace_root.create ~specified_by_user:root in
let rpc =
if watch then
Some (Dune_rpc_impl.Server.create ())
else
None
match watch with
| Yes _ -> Some (Dune_rpc_impl.Server.create ())
| No -> None
in
let stats =
Option.map stats_trace_file ~f:(fun f ->
Expand Down
2 changes: 1 addition & 1 deletion bin/common.mli
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ val stats : t -> Dune_stats.t option

val print_metrics : t -> bool

val watch : t -> bool
val watch : t -> Dune_engine.Watch_mode_config.t

val file_watcher : t -> Dune_engine.Scheduler.Run.file_watcher

Expand Down
16 changes: 9 additions & 7 deletions bin/import.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ include Common.Let_syntax

let in_group (t, info) = (Term.Group.Term t, info)

module Main = struct
module Main : sig
include module type of struct
include Dune_rules.Main
end

val setup : unit -> build_system Fiber.t
end = struct
include Dune_rules.Main

let setup () =
Expand Down Expand Up @@ -92,17 +98,13 @@ module Scheduler = struct
let config = Dune_config.for_scheduler dune_config None stats in
Scheduler.Run.go config ~on_event:(on_event dune_config) f

let poll ~(common : Common.t) ~config:dune_config ~every ~finally =
let go_with_rpc_server_and_console_status_reporting ~(common : Common.t)
~config:dune_config run =
let stats = Common.stats common in
let rpc_where = Some (Dune_rpc_private.Where.default ()) in
let config = Dune_config.for_scheduler dune_config rpc_where stats in
let file_watcher = Common.file_watcher common in
let run =
let run () =
Scheduler.Run.poll (fun ~report_error () ->
Fiber.finalize (every ~report_error) ~finally:(fun () ->
Fiber.return (finally ())))
in
match Common.rpc common with
| None -> run
| Some rpc ->
Expand Down
44 changes: 40 additions & 4 deletions bin/rpc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ module Init = struct
let term = (Term.Group.Term term, info)
end

let report_error error =
Printf.printf "Error: %s\n%!"
(Dyn.to_string (Dune_rpc_private.Response.Error.to_dyn error))

module Status = struct
let term =
let+ (common : Common.t) = Common.term in
Expand All @@ -117,20 +121,52 @@ module Status = struct
()
in
match response with
| Error _ -> assert false
(* TODO *)
| Error error -> report_error error
| Ok { clients } ->
List.iter clients ~f:(fun client ->
let sexp = Dune_rpc.Conv.to_sexp Dune_rpc.Id.sexp client in
Sexp.to_string sexp |> print_endline))

let info =
let doc = "shot active connections" in
let doc = "show active connections" in
Term.info "status" ~doc

let term = (Term.Group.Term term, info)
end

module Build = struct
let term =
let name_ = Arg.info [] ~docv:"TARGET" in
let+ (common : Common.t) = Common.term
and+ targets = Arg.(value & pos_all string [] name_) in
client_term common @@ fun common ->
let where = wait_for_server common in
Dune_rpc_impl.Run.client where
(Dune_rpc.Initialize.Request.create
~id:(Dune_rpc.Id.make (Sexp.Atom "build")))
~on_notification:(fun _ -> assert false)
~f:(fun session ->
let open Fiber.O in
let+ response =
Dune_rpc_impl.Client.request session Dune_rpc_impl.Server.Decl.build
targets
in
match response with
| Error (error : Dune_rpc_private.Response.Error.t) ->
report_error error
| Ok Failure -> print_endline "Failure"
| Ok Success -> print_endline "Success")

let info =
let doc =
"build a given target (requires dune to be running in passive watching \
mode)"
in
Term.info "build" ~doc

let term = (Term.Group.Term term, info)
end

let info =
let doc = "Dune's RPC mechanism. Experimental." in
let man =
Expand All @@ -141,4 +177,4 @@ let info =
in
Term.info "rpc" ~doc ~man

let group = (Term.Group.Group [ Init.term; Status.term ], info)
let group = (Term.Group.Group [ Init.term; Status.term; Build.term ], info)
2 changes: 2 additions & 0 deletions otherlibs/dune-rpc/private/dune_rpc_private.mli
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ module Response : sig

exception E of t

val to_dyn : t -> Stdune.Dyn.t

val of_conv : Conv.error -> t

val create : ?payload:Csexp.t -> kind:kind -> message:string -> unit -> t
Expand Down
2 changes: 2 additions & 0 deletions otherlibs/dune-rpc/private/types.mli
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ module Response : sig
; kind : kind
}

val to_dyn : t -> Dyn.t

val payload : t -> Sexp.t option

val message : t -> string
Expand Down
2 changes: 1 addition & 1 deletion src/dune_engine/clflags.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ let promote = ref None

let force = ref false

let watch = ref false
let watch = ref Watch_mode_config.No

let no_print_directory = ref false

Expand Down
2 changes: 1 addition & 1 deletion src/dune_engine/clflags.mli
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ val promote : Promote.t option ref
val force : bool ref

(** Instead of terminating build after completion, watch for changes *)
val watch : bool ref
val watch : Watch_mode_config.t ref

(** Do not print "Entering directory" messages *)
val no_print_directory : bool ref
Expand Down
1 change: 1 addition & 0 deletions src/dune_engine/dune_engine.ml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ module Execution_parameters = Execution_parameters
module Cache_debug_flags = Cache_debug_flags
module Reversible_digest = Reversible_digest
module Report_errors_config = Report_errors_config
module Watch_mode_config = Watch_mode_config
4 changes: 4 additions & 0 deletions src/dune_engine/fs_memo.ml
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,8 @@ module Event = struct
| Directory_deleted
| Unknown ->
invalidate_path_and_its_parent path

let path t = t.path

let kind t = t.kind
end
4 changes: 4 additions & 0 deletions src/dune_engine/fs_memo.mli
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ module Event : sig

type t

val kind : t -> kind

val path : t -> Path.t

val create : kind:kind -> path:Path.t -> t

(** Handle file system event. *)
Expand Down
Loading