19#include <unordered_map>
58 std::string_view session, std::uint64_t start_sequence, std::uint64_t count
76 void(std::string_view session, std::uint64_t expected, std::uint64_t received)>;
86 auto observe(std::string_view session, std::uint64_t first_sequence, std::uint64_t count)
88 const std::string key {session};
89 auto iter = m_expected_by_session.find(key);
90 if (iter == m_expected_by_session.end()) {
92 m_expected_by_session.emplace(key, first_sequence + count);
93 m_messages_seen += count;
97 std::uint64_t& expected = iter->second;
98 std::uint64_t gap = 0;
99 if (first_sequence > expected) {
100 gap = first_sequence - expected;
102 if (m_gap_callback) {
103 m_gap_callback(session, expected, first_sequence);
105 if (m_requester !=
nullptr) {
106 m_requester->request_retransmit(session, expected, gap);
110 const std::uint64_t end_sequence = first_sequence + count;
111 if (end_sequence > expected) {
113 const std::uint64_t already_seen =
114 expected > first_sequence ? expected - first_sequence : 0;
115 m_messages_seen += count - std::min(count, already_seen);
116 expected = end_sequence;
129 m_requester = requester;
137 )
const -> std::optional<std::uint64_t> {
138 const auto iter = m_expected_by_session.find(std::string {session});
139 if (iter == m_expected_by_session.end()) {
147 [[nodiscard]]
auto gap_count() const noexcept -> std::uint64_t {
return m_gap_count; }
151 [[nodiscard]]
auto messages_seen() const noexcept -> std::uint64_t {
return m_messages_seen; }
155 m_expected_by_session.clear();
161 std::unordered_map<std::string, std::uint64_t> m_expected_by_session {};
162 GapCallback m_gap_callback {};
164 std::uint64_t m_gap_count {0};
165 std::uint64_t m_messages_seen {0};
Abstract hook a caller implements to drive recovery against a replay or retransmission service when a...
RetransmitRequester(RetransmitRequester &&) noexcept=default
Move-constructs a requester.
RetransmitRequester(const RetransmitRequester &)=default
Copy-constructs a requester.
virtual auto request_retransmit(std::string_view session, std::uint64_t start_sequence, std::uint64_t count) -> void=0
Requests retransmission of count messages starting at sequence start_sequence for the given session.
RetransmitRequester()=default
Constructs a requester with no state.
Tracks per-session sequence numbers across a transport layer and surfaces gaps.
auto gap_count() const noexcept -> std::uint64_t
Total number of missing messages detected across all sessions.
auto reset() -> void
Forgets all per-session state and resets the counters.
std::function< void(std::string_view session, std::uint64_t expected, std::uint64_t received)> GapCallback
Invoked once per detected gap with the session, the sequence the tracker expected,...
auto observe(std::string_view session, std::uint64_t first_sequence, std::uint64_t count) -> std::uint64_t
Records that a packet beginning at first_sequence carried count sequenced messages for session.
auto expected_next(std::string_view session) const -> std::optional< std::uint64_t >
The next sequence number expected for a session, if it has been seen.
auto set_retransmit_requester(RetransmitRequester *requester) noexcept -> void
Installs a non-owning retransmission hook (nullptr clears it).
auto set_gap_callback(GapCallback callback) -> void
Installs the gap-notification callback (empty clears it).
auto messages_seen() const noexcept -> std::uint64_t
Total number of distinct sequenced messages observed.