mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Simplify ClusterController::API::set_configuration_request/response
It's easier to track outstanding controller/agent requests via a simple set of pending agent names, and we can remove all of the result aggregation logic since we can simply re-use the results reported by the agents. This can serve as a template for request-response patterns where a client's request triggers a request to all agents, followed by a response to the client once all agents have responded. Once we have a few more of those, it'll become clearer how to abstract this further.
This commit is contained in:
parent
0793a38cc5
commit
f9ac03d6e3
2 changed files with 20 additions and 52 deletions
|
@ -70,9 +70,9 @@ function send_config_to_agents(req: ClusterController::Request::Request,
|
||||||
areq$parent_id = req$id;
|
areq$parent_id = req$id;
|
||||||
|
|
||||||
# We track the requests sent off to each agent. As the
|
# We track the requests sent off to each agent. As the
|
||||||
# responses come in, we can check them off as completed,
|
# responses come in, we delete them. Once the requests
|
||||||
# and once all are, we respond back to the client.
|
# set is empty, we respond back to the client.
|
||||||
req$set_configuration_state$requests += areq;
|
add req$set_configuration_state$requests[areq$id];
|
||||||
|
|
||||||
# We could also broadcast just once on the agent prefix, but
|
# We could also broadcast just once on the agent prefix, but
|
||||||
# explicit request/response pairs for each agent seems cleaner.
|
# explicit request/response pairs for each agent seems cleaner.
|
||||||
|
@ -283,62 +283,30 @@ event ClusterAgent::API::set_configuration_response(reqid: string, result: Clust
|
||||||
if ( ClusterController::Request::is_null(areq) )
|
if ( ClusterController::Request::is_null(areq) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
# Record the result and mark the request as done. This also
|
# Release the request, which is now done.
|
||||||
# marks the request as done in the parent-level request, since
|
ClusterController::Request::finish(areq$id);
|
||||||
# these records are stored by reference.
|
|
||||||
areq$results[0] = result; # We only have a single result here atm
|
|
||||||
areq$finished = T;
|
|
||||||
|
|
||||||
# Update the original request from the client:
|
# Find the original request from the client
|
||||||
local req = ClusterController::Request::lookup(areq$parent_id);
|
local req = ClusterController::Request::lookup(areq$parent_id);
|
||||||
if ( ClusterController::Request::is_null(req) )
|
if ( ClusterController::Request::is_null(req) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
# If there are any requests to the agents still unfinished,
|
# Add this result to the overall response
|
||||||
# we're not done yet.
|
req$results[|req$results|] = result;
|
||||||
for ( i in req$set_configuration_state$requests )
|
|
||||||
if ( ! req$set_configuration_state$requests[i]$finished )
|
|
||||||
return;
|
|
||||||
|
|
||||||
# All set_configuration requests to instances are done, so respond
|
# Mark this request as done by removing it from the table of pending
|
||||||
# back to client. We need to compose the result, aggregating
|
# ones. The following if-check should always be true.
|
||||||
# the results we got from the requests to the agents. In the
|
if ( areq$id in req$set_configuration_state$requests )
|
||||||
# end we have one Result per instance requested in the
|
delete req$set_configuration_state$requests[areq$id];
|
||||||
# original set_configuration_request.
|
|
||||||
#
|
|
||||||
# XXX we can likely generalize result aggregation in the request module.
|
|
||||||
for ( i in req$set_configuration_state$requests )
|
|
||||||
{
|
|
||||||
local r = req$set_configuration_state$requests[i];
|
|
||||||
|
|
||||||
local success = T;
|
# If there are any pending requests to the agents, we're
|
||||||
local errors: string_vec;
|
# done: we respond once every agent has responed (or we time out).
|
||||||
local instance = "";
|
if ( |req$set_configuration_state$requests| > 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
for ( j in r$results )
|
# All set_configuration requests to instances are done, so adopt the
|
||||||
{
|
# client's requested configuration as the new one and respond back to
|
||||||
local res = r$results[j];
|
# client.
|
||||||
instance = res$instance;
|
|
||||||
|
|
||||||
if ( res$success )
|
|
||||||
next;
|
|
||||||
|
|
||||||
success = F;
|
|
||||||
errors += fmt("node %s failed: %s", res$node, res$error);
|
|
||||||
}
|
|
||||||
|
|
||||||
req$results += ClusterController::Types::Result(
|
|
||||||
$reqid = req$id,
|
|
||||||
$instance = instance,
|
|
||||||
$success = success,
|
|
||||||
$error = join_string_vec(errors, ", ")
|
|
||||||
);
|
|
||||||
|
|
||||||
ClusterController::Request::finish(r$id);
|
|
||||||
}
|
|
||||||
|
|
||||||
# We're now done with the original set_configuration request.
|
|
||||||
# Adopt the configuration as the current one.
|
|
||||||
g_config_current = req$set_configuration_state$config;
|
g_config_current = req$set_configuration_state$config;
|
||||||
g_config_reqid_pending = "";
|
g_config_reqid_pending = "";
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ export {
|
||||||
# State specific to the set_configuration request/response events
|
# State specific to the set_configuration request/response events
|
||||||
type SetConfigurationState: record {
|
type SetConfigurationState: record {
|
||||||
config: ClusterController::Types::Configuration;
|
config: ClusterController::Types::Configuration;
|
||||||
requests: vector of Request &default=vector();
|
requests: set[string] &default=set();
|
||||||
};
|
};
|
||||||
|
|
||||||
# State specific to supervisor interactions
|
# State specific to supervisor interactions
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue