From e1f9e9f36c3bf6f977ce52c9d5cdbede0e8e96b8 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Fri, 14 Jun 2024 12:30:56 +0100 Subject: [PATCH 1/3] Shell: change get_estimate_time_to_next_level to take a store getter --- src/lib_shell/http_cache_headers.ml | 51 +++++++++++++++------------- src/lib_shell/http_cache_headers.mli | 2 +- src/lib_shell/node.ml | 2 +- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/lib_shell/http_cache_headers.ml b/src/lib_shell/http_cache_headers.ml index 8242cf895e3c..3118321b000f 100644 --- a/src/lib_shell/http_cache_headers.ml +++ b/src/lib_shell/http_cache_headers.ml @@ -9,32 +9,35 @@ type tools = { get_estimated_time_to_next_level : unit -> Ptime.span option Lwt.t; } -(** [get_estimated_time_to_next_level chain_store] gets the estimated time - to the next level of the main chain *) -let get_estimated_time_to_next_level chain_store = +(** [get_estimated_time_to_next_level get_chain_store] gets the estimated time + to the next level of the main chain, obtained with the [get_chain_store] *) +let get_estimated_time_to_next_level get_chain_store = let open Lwt_option_syntax in - let*! block = Store.Chain.current_head chain_store in - let header = Store.Block.shell_header block in - let*! proto_hash = Store.Block.protocol_hash_exn chain_store block in - let*? (module Http_cache_headers) = - Protocol_plugin.find_http_cache_headers proto_hash - in - let* round_end = - Http_cache_headers.get_round_end_time - ~get_context:(fun () -> Store.Block.context_exn chain_store block) - header - in - let now = Time.System.now () in - if round_end < now then - (* If the round has ended, then the next level block is late. - We cannot be sure when it will arrive. *) - Lwt.return_none - else - let timespan = Ptime.diff round_end now in - return timespan + match get_chain_store () with + | None -> Lwt.return_none + | Some chain_store -> + let*! block = Store.Chain.current_head chain_store in + let header = Store.Block.shell_header block in + let*! proto_hash = Store.Block.protocol_hash_exn chain_store block in + let*? (module Http_cache_headers) = + Protocol_plugin.find_http_cache_headers proto_hash + in + let* round_end = + Http_cache_headers.get_round_end_time + ~get_context:(fun () -> Store.Block.context_exn chain_store block) + header + in + let now = Time.System.now () in + if round_end < now then + (* If the round has ended, then the next level block is late. + We cannot be sure when it will arrive. *) + Lwt.return_none + else + let timespan = Ptime.diff round_end now in + return timespan -let make_tools chain_store = +let make_tools get_chain_store = { get_estimated_time_to_next_level = - (fun () -> get_estimated_time_to_next_level chain_store); + (fun () -> get_estimated_time_to_next_level get_chain_store); } diff --git a/src/lib_shell/http_cache_headers.mli b/src/lib_shell/http_cache_headers.mli index 634885207287..dd490a7b4813 100644 --- a/src/lib_shell/http_cache_headers.mli +++ b/src/lib_shell/http_cache_headers.mli @@ -13,4 +13,4 @@ type tools = { get_estimated_time_to_next_level : unit -> Ptime.span option Lwt.t; } -val make_tools : Store.chain_store -> tools +val make_tools : (unit -> Store.chain_store option) -> tools diff --git a/src/lib_shell/node.ml b/src/lib_shell/node.ml index 3952f44dc7ed..ae8cfb0f8163 100644 --- a/src/lib_shell/node.ml +++ b/src/lib_shell/node.ml @@ -354,7 +354,7 @@ let shutdown node = node.shutdown () let http_cache_header_tools node = let store = node.store in let chain_store = Store.main_chain_store store in - Http_cache_headers.make_tools chain_store + Http_cache_headers.make_tools (fun () -> Some chain_store) let build_rpc_directory ~node_version node = let dir : unit Tezos_rpc.Directory.t ref = ref Tezos_rpc.Directory.empty in -- GitLab From bb17185fdb1ce82d647d262bee971b1fc7d2dcf9 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Mon, 10 Jun 2024 11:40:48 +0100 Subject: [PATCH 2/3] Node run: add http cache header middleware to external rpc server --- src/bin_node/node_run_command.ml | 19 +++++++++++-------- src/lib_rpc_process/main.ml | 16 ++++++++++++++++ src/lib_rpc_process/rpc_process_events.ml | 8 ++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/bin_node/node_run_command.ml b/src/bin_node/node_run_command.ml index 73b7fcdf6ee9..8a5c15a60fd6 100644 --- a/src/bin_node/node_run_command.ml +++ b/src/bin_node/node_run_command.ml @@ -209,11 +209,11 @@ module Event = struct ~level:Warning () - let enable_http_cache_headers = + let enable_http_cache_headers_for_local = declare_0 ~section - ~name:"enable_http_cache_headers" - ~msg:"HTTP cache headers enabled" + ~name:"enable_http_cache_headers_for_local" + ~msg:"HTTP cache headers enabled for local rpc server" ~level:Notice () end @@ -546,8 +546,8 @@ let rpc_socket_path ~socket_dir ~id ~pid = (* Initializes an RPC server handled by the node process. It will be used by an external RPC process, identified by [id], to forward RPCs to the node through a Unix socket. *) -let init_local_rpc_server_for_external_process id (config : Config_file.t) dir - addr = +let init_local_rpc_server_for_external_process ?middleware id + (config : Config_file.t) dir addr = let open Lwt_result_syntax in let socket_dir = Tezos_base_unix.Socket.get_temporary_socket_dir () in let pid = Unix.getpid () in @@ -561,11 +561,12 @@ let init_local_rpc_server_for_external_process id (config : Config_file.t) dir Lwt_unix.unlink comm_socket_path) in let* rpc_server = - launch_rpc_server config dir (Process comm_socket_path) addr + launch_rpc_server ?middleware config dir (Process comm_socket_path) addr in return (rpc_server, comm_socket_path) -let init_external_rpc_server config node_version dir internal_events = +let init_external_rpc_server ?middleware config node_version dir internal_events + = let open Lwt_result_syntax in (* Start one rpc_process for each rpc endpoint. *) let id = ref 0 in @@ -585,6 +586,7 @@ let init_external_rpc_server config node_version dir internal_events = in let* local_rpc_server, comm_socket_path = init_local_rpc_server_for_external_process + ?middleware id config dir @@ -670,7 +672,8 @@ let init_rpc (config : Config_file.t) (node : Node.t) internal_events = else let* middleware = if config.rpc.enable_http_cache_headers then - let*! () = Event.(emit enable_http_cache_headers ()) in + let*! () = Event.(emit enable_http_cache_headers_for_local ()) in + let http_cache_headers_middleware = let Http_cache_headers.{get_estimated_time_to_next_level} = Node.http_cache_header_tools node diff --git a/src/lib_rpc_process/main.ml b/src/lib_rpc_process/main.ml index 08bb142e0c03..8a282d236289 100644 --- a/src/lib_rpc_process/main.ml +++ b/src/lib_rpc_process/main.ml @@ -119,6 +119,22 @@ let launch_rpc_server dynamic_store (params : Parameters.t) (addr, port) let callback = Forward_handler.callback ~acl server params.rpc_comm_socket_path in + let* callback = + if params.config.rpc.enable_http_cache_headers then + let Http_cache_headers.{get_estimated_time_to_next_level} = + Http_cache_headers.make_tools (fun () -> + let store_opt = !dynamic_store in + Option.map Store.main_chain_store store_opt) + in + let*! () = + Rpc_process_events.(emit enable_http_cache_headers_for_external ()) + in + return + (RPC_middleware.Http_cache_headers.make + ~get_estimated_time_to_next_level + callback) + else return callback + in Lwt.catch (fun () -> let*! () = diff --git a/src/lib_rpc_process/rpc_process_events.ml b/src/lib_rpc_process/rpc_process_events.ml index 324c62bc23b6..91a72b302662 100644 --- a/src/lib_rpc_process/rpc_process_events.ml +++ b/src/lib_rpc_process/rpc_process_events.ml @@ -106,3 +106,11 @@ let store_synchronized_on_head = ~pp1:Block_hash.pp_short ("hash", Block_hash.encoding) ("level", Data_encoding.int32) + +let enable_http_cache_headers_for_external = + declare_0 + ~section + ~name:"enable_http_cache_headers_for_external" + ~msg:"HTTP cache headers enabled for external rpc server" + ~level:Notice + () -- GitLab From 3f61ee8a9e237db391ee7ed8ed34e4f1782f1e65 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Tue, 25 Jun 2024 17:00:16 +0100 Subject: [PATCH 3/3] Tezt: add tezt tests for external --- tezt/tests/http_cache_headers.ml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tezt/tests/http_cache_headers.ml b/tezt/tests/http_cache_headers.ml index 37b88f3f0cc2..e6b2a4c9cec1 100644 --- a/tezt/tests/http_cache_headers.ml +++ b/tezt/tests/http_cache_headers.ml @@ -41,20 +41,26 @@ let check_max_age_in_headers ?(expects_missing_header = false) ~__LOC__ headers when the round duration has not yet elapsed and the absence of the header field when the round duration has elapsed and no new block has arrived. *) -let test_max_age = +let test_max_age ~rpc_external = + let title = + "max-age header for " ^ if rpc_external then "external rpc" else "local rpc" + in Protocol.register_test ~__FILE__ - ~title:"max-age header" + ~title ~tags:["rpc"; "middleware"; "http_cache_headers"] ~supports:(From_protocol 19) @@ fun protocol -> Log.info "Initialize client, node and baker" ; let node = Node.create + ~rpc_external [Connections 0; Synchronisation_threshold 0; Enable_http_cache_headers] in let http_cache_headers_enabled_event = - Node.wait_for node "enable_http_cache_headers.v0" Option.some + if rpc_external then + Node.wait_for node "enable_http_cache_headers_for_external.v0" Option.some + else Node.wait_for node "enable_http_cache_headers_for_local.v0" Option.some in let* () = Node.run node [] in let* () = Node.wait_for_ready node in @@ -90,4 +96,6 @@ let test_max_age = let* () = Node.terminate node in unit -let register ~protocols = test_max_age protocols +let register ~protocols = + test_max_age ~rpc_external:true protocols ; + test_max_age ~rpc_external:false protocols -- GitLab