xref: /aosp_15_r20/external/federated-compute/fcp/client/federated_protocol.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker  * Copyright 2020 Google LLC
3*14675a02SAndroid Build Coastguard Worker  *
4*14675a02SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker  *
8*14675a02SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker  *
10*14675a02SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker  * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker  */
16*14675a02SAndroid Build Coastguard Worker #ifndef FCP_CLIENT_FEDERATED_PROTOCOL_H_
17*14675a02SAndroid Build Coastguard Worker #define FCP_CLIENT_FEDERATED_PROTOCOL_H_
18*14675a02SAndroid Build Coastguard Worker 
19*14675a02SAndroid Build Coastguard Worker #include <cstdint>
20*14675a02SAndroid Build Coastguard Worker #include <functional>
21*14675a02SAndroid Build Coastguard Worker #include <memory>
22*14675a02SAndroid Build Coastguard Worker #include <optional>
23*14675a02SAndroid Build Coastguard Worker #include <string>
24*14675a02SAndroid Build Coastguard Worker #include <utility>
25*14675a02SAndroid Build Coastguard Worker #include <variant>
26*14675a02SAndroid Build Coastguard Worker #include <vector>
27*14675a02SAndroid Build Coastguard Worker 
28*14675a02SAndroid Build Coastguard Worker #include "absl/container/node_hash_map.h"
29*14675a02SAndroid Build Coastguard Worker #include "absl/status/status.h"
30*14675a02SAndroid Build Coastguard Worker #include "absl/status/statusor.h"
31*14675a02SAndroid Build Coastguard Worker #include "fcp/client/engine/engine.pb.h"
32*14675a02SAndroid Build Coastguard Worker #include "fcp/client/stats.h"
33*14675a02SAndroid Build Coastguard Worker #include "fcp/protos/federated_api.pb.h"
34*14675a02SAndroid Build Coastguard Worker #include "fcp/protos/federatedcompute/eligibility_eval_tasks.pb.h"
35*14675a02SAndroid Build Coastguard Worker #include "fcp/protos/plan.pb.h"
36*14675a02SAndroid Build Coastguard Worker 
37*14675a02SAndroid Build Coastguard Worker namespace fcp {
38*14675a02SAndroid Build Coastguard Worker namespace client {
39*14675a02SAndroid Build Coastguard Worker 
40*14675a02SAndroid Build Coastguard Worker // Data type used to encode results of a computation - a TensorFlow
41*14675a02SAndroid Build Coastguard Worker // checkpoint, or SecAgg quantized tensors.
42*14675a02SAndroid Build Coastguard Worker // For non-SecAgg use (simple federated aggregation, or local computation),
43*14675a02SAndroid Build Coastguard Worker // this map should only contain one entry - a TFCheckpoint - and the string
44*14675a02SAndroid Build Coastguard Worker // should be ignored by downstream code.
45*14675a02SAndroid Build Coastguard Worker // For SecAgg use, there should be
46*14675a02SAndroid Build Coastguard Worker // * at most one TFCheckpoint - again, the key should be ignored - and
47*14675a02SAndroid Build Coastguard Worker // * N QuantizedTensors, whose string keys must map to the tensor names
48*14675a02SAndroid Build Coastguard Worker //   provided in the server's CheckinResponse's SideChannelExecutionInfo.
49*14675a02SAndroid Build Coastguard Worker using TFCheckpoint = std::string;
50*14675a02SAndroid Build Coastguard Worker struct QuantizedTensor {
51*14675a02SAndroid Build Coastguard Worker   std::vector<uint64_t> values;
52*14675a02SAndroid Build Coastguard Worker   int32_t bitwidth = 0;
53*14675a02SAndroid Build Coastguard Worker   std::vector<int64_t> dimensions;
54*14675a02SAndroid Build Coastguard Worker 
55*14675a02SAndroid Build Coastguard Worker   QuantizedTensor() = default;
56*14675a02SAndroid Build Coastguard Worker   // Disallow copy and assign.
57*14675a02SAndroid Build Coastguard Worker   QuantizedTensor(const QuantizedTensor&) = delete;
58*14675a02SAndroid Build Coastguard Worker   QuantizedTensor& operator=(const QuantizedTensor&) = delete;
59*14675a02SAndroid Build Coastguard Worker   // Enable move semantics.
60*14675a02SAndroid Build Coastguard Worker   QuantizedTensor(QuantizedTensor&&) = default;
61*14675a02SAndroid Build Coastguard Worker   QuantizedTensor& operator=(QuantizedTensor&&) = default;
62*14675a02SAndroid Build Coastguard Worker };
63*14675a02SAndroid Build Coastguard Worker // This is equivalent to using ComputationResults =
64*14675a02SAndroid Build Coastguard Worker //    std::map<std::string, std::variant<TFCheckpoint, QuantizedTensor>>;
65*14675a02SAndroid Build Coastguard Worker // except copy construction and assignment are explicitly prohibited and move
66*14675a02SAndroid Build Coastguard Worker // semantics is enforced.
67*14675a02SAndroid Build Coastguard Worker class ComputationResults
68*14675a02SAndroid Build Coastguard Worker     : public absl::node_hash_map<std::string,
69*14675a02SAndroid Build Coastguard Worker                                  std::variant<TFCheckpoint, QuantizedTensor>> {
70*14675a02SAndroid Build Coastguard Worker  public:
71*14675a02SAndroid Build Coastguard Worker   using Base = absl::node_hash_map<std::string,
72*14675a02SAndroid Build Coastguard Worker                                    std::variant<TFCheckpoint, QuantizedTensor>>;
73*14675a02SAndroid Build Coastguard Worker   using Base::Base;
74*14675a02SAndroid Build Coastguard Worker   using Base::operator=;
75*14675a02SAndroid Build Coastguard Worker   ComputationResults(const ComputationResults&) = delete;
76*14675a02SAndroid Build Coastguard Worker   ComputationResults& operator=(const ComputationResults&) = delete;
77*14675a02SAndroid Build Coastguard Worker   ComputationResults(ComputationResults&&) = default;
78*14675a02SAndroid Build Coastguard Worker   ComputationResults& operator=(ComputationResults&&) = default;
79*14675a02SAndroid Build Coastguard Worker };
80*14675a02SAndroid Build Coastguard Worker 
81*14675a02SAndroid Build Coastguard Worker // An interface that represents a single Federated Compute protocol session.
82*14675a02SAndroid Build Coastguard Worker //
83*14675a02SAndroid Build Coastguard Worker // An instance of this class represents a single session of client-server
84*14675a02SAndroid Build Coastguard Worker // interaction. Instances are generally stateful, and therefore cannot be
85*14675a02SAndroid Build Coastguard Worker // reused (each session should use a dedicated instance).
86*14675a02SAndroid Build Coastguard Worker //
87*14675a02SAndroid Build Coastguard Worker // The protocol consists of 3 phases, which must occur in the following order:
88*14675a02SAndroid Build Coastguard Worker // 1. A call to `EligibilityEvalCheckin()`.
89*14675a02SAndroid Build Coastguard Worker // 2. A call to `Checkin(...)`, only if the client wasn't rejected by the server
90*14675a02SAndroid Build Coastguard Worker //    in the previous phase.
91*14675a02SAndroid Build Coastguard Worker // 3. A call to `ReportCompleted(...)` or `ReportNotCompleted(...)`, only if the
92*14675a02SAndroid Build Coastguard Worker //    client wasn't rejected in the previous phase.
93*14675a02SAndroid Build Coastguard Worker class FederatedProtocol {
94*14675a02SAndroid Build Coastguard Worker  public:
95*14675a02SAndroid Build Coastguard Worker   virtual ~FederatedProtocol() = default;
96*14675a02SAndroid Build Coastguard Worker 
97*14675a02SAndroid Build Coastguard Worker   // The unparsed plan and checkpoint payload which make up a computation. The
98*14675a02SAndroid Build Coastguard Worker   // data can be provided as either an std::string or an absl::Cord.
99*14675a02SAndroid Build Coastguard Worker   struct PlanAndCheckpointPayloads {
100*14675a02SAndroid Build Coastguard Worker     std::variant<std::string, absl::Cord> plan;
101*14675a02SAndroid Build Coastguard Worker     std::variant<std::string, absl::Cord> checkpoint;
102*14675a02SAndroid Build Coastguard Worker   };
103*14675a02SAndroid Build Coastguard Worker 
104*14675a02SAndroid Build Coastguard Worker   // An eligibility task, consisting of task payloads and an execution ID.
105*14675a02SAndroid Build Coastguard Worker   struct EligibilityEvalTask {
106*14675a02SAndroid Build Coastguard Worker     PlanAndCheckpointPayloads payloads;
107*14675a02SAndroid Build Coastguard Worker     std::string execution_id;
108*14675a02SAndroid Build Coastguard Worker     std::optional<
109*14675a02SAndroid Build Coastguard Worker         google::internal::federatedcompute::v1::PopulationEligibilitySpec>
110*14675a02SAndroid Build Coastguard Worker         population_eligibility_spec;
111*14675a02SAndroid Build Coastguard Worker   };
112*14675a02SAndroid Build Coastguard Worker   // A rejection of a client by the server.
113*14675a02SAndroid Build Coastguard Worker   struct Rejection {};
114*14675a02SAndroid Build Coastguard Worker   // Indicates that the server does not have an eligibility eval task configured
115*14675a02SAndroid Build Coastguard Worker   // for the population.
116*14675a02SAndroid Build Coastguard Worker   struct EligibilityEvalDisabled {};
117*14675a02SAndroid Build Coastguard Worker   // EligibilityEvalCheckin() returns either
118*14675a02SAndroid Build Coastguard Worker   // 1. an `EligibilityEvalTask` struct holding the payloads for an eligibility
119*14675a02SAndroid Build Coastguard Worker   //    eval task, if the population is configured with such a task. In this
120*14675a02SAndroid Build Coastguard Worker   //    case the caller should execute the task and pass the resulting
121*14675a02SAndroid Build Coastguard Worker   //    `TaskEligibilityInfo` value to the `Checkin(...)` method.
122*14675a02SAndroid Build Coastguard Worker   // 2. an `EligibilityEvalDisabled` struct if the population doesn't have an
123*14675a02SAndroid Build Coastguard Worker   //    eligibility eval task configured. In this case the caller should
124*14675a02SAndroid Build Coastguard Worker   //    continue the protocol by calling the `Checkin(...)` method without
125*14675a02SAndroid Build Coastguard Worker   //    providing a `TaskEligibilityInfo` value.
126*14675a02SAndroid Build Coastguard Worker   // 3. a `Rejection` if the server rejected this device. In this case the
127*14675a02SAndroid Build Coastguard Worker   // caller
128*14675a02SAndroid Build Coastguard Worker   //    should end its protocol interaction.
129*14675a02SAndroid Build Coastguard Worker   using EligibilityEvalCheckinResult =
130*14675a02SAndroid Build Coastguard Worker       std::variant<EligibilityEvalTask, EligibilityEvalDisabled, Rejection>;
131*14675a02SAndroid Build Coastguard Worker 
132*14675a02SAndroid Build Coastguard Worker   // Checks in with a federated server to receive the population's eligibility
133*14675a02SAndroid Build Coastguard Worker   // eval task. This method is optional and may be called 0 or 1 times. If it is
134*14675a02SAndroid Build Coastguard Worker   // called, then it must be called before any call to `Checkin(...)`.
135*14675a02SAndroid Build Coastguard Worker   //
136*14675a02SAndroid Build Coastguard Worker   // If an eligibility eval task is configured, then the
137*14675a02SAndroid Build Coastguard Worker   // `payload_uris_received_callback` function will be called with a partially
138*14675a02SAndroid Build Coastguard Worker   // populated `EligibilityEvalTask` containing all of the task's info except
139*14675a02SAndroid Build Coastguard Worker   // for the actual payloads (which are yet to be fetched at that point).
140*14675a02SAndroid Build Coastguard Worker   //
141*14675a02SAndroid Build Coastguard Worker   // Returns:
142*14675a02SAndroid Build Coastguard Worker   // - On success, an EligibilityEvalCheckinResult.
143*14675a02SAndroid Build Coastguard Worker   // - On error:
144*14675a02SAndroid Build Coastguard Worker   //   - ABORTED when one of the I/O operations got aborted by the server.
145*14675a02SAndroid Build Coastguard Worker   //   - CANCELLED when one of the I/O operations was interrupted by the client
146*14675a02SAndroid Build Coastguard Worker   //     (possibly due to a positive result from the should_abort callback).
147*14675a02SAndroid Build Coastguard Worker   //   - UNAVAILABLE when server cannot be reached or URI is invalid.
148*14675a02SAndroid Build Coastguard Worker   //   - NOT_FOUND if the server responds with NOT_FOUND, e.g. because the
149*14675a02SAndroid Build Coastguard Worker   //     specified population name is incorrect.
150*14675a02SAndroid Build Coastguard Worker   //   - UNIMPLEMENTED if an unexpected server response is received.
151*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL if the server-provided ClientOnlyPlan cannot be parsed. (See
152*14675a02SAndroid Build Coastguard Worker   //     note in federated_protocol.cc for the reasoning for this.)
153*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL for other unexpected client-side errors.
154*14675a02SAndroid Build Coastguard Worker   //   - any server-provided error code.
155*14675a02SAndroid Build Coastguard Worker   virtual absl::StatusOr<EligibilityEvalCheckinResult> EligibilityEvalCheckin(
156*14675a02SAndroid Build Coastguard Worker       std::function<void(const EligibilityEvalTask&)>
157*14675a02SAndroid Build Coastguard Worker           payload_uris_received_callback) = 0;
158*14675a02SAndroid Build Coastguard Worker 
159*14675a02SAndroid Build Coastguard Worker   // Report an eligibility eval task error to the federated server.
160*14675a02SAndroid Build Coastguard Worker   // Must only be called once and after a successful call to
161*14675a02SAndroid Build Coastguard Worker   // EligibilityEvalCheckin() which returns an eligibility eval task. This
162*14675a02SAndroid Build Coastguard Worker   // method is only used to report an error happened during the computation of
163*14675a02SAndroid Build Coastguard Worker   // the eligibility eval task. If the eligibility eval computation succeeds,
164*14675a02SAndroid Build Coastguard Worker   // the success will be reported during task assignment.
165*14675a02SAndroid Build Coastguard Worker   // @param status the outcome of the eligibility eval computation.
166*14675a02SAndroid Build Coastguard Worker   virtual void ReportEligibilityEvalError(absl::Status error_status) = 0;
167*14675a02SAndroid Build Coastguard Worker 
168*14675a02SAndroid Build Coastguard Worker   // SecAgg metadata, e.g. see SecureAggregationProtocolExecutionInfo in
169*14675a02SAndroid Build Coastguard Worker   // federated_api.proto.
170*14675a02SAndroid Build Coastguard Worker   struct SecAggInfo {
171*14675a02SAndroid Build Coastguard Worker     int32_t expected_number_of_clients;
172*14675a02SAndroid Build Coastguard Worker     int32_t minimum_clients_in_server_visible_aggregate;
173*14675a02SAndroid Build Coastguard Worker   };
174*14675a02SAndroid Build Coastguard Worker 
175*14675a02SAndroid Build Coastguard Worker   // A task assignment, consisting of task payloads, a URI template to download
176*14675a02SAndroid Build Coastguard Worker   // federated select task slices with (if the plan uses federated select), a
177*14675a02SAndroid Build Coastguard Worker   // session identifier, and SecAgg-related metadata.
178*14675a02SAndroid Build Coastguard Worker   struct TaskAssignment {
179*14675a02SAndroid Build Coastguard Worker     PlanAndCheckpointPayloads payloads;
180*14675a02SAndroid Build Coastguard Worker     std::string federated_select_uri_template;
181*14675a02SAndroid Build Coastguard Worker     std::string aggregation_session_id;
182*14675a02SAndroid Build Coastguard Worker     std::optional<SecAggInfo> sec_agg_info;
183*14675a02SAndroid Build Coastguard Worker   };
184*14675a02SAndroid Build Coastguard Worker   // Checkin() returns either
185*14675a02SAndroid Build Coastguard Worker   // 1. a `TaskAssignment` struct if the client was assigned a task to run, or
186*14675a02SAndroid Build Coastguard Worker   // 2. a `Rejection` struct if the server rejected this device.
187*14675a02SAndroid Build Coastguard Worker   using CheckinResult = std::variant<TaskAssignment, Rejection>;
188*14675a02SAndroid Build Coastguard Worker 
189*14675a02SAndroid Build Coastguard Worker   // Checks in with a federated server. Must only be called once. If the
190*14675a02SAndroid Build Coastguard Worker   // `EligibilityEvalCheckin()` method was previously called, then this method
191*14675a02SAndroid Build Coastguard Worker   // must only be called if the result of that call was not a `Rejection`.
192*14675a02SAndroid Build Coastguard Worker   //
193*14675a02SAndroid Build Coastguard Worker   // If the caller previously called `EligibilityEvalCheckin()` and:
194*14675a02SAndroid Build Coastguard Worker   // - received a payload, then the `TaskEligibilityInfo` value computed by that
195*14675a02SAndroid Build Coastguard Worker   //   payload must be provided via the `task_eligibility_info` parameter.
196*14675a02SAndroid Build Coastguard Worker   // - received an `EligibilityEvalDisabled` result, then the
197*14675a02SAndroid Build Coastguard Worker   //   `task_eligibility_info` parameter should be left empty.
198*14675a02SAndroid Build Coastguard Worker   //
199*14675a02SAndroid Build Coastguard Worker   // If the caller did not previously call `EligibilityEvalCheckin()`, then the
200*14675a02SAndroid Build Coastguard Worker   // `task_eligibility_info` parameter should be left empty.
201*14675a02SAndroid Build Coastguard Worker   //
202*14675a02SAndroid Build Coastguard Worker   // If the client is assigned a task by the server, then the
203*14675a02SAndroid Build Coastguard Worker   // `payload_uris_received_callback` function will be called with a partially
204*14675a02SAndroid Build Coastguard Worker   // populated `TaskAssignment` containing all of the task's info except for the
205*14675a02SAndroid Build Coastguard Worker   // actual payloads (which are yet to be fetched at that point)
206*14675a02SAndroid Build Coastguard Worker   //
207*14675a02SAndroid Build Coastguard Worker   // Returns:
208*14675a02SAndroid Build Coastguard Worker   // - On success, a `CheckinResult`.
209*14675a02SAndroid Build Coastguard Worker   // - On error:
210*14675a02SAndroid Build Coastguard Worker   //   - ABORTED when one of the I/O operations got aborted by the server.
211*14675a02SAndroid Build Coastguard Worker   //   - CANCELLED when one of the I/O operations was interrupted by the client
212*14675a02SAndroid Build Coastguard Worker   //     (possibly due to a positive result from the should_abort callback).
213*14675a02SAndroid Build Coastguard Worker   //   - UNAVAILABLE when server cannot be reached or URI is invalid.
214*14675a02SAndroid Build Coastguard Worker   //   - NOT_FOUND if the server responds with NOT_FOUND, e.g. because the
215*14675a02SAndroid Build Coastguard Worker   //     specified population name is incorrect.
216*14675a02SAndroid Build Coastguard Worker   //   - UNIMPLEMENTED if an unexpected server response is received.
217*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL if the server-provided ClientOnlyPlan cannot be parsed. (See
218*14675a02SAndroid Build Coastguard Worker   //     note in federated_protocol.cc for the reasoning for this.)
219*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL for other unexpected client-side errors.
220*14675a02SAndroid Build Coastguard Worker   //   - any server-provided error code.
221*14675a02SAndroid Build Coastguard Worker   // TODO(team): Replace this reference to protocol-specific
222*14675a02SAndroid Build Coastguard Worker   // TaskEligibilityInfo proto with a protocol-agnostic struct.
223*14675a02SAndroid Build Coastguard Worker   virtual absl::StatusOr<CheckinResult> Checkin(
224*14675a02SAndroid Build Coastguard Worker       const std::optional<
225*14675a02SAndroid Build Coastguard Worker           google::internal::federatedml::v2::TaskEligibilityInfo>&
226*14675a02SAndroid Build Coastguard Worker           task_eligibility_info,
227*14675a02SAndroid Build Coastguard Worker       std::function<void(const TaskAssignment&)>
228*14675a02SAndroid Build Coastguard Worker           payload_uris_received_callback) = 0;
229*14675a02SAndroid Build Coastguard Worker 
230*14675a02SAndroid Build Coastguard Worker   // A list of absl::StatusOr<TaskAssignment> returned by
231*14675a02SAndroid Build Coastguard Worker   // PerformMultipleTaskAssignments. Individual absl::StatusOr<TaskAssignment>
232*14675a02SAndroid Build Coastguard Worker   // may be an error status due to failed to fetch the plan resources.
233*14675a02SAndroid Build Coastguard Worker   struct MultipleTaskAssignments {
234*14675a02SAndroid Build Coastguard Worker     std::vector<absl::StatusOr<TaskAssignment>> task_assignments;
235*14675a02SAndroid Build Coastguard Worker   };
236*14675a02SAndroid Build Coastguard Worker 
237*14675a02SAndroid Build Coastguard Worker   // Checks in with a federated server to get multiple task assignments.
238*14675a02SAndroid Build Coastguard Worker   //
239*14675a02SAndroid Build Coastguard Worker   // Must only be called once after the following conditions are met:
240*14675a02SAndroid Build Coastguard Worker   //
241*14675a02SAndroid Build Coastguard Worker   // - the caller previously called `EligibilityEvalCheckin()` and,
242*14675a02SAndroid Build Coastguard Worker   // - received a payload, and the returned EligibilityEvalTask's
243*14675a02SAndroid Build Coastguard Worker   // `PopulationEligibilitySpec` contained at least one task with
244*14675a02SAndroid Build Coastguard Worker   // TASK_ASSIGNMENT_MODE_MULTIPLE, for which the device is eligible.
245*14675a02SAndroid Build Coastguard Worker   //
246*14675a02SAndroid Build Coastguard Worker   //
247*14675a02SAndroid Build Coastguard Worker   // Returns:
248*14675a02SAndroid Build Coastguard Worker   // - On success, a `MultipleTaskAssignments`.
249*14675a02SAndroid Build Coastguard Worker   // - On error:
250*14675a02SAndroid Build Coastguard Worker   //   - ABORTED when one of the I/O operations got aborted by the server.
251*14675a02SAndroid Build Coastguard Worker   //   - CANCELLED when one of the I/O operations was interrupted by the client
252*14675a02SAndroid Build Coastguard Worker   //     (possibly due to a positive result from the should_abort callback).
253*14675a02SAndroid Build Coastguard Worker   //   - UNAVAILABLE when server cannot be reached or URI is invalid.
254*14675a02SAndroid Build Coastguard Worker   //   - NOT_FOUND if the server responds with NOT_FOUND, e.g. because the
255*14675a02SAndroid Build Coastguard Worker   //     specified population name is incorrect.
256*14675a02SAndroid Build Coastguard Worker   //   - UNIMPLEMENTED if an unexpected server response is received.
257*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL for other unexpected client-side errors.
258*14675a02SAndroid Build Coastguard Worker   //   - any server-provided error code.
259*14675a02SAndroid Build Coastguard Worker   virtual absl::StatusOr<MultipleTaskAssignments>
260*14675a02SAndroid Build Coastguard Worker   PerformMultipleTaskAssignments(
261*14675a02SAndroid Build Coastguard Worker       const std::vector<std::string>& task_names) = 0;
262*14675a02SAndroid Build Coastguard Worker 
263*14675a02SAndroid Build Coastguard Worker   // Reports the result of a federated computation to the server. Must only be
264*14675a02SAndroid Build Coastguard Worker   // called once and after a successful call to Checkin().
265*14675a02SAndroid Build Coastguard Worker   // @param checkpoint A checkpoint proto.
266*14675a02SAndroid Build Coastguard Worker   // @param stats all stats reported during the computation.
267*14675a02SAndroid Build Coastguard Worker   // @param plan_duration the duration for executing the plan in the plan
268*14675a02SAndroid Build Coastguard Worker   //        engine. Does not include time spent on downloading the plan.
269*14675a02SAndroid Build Coastguard Worker   // Returns:
270*14675a02SAndroid Build Coastguard Worker   // - On success, OK.
271*14675a02SAndroid Build Coastguard Worker   // - On error (e.g. an interruption, network error, or other unexpected
272*14675a02SAndroid Build Coastguard Worker   //   error):
273*14675a02SAndroid Build Coastguard Worker   //   - ABORTED when one of the I/O operations got aborted by the server.
274*14675a02SAndroid Build Coastguard Worker   //   - CANCELLED when one of the I/O operations was interrupted by the client
275*14675a02SAndroid Build Coastguard Worker   //     (possibly due to a positive result from the should_abort callback).
276*14675a02SAndroid Build Coastguard Worker   //   - UNIMPLEMENTED if the server responded with an unexpected response
277*14675a02SAndroid Build Coastguard Worker   //     message.
278*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL for other unexpected client-side errors.
279*14675a02SAndroid Build Coastguard Worker   //   - any server-provided error code.
280*14675a02SAndroid Build Coastguard Worker   virtual absl::Status ReportCompleted(
281*14675a02SAndroid Build Coastguard Worker       ComputationResults results, absl::Duration plan_duration,
282*14675a02SAndroid Build Coastguard Worker       std::optional<std::string> aggregation_session_id) = 0;
283*14675a02SAndroid Build Coastguard Worker 
284*14675a02SAndroid Build Coastguard Worker   // Reports the unsuccessful result of a federated computation to the server.
285*14675a02SAndroid Build Coastguard Worker   // Must only be called once and after a successful call to Checkin().
286*14675a02SAndroid Build Coastguard Worker   // @param phase_outcome the outcome of the federated computation.
287*14675a02SAndroid Build Coastguard Worker   // @param plan_duration the duration for executing the plan in the plan
288*14675a02SAndroid Build Coastguard Worker   //        engine. Does not include time spent on downloading the plan.
289*14675a02SAndroid Build Coastguard Worker   // Returns:
290*14675a02SAndroid Build Coastguard Worker   // - On success, OK.
291*14675a02SAndroid Build Coastguard Worker   // - On error:
292*14675a02SAndroid Build Coastguard Worker   //   - ABORTED when one of the I/O operations got aborted by the server.
293*14675a02SAndroid Build Coastguard Worker   //   - CANCELLED when one of the I/O operations was interrupted by the client
294*14675a02SAndroid Build Coastguard Worker   //     (possibly due to a positive result from the should_abort callback).
295*14675a02SAndroid Build Coastguard Worker   //   - UNIMPLEMENTED if the server responded with an unexpected response
296*14675a02SAndroid Build Coastguard Worker   //     message, or if the results to report require SecAgg support.
297*14675a02SAndroid Build Coastguard Worker   //   - INTERNAL for other unexpected client-side errors.
298*14675a02SAndroid Build Coastguard Worker   //   - any server-provided error code.
299*14675a02SAndroid Build Coastguard Worker   virtual absl::Status ReportNotCompleted(
300*14675a02SAndroid Build Coastguard Worker       engine::PhaseOutcome phase_outcome, absl::Duration plan_duration,
301*14675a02SAndroid Build Coastguard Worker       std::optional<std::string> aggregation_session_id) = 0;
302*14675a02SAndroid Build Coastguard Worker 
303*14675a02SAndroid Build Coastguard Worker   // Returns the RetryWindow the caller should use when rescheduling, based on
304*14675a02SAndroid Build Coastguard Worker   // the current protocol phase. The value returned by this method may change
305*14675a02SAndroid Build Coastguard Worker   // after every interaction with the protocol, so callers should call this
306*14675a02SAndroid Build Coastguard Worker   // right before ending their interactions with the FederatedProtocol object to
307*14675a02SAndroid Build Coastguard Worker   // ensure they use the most recent value.
308*14675a02SAndroid Build Coastguard Worker   // TODO(team): Replace this reference to protocol-specific
309*14675a02SAndroid Build Coastguard Worker   // RetryWindow proto with a protocol-agnostic struct (or just a single
310*14675a02SAndroid Build Coastguard Worker   // absl::Duration).
311*14675a02SAndroid Build Coastguard Worker   virtual google::internal::federatedml::v2::RetryWindow
312*14675a02SAndroid Build Coastguard Worker   GetLatestRetryWindow() = 0;
313*14675a02SAndroid Build Coastguard Worker 
314*14675a02SAndroid Build Coastguard Worker   // Returns the best estimate of the total bytes downloaded and uploaded over
315*14675a02SAndroid Build Coastguard Worker   // the network, plus the best estimate of the duration of wall clock time
316*14675a02SAndroid Build Coastguard Worker   // spent waiting for network requests to finish (but, for example, excluding
317*14675a02SAndroid Build Coastguard Worker   // any idle time spent waiting between issuing polling requests).
318*14675a02SAndroid Build Coastguard Worker   //
319*14675a02SAndroid Build Coastguard Worker   // Note that this estimate may still include time spent simply waiting for a
320*14675a02SAndroid Build Coastguard Worker   // server response, even if no data was being sent or received during that
321*14675a02SAndroid Build Coastguard Worker   // time. E.g. in the case of the legacy gRPC protocol where the single checkin
322*14675a02SAndroid Build Coastguard Worker   // request blocks until a task is assigned to the client.
323*14675a02SAndroid Build Coastguard Worker   //
324*14675a02SAndroid Build Coastguard Worker   // If possible, this estimate should also include time spent
325*14675a02SAndroid Build Coastguard Worker   // compressing/decompressing payloads before writing them to or after reading
326*14675a02SAndroid Build Coastguard Worker   // them from the network.
327*14675a02SAndroid Build Coastguard Worker   virtual NetworkStats GetNetworkStats() = 0;
328*14675a02SAndroid Build Coastguard Worker 
329*14675a02SAndroid Build Coastguard Worker  protected:
330*14675a02SAndroid Build Coastguard Worker   // A list of states representing the sequence of calls we expect to receive
331*14675a02SAndroid Build Coastguard Worker   // via this interface, as well as their possible outcomes. Implementations of
332*14675a02SAndroid Build Coastguard Worker   // this class are likely to share these coarse-grained states, and use them to
333*14675a02SAndroid Build Coastguard Worker   // determine which values to return from `GetLatestRetryWindow()`.
334*14675a02SAndroid Build Coastguard Worker   enum class ObjectState {
335*14675a02SAndroid Build Coastguard Worker     // The initial object state.
336*14675a02SAndroid Build Coastguard Worker     kInitialized,
337*14675a02SAndroid Build Coastguard Worker     // EligibilityEvalCheckin() was called but it failed with a 'transient'
338*14675a02SAndroid Build Coastguard Worker     // error (e.g. an UNAVAILABLE network error, although the set of transient
339*14675a02SAndroid Build Coastguard Worker     // errors is flag-defined).
340*14675a02SAndroid Build Coastguard Worker     kEligibilityEvalCheckinFailed,
341*14675a02SAndroid Build Coastguard Worker     // EligibilityEvalCheckin() was called but it failed with a 'permanent'
342*14675a02SAndroid Build Coastguard Worker     // error (e.g. a NOT_FOUND network error, although the set of permanent
343*14675a02SAndroid Build Coastguard Worker     // errors is flag-defined).
344*14675a02SAndroid Build Coastguard Worker     kEligibilityEvalCheckinFailedPermanentError,
345*14675a02SAndroid Build Coastguard Worker     // EligibilityEvalCheckin() was called, and the server rejected the client.
346*14675a02SAndroid Build Coastguard Worker     kEligibilityEvalCheckinRejected,
347*14675a02SAndroid Build Coastguard Worker     // EligibilityEvalCheckin() was called, and the server did not return an
348*14675a02SAndroid Build Coastguard Worker     // eligibility eval payload.
349*14675a02SAndroid Build Coastguard Worker     kEligibilityEvalDisabled,
350*14675a02SAndroid Build Coastguard Worker     // EligibilityEvalCheckin() was called, and the server did return an
351*14675a02SAndroid Build Coastguard Worker     // eligibility eval payload, which must then be run to produce a
352*14675a02SAndroid Build Coastguard Worker     // TaskEligibilityInfo value.
353*14675a02SAndroid Build Coastguard Worker     kEligibilityEvalEnabled,
354*14675a02SAndroid Build Coastguard Worker     // Checkin(...) was called but it failed with a 'transient' error.
355*14675a02SAndroid Build Coastguard Worker     kCheckinFailed,
356*14675a02SAndroid Build Coastguard Worker     // Checkin(...) was called but it failed with a 'permanent' error.
357*14675a02SAndroid Build Coastguard Worker     kCheckinFailedPermanentError,
358*14675a02SAndroid Build Coastguard Worker     // Checkin(...) was called, and the server rejected the client.
359*14675a02SAndroid Build Coastguard Worker     kCheckinRejected,
360*14675a02SAndroid Build Coastguard Worker     // Checkin(...) was called, and the server accepted the client and returned
361*14675a02SAndroid Build Coastguard Worker     // a payload, which must then be run to produce a report.
362*14675a02SAndroid Build Coastguard Worker     kCheckinAccepted,
363*14675a02SAndroid Build Coastguard Worker     // PerformMultipleTaskAssignments(...) was called but it failed with a
364*14675a02SAndroid Build Coastguard Worker     // 'transient' error, without receiving a single task assignment. If some
365*14675a02SAndroid Build Coastguard Worker     // task assignments were successfully received, but some others failed (e.g.
366*14675a02SAndroid Build Coastguard Worker     // because their resources failed to be downloaded), then this state won't
367*14675a02SAndroid Build Coastguard Worker     // be used.
368*14675a02SAndroid Build Coastguard Worker     kMultipleTaskAssignmentsFailed,
369*14675a02SAndroid Build Coastguard Worker     // PerformMultipleTaskAssignments(...) was called but it failed with a
370*14675a02SAndroid Build Coastguard Worker     // 'permanent' error.
371*14675a02SAndroid Build Coastguard Worker     kMultipleTaskAssignmentsFailedPermanentError,
372*14675a02SAndroid Build Coastguard Worker     // PerformMultipleTaskAssignments(...) was called but an empty list of tasks
373*14675a02SAndroid Build Coastguard Worker     // is returned by the server.
374*14675a02SAndroid Build Coastguard Worker     kMultipleTaskAssignmentsNoAvailableTask,
375*14675a02SAndroid Build Coastguard Worker     // PerformMultipleTaskAssignments(...) was called, and the server accepted
376*14675a02SAndroid Build Coastguard Worker     // the client and returned one or more payload, which must then be run to
377*14675a02SAndroid Build Coastguard Worker     // produce a report.
378*14675a02SAndroid Build Coastguard Worker     kMultipleTaskAssignmentsAccepted,
379*14675a02SAndroid Build Coastguard Worker     // Report(...) was called.
380*14675a02SAndroid Build Coastguard Worker     kReportCalled,
381*14675a02SAndroid Build Coastguard Worker     // Report(...) was called and it resulted in a 'permanent' error.
382*14675a02SAndroid Build Coastguard Worker     //
383*14675a02SAndroid Build Coastguard Worker     // Note: there is no kReportFailed (corresponding to 'transient' errors,
384*14675a02SAndroid Build Coastguard Worker     // like the other phases have), because by the time the report phase is
385*14675a02SAndroid Build Coastguard Worker     // reached, a set of RetryWindows is guaranteed to have been received from
386*14675a02SAndroid Build Coastguard Worker     // the server.
387*14675a02SAndroid Build Coastguard Worker     kReportFailedPermanentError,
388*14675a02SAndroid Build Coastguard Worker     // Report(...) was called for multiple tasks, and only a subset of the tasks
389*14675a02SAndroid Build Coastguard Worker     // succeed.
390*14675a02SAndroid Build Coastguard Worker     kReportMultipleTaskPartialError,
391*14675a02SAndroid Build Coastguard Worker   };
392*14675a02SAndroid Build Coastguard Worker };
393*14675a02SAndroid Build Coastguard Worker 
394*14675a02SAndroid Build Coastguard Worker }  // namespace client
395*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
396*14675a02SAndroid Build Coastguard Worker 
397*14675a02SAndroid Build Coastguard Worker #endif  // FCP_CLIENT_FEDERATED_PROTOCOL_H_
398