1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
// 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_UTIL_WRAPPED_RATE_LIMITER_H_
#define COMPONENTS_REPORTING_UTIL_WRAPPED_RATE_LIMITER_H_
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "components/reporting/util/rate_limiter_interface.h"
namespace reporting {
// This class wraps around rate limiter instance to ensure the latter
// is used sequentially. It is instantiated by calling
// `WrappedRateLimiter::Create`.
//
// The usage snippet in an owner class:
//
// class RateLimitedEventSender {
// public:
// explicit RateLimitedEventSender(
// std::unique_ptr<RateLimiterInterface> rate_limiter)
// : wrapped_rate_limiter_(
// WrappedRateLimiter::Create(std::move(rate_limiter))),
// async_acquire_cb_(wrapped_rate_limiter_->async_acquire_cb()) {}
//
// void SendEvent(Event event, EnqueueCallback cb) {
// const size_t event_size = event.ByteSizeLong();
// async_acquire_cb_.Run(
// event_size,
// base::BindOnce([](Event event, EnqueueCallback cb, bool acquired) {
// if (!acquired) {
// std::move(cb).Run(Status{error::OUT_OF_RANGE, "..."});
// return;
// }
// ... // Actually enqueue `event`, using `cb` to return outcome.
// }, std::move(event), std::move(cb));
// }
//
// private:
// WrappedRateLimiter::SmartPtr wrapped_rate_limiter_;
// AsyncAcquireCb async_acquire_cb_;
// };
//
class WrappedRateLimiter {
public:
using SmartPtr =
std::unique_ptr<WrappedRateLimiter, base::OnTaskRunnerDeleter>;
using AsyncAcquireCb =
base::RepeatingCallback<void(size_t /*event_size*/,
base::OnceCallback<void(bool)> /*cb*/)>;
// Events rate limiting UMA metric name.
static constexpr char kRateLimitedEventsUma[] =
"Browser.ERP.RateLimitedEvents";
// Creates wrapped rate limiter that ensures sequenced access to `Acquire`.
static SmartPtr Create(std::unique_ptr<RateLimiterInterface> rate_limiter);
WrappedRateLimiter(const WrappedRateLimiter&) = delete;
WrappedRateLimiter& operator=(const WrappedRateLimiter&) = delete;
~WrappedRateLimiter();
// Returns `AsyncAcquireCb` callback that invokes `Acquire` on
// `sequenced_task_runner_` and then passes the result to `cb` on the current
// task runner.
AsyncAcquireCb async_acquire_cb() const;
private:
// Constructor can only be called by `Create` factory method above.
WrappedRateLimiter(
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner,
std::unique_ptr<RateLimiterInterface> rate_limiter);
// Helper method, forwards `Acquire` call to owned rate limiter, if wrapper is
// still valid, otherwise returns `false`. Must be called on
// `sequence_task_runner_`.
static bool Acquire(base::WeakPtr<WrappedRateLimiter> self,
size_t event_size);
// Helper method, calls `Acquire` on `sequenced_task_runner_` and then passes
// the result to `cb` on the current task runner, if wrapper is still valid,
// otherwise calls `cb` with `false`.
static void AsyncAcquire(base::WeakPtr<WrappedRateLimiter> self,
size_t event_size,
base::OnceCallback<void(bool)> cb);
const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
// Wrapped rate limiter instance.
const std::unique_ptr<RateLimiterInterface> rate_limiter_;
// AsyncAcquireCb callback. Set once only, by constructor.
AsyncAcquireCb async_acquire_cb_;
// Weak ptr factory.
base::WeakPtrFactory<WrappedRateLimiter> weak_ptr_factory_{this};
};
} // namespace reporting
#endif // COMPONENTS_REPORTING_UTIL_WRAPPED_RATE_LIMITER_H_
|