// Copyright 2021 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_H_ #define COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_H_ #include <memory> #include <queue> #include <string> #include <utility> #include "base/functional/callback.h" #include "base/values.h" #include "components/reporting/proto/synced/record.pb.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/reporting/storage/storage_uploader_interface.h" #include "components/reporting/util/status.h" #include "components/reporting/util/statusor.h" #include "third_party/protobuf/src/google/protobuf/message_lite.h" namespace reporting { // A |ReportQueue| is not meant to be created directly, instead it is // instantiated by |ReportQueueProvider|. |ReportQueue| allows a user // to |Enqueue| a message for delivery to a handler specified by the // |Destination| held by the provided |ReportQueueConfiguration|. // |ReportQueue| implementation handles scheduling storage and // delivery. // Enqueue can also be used with a |base::Value| or |std::string|. // // Example Usage: // void SendMessage(google::protobuf::ImportantMessage important_message, // reporting::ReportQueue::EnqueueCallback done_cb) { // // Create configuration. // StatusOr<reporting::ReportQueueConfiguration> config_result = // reporting::ReportQueueConfiguration::Create({...}).Set...().Build(); // // Bail out if configuration failed to create. // if (!config_result.has_value()) { // std::move(done_cb).Run(config_result.error()); // return; // } // // Asynchronously instantiate ReportQueue. // base::ThreadPool::PostTask( // FROM_HERE, // base::BindOnce( // [](google::protobuf::ImportantMessage important_message, // reporting::ReportQueue::EnqueueCallback done_cb, // std::unique_ptr<reporting::ReportQueueConfiguration> config) { // reporting::ReportQueueProvider::CreateQueue( // std::move(config), // base::BindOnce( // [](google::protobuf::ImportantMessage important_message, // reporting::ReportQueue::EnqueueCallback done_cb, // reporting::StatusOr<std::unique_ptr< // reporting::ReportQueue>> report_queue_result) { // // Bail out if queue failed to create. // if (!report_queue_result.has_value()) { // std::move(done_cb).Run(report_queue_result.error()); // return; // } // // Queue created successfully, enqueue the message. // report_queue_result.value()->Enqueue( // std::move(important_message), std::move(done_cb)); // }, // std::move(important_message), std::move(done_cb))); // }, // std::move(important_message), std::move(done_cb), // std::move(config_result.value()))); // } // // |SpeculativeReportQueueImpl| is an extension to |ReportQueue| which allows // to speculatively enqueue records before the actual |ReportQueue| is created // (which may be delayed by inability to initialize |ReportClient|). // Instantiated by |ReportQueueProvider| and can be used anywhere |ReportQueue| // fits. Note however, that records enqueued before actual |ReportQueue| // is ready may be lost, e.g. if the machine reboots, so for the records // that need to be definiately recorded |ReportQueue| is preferable. // // Example Usage: // void SendMessage(google::protobuf::LessImportantMessage // less_important_message, // reporting::ReportQueue::EnqueueCallback done_cb) { // // Create configuration. // StatusOr<reporting::ReportQueueConfiguration> config_result = // reporting::ReportQueueConfiguration::Create({...}).Set...().Build(); // // Bail out if configuration failed to create. // if (!config_result.has_value()) { // std::move(done_cb).Run(config_result.error()); // return; // } // // Synchronously instantiate SpeculativeReportQueueImpl, returning it as // // ReportQueue still. // auto report_queue_result = // reporting::ReportQueueProvider::CreateSpeculativeQueue( // std::move(config)); // if (!report_queue_result.has_value()) { // std::move(done_cb).Run(config_result.error()); // return; // } // // Enqueue event (store it in memory only until the actual queue is // // created). // report_queue_result.value()->Enqueue( // std::move(less_important_message), std::move(done_cb)); // } class ReportQueue { … }; } // namespace reporting #endif // COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_H_