chromium/components/reporting/client/filtered_report_queue.h

// Copyright 2023 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_FILTERED_REPORT_QUEUE_H_
#define COMPONENTS_REPORTING_CLIENT_FILTERED_REPORT_QUEUE_H_

#include <memory>
#include <queue>
#include <string>
#include <type_traits>
#include <utility>

#include "base/metrics/histogram_functions.h"
#include "base/values.h"
#include "components/reporting/client/report_queue.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/reporting/util/status.h"
#include "third_party/protobuf/src/google/protobuf/message_lite.h"

namespace reporting {

namespace internal {
// A concept that determines whether a type U is implicitly convertible from a
// type V.
IsImplicitlyConstructible;
}  // namespace internal

// `FilteredReportQueue` is a wrapper template using actual `ReportQueue`
// instance. It will make a call to a provided filtering interface `Filter`
// whenever `Enqueue` API is called.
// As opposed to `ReportQueue`, filtering only accepts one form of `Enqueue` -
// string, dictionary or proto - others would not compile. And since the
// filtering is called before the event is serialized, it can be analyzed or
// deduplicated in its original form, without the need to deserialize it back.
//
// Usage sketch (note that Filter thread-safety is expected to be ensured by the
// caller code here):
//
// proto EventMessage { optional string tag; optional string data; }
//
// class EventFilter : public FilteredReportQueue<EventMessage>::Filter {
//  private:
//   Status is_accepted(const EventMessage& new_event) override {
//     if (!last_event_tag_.empty() && new_event.tag() == last_event_tag_) {
//       return Status(error::ALREADY_EXISTS, "Duplicated event");
//     }
//     last_event_tag_ = new_event.tag();
//     return Status::StatusOK();
//   }
//
//   std::string last_event_tag_;
// };
//
// auto filtered_queue = std::make_unique<FilteredReportQueue<EventMessage>>(
//     std::make_unique<EventFilter>(filter),
//     std::move(actual_report_queue));
//
// ...
//
// EventMessage event;
// event.set_tag(...);
// event.set_data(...);
// filtered_queue->Enqueue(std::move(event), priority, callback);
//
// The event will only be posted, if its tag differs from the tag in the last
// message before it.
//
template <typename T>
class FilteredReportQueue {};

}  // namespace reporting

#endif  // COMPONENTS_REPORTING_CLIENT_FILTERED_REPORT_QUEUE_H_