diff --git a/src/lib_node_config/config_file.ml b/src/lib_node_config/config_file.ml index 63f14a146b35dfc5a54e7e7086c8d3e0b86de9b5..a5752da8db8ae8bcb9f62be478bea33f4b4d9d9d 100644 --- a/src/lib_node_config/config_file.ml +++ b/src/lib_node_config/config_file.ml @@ -890,7 +890,7 @@ let update ?(disable_config_validation = false) ?data_dir ?min_connections ?(enable_testchain = default_p2p.enable_testchain) ?(cors_origins = []) ?(cors_headers = []) ?rpc_tls ?log_output ?log_coloring ?synchronisation_threshold ?history_mode ?network ?latency ?context_pruning - cfg = + ?storage_maintenance_delay cfg = let open Lwt_result_syntax in let disable_config_validation = cfg.disable_config_validation || disable_config_validation @@ -1014,6 +1014,10 @@ let update ?(disable_config_validation = false) ?data_dir ?min_connections history_mode = Option.either history_mode cfg.shell.history_mode; context_pruning = Option.either context_pruning cfg.shell.context_pruning; + storage_maintenance_delay = + Option.either + storage_maintenance_delay + cfg.shell.storage_maintenance_delay; } in (* If --network is specified it overrides the "network" entry of the diff --git a/src/lib_node_config/config_file.mli b/src/lib_node_config/config_file.mli index b6e9fe96d76868a6e5add75607dbf5b8c379d4a1..0f68d4574ca69c2cd02c89f07c6afe44110de394 100644 --- a/src/lib_node_config/config_file.mli +++ b/src/lib_node_config/config_file.mli @@ -141,6 +141,7 @@ val update : ?network:blockchain_network -> ?latency:int -> ?context_pruning:Storage_maintenance.context_pruning -> + ?storage_maintenance_delay:Storage_maintenance.delay -> t -> t tzresult Lwt.t diff --git a/src/lib_node_config/shared_arg.ml b/src/lib_node_config/shared_arg.ml index 13fbf43b37050c0a203c7269910942e456875ac6..052989eea6027ef3559c63c525be4094c37cc654 100644 --- a/src/lib_node_config/shared_arg.ml +++ b/src/lib_node_config/shared_arg.ml @@ -71,6 +71,7 @@ type t = { operation_metadata_size_limit : Shell_limits.operation_metadata_size_limit option; context_pruning : Storage_maintenance.context_pruning option; + storage_maintenance_delay : Storage_maintenance.delay; } type error += @@ -192,7 +193,7 @@ let wrap data_dir config_file network connections max_download_speed log_coloring history_mode synchronisation_threshold latency disable_config_validation allow_all_rpc media_type max_active_rpc_connections metrics_addr operation_metadata_size_limit - context_pruning = + context_pruning storage_maintenance_delay = let actual_data_dir = Option.value ~default:Config_file.default_data_dir data_dir in @@ -242,6 +243,7 @@ let wrap data_dir config_file network connections max_download_speed metrics_addr; operation_metadata_size_limit; context_pruning; + storage_maintenance_delay; } let process_command run = @@ -758,7 +760,7 @@ module Term = struct in let parse str = match str with - | "disabled" -> `Ok Disabled + | "disabled" -> `Ok (Disabled : Storage_maintenance.context_pruning) | "enabled" -> `Ok Enabled | _ -> `Error @@ -769,6 +771,19 @@ module Term = struct & opt (some (parse, pp_context_pruning)) None & info ~docs ~doc ["context-pruning"]) + let storage_maintenance_delay = + let open Storage_maintenance in + let doc = "Configures the storage maintenance delays" in + let get_storage_maintenance_delay_arg str = + match str with + | "disabled" -> `Ok Disabled + | _ -> `Error "storage-maintenance-delay only supports \"disabled\" mode" + in + Arg.( + value + & opt (get_storage_maintenance_delay_arg, pp_delay) Disabled + & info ~docs ~doc ["storage-maintenance-delay"]) + (* Args. *) let args = @@ -783,7 +798,7 @@ module Term = struct $ log_output $ log_coloring $ history_mode $ synchronisation_threshold $ latency $ disable_config_validation $ allow_all_rpc $ media_type $ max_active_rpc_connections $ metrics_addr $ operation_metadata_size_limit - $ context_pruning + $ context_pruning $ storage_maintenance_delay end let read_config_file args = @@ -932,6 +947,7 @@ let patch_config ?(may_override_network = false) ?(emit = Event.emit) metrics_addr; operation_metadata_size_limit; context_pruning; + storage_maintenance_delay; } = args in @@ -1090,6 +1106,7 @@ let patch_config ?(may_override_network = false) ?(emit = Event.emit) ?history_mode ?latency ?context_pruning + ~storage_maintenance_delay cfg let read_and_patch_config_file ?may_override_network ?emit diff --git a/src/lib_node_config/shared_arg.mli b/src/lib_node_config/shared_arg.mli index 3468dd6eb10c3f97ac875cc4aaabc550e79386bf..06ad1ea1c64349331d2ca1705bd8647bbea590d9 100644 --- a/src/lib_node_config/shared_arg.mli +++ b/src/lib_node_config/shared_arg.mli @@ -87,6 +87,7 @@ type t = { Shell_limits.operation_metadata_size_limit option; (** maximum operation metadata size allowed to be stored on disk *) context_pruning : Storage_maintenance.context_pruning option; + storage_maintenance_delay : Storage_maintenance.delay; } val process_command : unit tzresult Lwt.t -> unit Cmdliner.Term.ret diff --git a/src/lib_shell_services/shell_limits.ml b/src/lib_shell_services/shell_limits.ml index e8092ba291034963350d87317b5434dc6e5c0732..f8e8589cf87001d3d4d9375a466478fca9835115 100644 --- a/src/lib_shell_services/shell_limits.ml +++ b/src/lib_shell_services/shell_limits.ml @@ -247,6 +247,8 @@ let chain_validator_limits_encoding = let default_storage_maintenance_context_pruning = Storage_maintenance.Enabled +let default_storage_maintenance_delay = Storage_maintenance.Disabled + type limits = { block_validator_limits : block_validator_limits; prevalidator_limits : prevalidator_limits; @@ -254,6 +256,7 @@ type limits = { chain_validator_limits : chain_validator_limits; history_mode : History_mode.t option; context_pruning : Storage_maintenance.context_pruning option; + storage_maintenance_delay : Storage_maintenance.delay option; } let default_limits = @@ -264,6 +267,7 @@ let default_limits = chain_validator_limits = default_chain_validator_limits; history_mode = None; context_pruning = Some Enabled; + storage_maintenance_delay = Some Disabled; } let limits_encoding = @@ -276,19 +280,22 @@ let limits_encoding = chain_validator_limits; history_mode; context_pruning; + storage_maintenance_delay; } -> ( peer_validator_limits, block_validator_limits, prevalidator_limits, chain_validator_limits, history_mode, - context_pruning )) + context_pruning, + storage_maintenance_delay )) (fun ( peer_validator_limits, block_validator_limits, prevalidator_limits, chain_validator_limits, history_mode, - context_pruning ) -> + context_pruning, + storage_maintenance_delay ) -> { peer_validator_limits; block_validator_limits; @@ -296,8 +303,9 @@ let limits_encoding = chain_validator_limits; history_mode; context_pruning; + storage_maintenance_delay; }) - (obj6 + (obj7 (dft "peer_validator" peer_validator_limits_encoding @@ -315,4 +323,5 @@ let limits_encoding = chain_validator_limits_encoding default_chain_validator_limits) (opt "history_mode" History_mode.encoding) - (opt "context_pruning" Storage_maintenance.context_pruning_encoding)) + (opt "context_pruning" Storage_maintenance.context_pruning_encoding) + (opt "storage_maintenance_delay" Storage_maintenance.delay_encoding)) diff --git a/src/lib_shell_services/shell_limits.mli b/src/lib_shell_services/shell_limits.mli index 79a8ee85501f3388ef6c5d48587c948144756850..86813499bc559c5befc86ec260fcc207b6918670 100644 --- a/src/lib_shell_services/shell_limits.mli +++ b/src/lib_shell_services/shell_limits.mli @@ -96,6 +96,8 @@ val chain_validator_limits_encoding : chain_validator_limits Data_encoding.t val default_storage_maintenance_context_pruning : Storage_maintenance.context_pruning +val default_storage_maintenance_delay : Storage_maintenance.delay + type limits = { block_validator_limits : block_validator_limits; prevalidator_limits : prevalidator_limits; @@ -103,6 +105,7 @@ type limits = { chain_validator_limits : chain_validator_limits; history_mode : History_mode.t option; context_pruning : Storage_maintenance.context_pruning option; + storage_maintenance_delay : Storage_maintenance.delay option; } val default_limits : limits diff --git a/src/lib_shell_services/storage_maintenance.ml b/src/lib_shell_services/storage_maintenance.ml index ccd56d0dac3a3d3b4e8b955748ca211981730610..c7c0d1b683c34d79334f2f5367bd51f311795eb0 100644 --- a/src/lib_shell_services/storage_maintenance.ml +++ b/src/lib_shell_services/storage_maintenance.ml @@ -38,3 +38,27 @@ let context_pruning_encoding = let pp_context_pruning fmt = function | Disabled -> Format.fprintf fmt "disabled" | Enabled -> Format.fprintf fmt "enabled" + +type delay = Disabled + +let delay_encoding = + let open Data_encoding in + def + "storage_maintenance_delay" + ~title:"storage maintenance delay" + ~description:"Delay prior to the storage maintenance trigger" + (union + ~tag_size:`Uint8 + [ + case + ~title:"disabled" + ~description: + "When disabled, the storage maintenance is triggered without any \ + delay, as soon as a new cycle starts." + (Tag 0) + (constant "disabled") + (function Disabled -> Some ()) + (fun () -> Disabled); + ]) + +let pp_delay fmt = function Disabled -> Format.fprintf fmt "disabled" diff --git a/src/lib_shell_services/storage_maintenance.mli b/src/lib_shell_services/storage_maintenance.mli index aed282bf3d6479c087ca2993d1fc4d4fbef56a56..1a96fb55dfaef888e7f4a47b045d4e6c1c1ae254 100644 --- a/src/lib_shell_services/storage_maintenance.mli +++ b/src/lib_shell_services/storage_maintenance.mli @@ -19,3 +19,14 @@ type context_pruning = Enabled | Disabled val context_pruning_encoding : context_pruning Data_encoding.t val pp_context_pruning : Format.formatter -> context_pruning -> unit + +(** The type [delay] specifies whether or not a storage maintenance + should be delayed or not. + Setting it to [Disabled] will trigger the storage maintenance as + soon as possible, that is, at the very beginning of a new cycle + dawn. *) +type delay = Disabled + +val delay_encoding : delay Data_encoding.t + +val pp_delay : Format.formatter -> delay -> unit diff --git a/tezt/lib_tezos/node.ml b/tezt/lib_tezos/node.ml index 0f74708139cfe9dd6117a7ddc1fe51a62be38a75..df0e8f121abc6de161a65a80d187c3c9c667d359 100644 --- a/tezt/lib_tezos/node.ml +++ b/tezt/lib_tezos/node.ml @@ -60,6 +60,7 @@ type argument = | RPC_additional_addr_external of string | Max_active_rpc_connections of int | Context_pruning of string + | Storage_maintenance_delay of string let make_argument = function | Network x -> ["--network"; x] @@ -94,6 +95,7 @@ let make_argument = function | Max_active_rpc_connections n -> ["--max-active-rpc-connections"; string_of_int n] | Context_pruning x -> ["--context-pruning"; x] + | Storage_maintenance_delay x -> ["--storage-maintenance-delay"; x] let make_arguments arguments = List.flatten (List.map make_argument arguments) @@ -117,7 +119,8 @@ let is_redundant = function | Metadata_size_limit _, Metadata_size_limit _ | Version, Version | Max_active_rpc_connections _, Max_active_rpc_connections _ - | Context_pruning _, Context_pruning _ -> + | Context_pruning _, Context_pruning _ + | Storage_maintenance_delay _, Storage_maintenance_delay _ -> true | Metrics_addr addr1, Metrics_addr addr2 -> addr1 = addr2 | Peer peer1, Peer peer2 -> peer1 = peer2 @@ -143,7 +146,8 @@ let is_redundant = function | RPC_additional_addr_external _, _ | Version, _ | Max_active_rpc_connections _, _ - | Context_pruning _, _ -> + | Context_pruning _, _ + | Storage_maintenance_delay _, _ -> false (* Some arguments should not be written in the config file by [Node.init] diff --git a/tezt/lib_tezos/node.mli b/tezt/lib_tezos/node.mli index 0876ae58905a8641b6b4dac1000d87182b71a95b..08f925ff56affc1a7507bb45b874fe54c7b8920b 100644 --- a/tezt/lib_tezos/node.mli +++ b/tezt/lib_tezos/node.mli @@ -100,6 +100,7 @@ type argument = | RPC_additional_addr_external of string (** [--external-rpc-addr] *) | Max_active_rpc_connections of int (** [--max-active-rpc-connections] *) | Context_pruning of string (** [--context-pruning] *) + | Storage_maintenance_delay of string (** [--storage-maintenance-delay]*) (** A TLS configuration for the node: paths to a [.crt] and a [.key] file. diff --git a/tezt/tests/storage_maintenance.ml b/tezt/tests/storage_maintenance.ml index a5b809b835c7944ca36f31eeaea12a66cb31afba..baf3888a49ef417d8b1e73bcbb69b0439cad1565 100644 --- a/tezt/tests/storage_maintenance.ml +++ b/tezt/tests/storage_maintenance.ml @@ -68,4 +68,59 @@ let test_context_pruning_call = let* () = wait_context_gc and* () = wait_context_split in unit -let register ~protocols = test_context_pruning_call protocols +let wait_for_complete_storage_maintenance node target = + let filter json = + let level = JSON.(json |> as_int) in + if level = target then Some () else None + in + let wait_for_ending_merge () = + Node.wait_for node "end_merging_stores.v0" @@ fun _json -> Some () + in + let* () = Node.wait_for node "start_merging_stores.v0" filter in + wait_for_ending_merge () + +let test_disabled_maintenance_delay = + Protocol.register_test + ~__FILE__ + ~title:(Format.asprintf "storage maintenance disabled delay") + ~tags:[team; "storage"; "maintenance"; "delay"; "disabled"] + @@ fun protocol -> + let* node = + Node.init + Node.[Synchronisation_threshold 0; Storage_maintenance_delay "disabled"] + in + let* client = Client.init ~endpoint:(Node node) () in + let* () = Client.activate_protocol_and_wait ~protocol ~node client in + let blocks_per_cycle = 8 in + let blocks_to_bake = 2 * blocks_per_cycle in + let wait_merge = + wait_for_complete_storage_maintenance node (blocks_per_cycle + 1) + in + let* () = bake_blocks node client ~blocks_to_bake in + Log.info "Waiting for the merge" ; + let* () = wait_merge in + unit + +(* This is a temporary test to ensure that only the disabled mode is + implemented. *) +let test_only_disabled_is_implemented = + Protocol.register_test + ~__FILE__ + ~title:(Format.asprintf "storage maintenance allows disabled only") + ~tags:[team; "storage"; "maintenance"; "delay"; "enable"] + ~uses_client:false + ~uses_admin_client:false + @@ fun _protocol -> + let node = Node.create Node.[Synchronisation_threshold 0] in + let* () = + Node.spawn_config_update node [Storage_maintenance_delay "enabled"] + |> Process.check_error + ~msg:(rex "only supports \"disabled\" mode") + ~exit_code:124 + in + unit + +let register ~protocols = + test_context_pruning_call protocols ; + test_disabled_maintenance_delay protocols ; + test_only_disabled_is_implemented protocols