| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #pragma once |
| |
| #include <cstddef> |
| /** |
| * @file iggy.hpp |
| * @brief Public C++ API for the Apache Iggy client. |
| */ |
| |
| #include <chrono> |
| #include <cstdint> |
| #include <limits> |
| #include <map> |
| #include <optional> |
| #include <stdexcept> |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| #include <variant> |
| #include <vector> |
| |
| #if defined(__GNUC__) |
| # pragma GCC diagnostic push |
| # pragma GCC diagnostic ignored "-Wpedantic" |
| #endif |
| #include "absl/numeric/int128.h" |
| #if defined(__GNUC__) |
| # pragma GCC diagnostic pop |
| #endif |
| |
| #include "lib.rs.h" |
| |
| namespace iggy { |
| |
| class Consumer; |
| class ConsumerOffsetInfo; |
| class ClientInfo; |
| class ClientInfoDetails; |
| class CacheMetricEntry; |
| class Stats; |
| class ConsumerGroupInfo; |
| class IggyBlockingClient; |
| class LoginInfo; |
| class Partition; |
| class Topic; |
| class TopicDetails; |
| class Stream; |
| class StreamDetails; |
| class GlobalPermissions; |
| class Permissions; |
| class StreamPermissions; |
| class TopicPermissions; |
| class UserInfo; |
| class UserInfoDetails; |
| class ConsumerGroup; |
| class ConsumerGroupDetails; |
| class ConsumerGroupMember; |
| class IggyMessagePolled; |
| class IggyMessageToSend; |
| |
| namespace detail { |
| /** @brief Internal base for string-backed option types. */ |
| template <typename Tag> |
| class StringTag { |
| protected: |
| explicit StringTag(std::string value) : value_(std::move(value)) {} |
| ~StringTag() = default; |
| StringTag(const StringTag &) = default; |
| StringTag(StringTag &&) = default; |
| StringTag &operator=(const StringTag &) = default; |
| StringTag &operator=(StringTag &&) = default; |
| |
| [[nodiscard]] std::string_view Value() const { return value_; } |
| |
| private: |
| std::string value_; |
| }; |
| |
| } // namespace detail |
| |
| /** |
| * @brief Exception thrown when an Iggy client operation fails. |
| */ |
| class IggyException : public std::runtime_error { |
| public: |
| /** |
| * @brief Creates an Iggy exception from a null-terminated message. |
| * @param message Error description. |
| */ |
| explicit IggyException(const char *message) : std::runtime_error(message) {} |
| |
| /** |
| * @brief Creates an Iggy exception from an owning string. |
| * @param message Error description. |
| */ |
| explicit IggyException(const std::string &message) : std::runtime_error(message) {} |
| }; |
| |
| /** |
| * @brief Details returned after a successful login. |
| * |
| * Contains the authenticated user's ID. For HTTP connections, it also includes |
| * the access token retained by the client for subsequent requests. Stateful |
| * transports do not provide an access token. Treat the token as a credential: |
| * do not write it to logs or expose it to untrusted code. |
| */ |
| class LoginInfo final { |
| public: |
| /** |
| * @brief Returns the numeric ID of the authenticated user. |
| * @return Numeric user ID. |
| */ |
| [[nodiscard]] std::uint32_t UserId() const noexcept { return user_id_; } |
| |
| /** |
| * @brief Returns the HTTP access token when the login returned one. |
| * @return Reference to the owning optional token. Empty when the selected |
| * transport does not use an access token. |
| */ |
| [[nodiscard]] const std::optional<std::string> &AccessToken() const noexcept { return access_token_; } |
| |
| /** |
| * @brief Returns the access-token expiry when a token was returned. |
| * @return Empty when no access token was returned; otherwise the |
| * server-provided expiry value. |
| */ |
| [[nodiscard]] std::optional<std::uint64_t> AccessTokenExpiry() const noexcept { return access_token_expiry_; } |
| |
| private: |
| LoginInfo(std::uint32_t user_id, |
| std::optional<std::string> access_token, |
| std::optional<std::uint64_t> access_token_expiry) |
| : user_id_(user_id), access_token_(std::move(access_token)), access_token_expiry_(access_token_expiry) {} |
| |
| static LoginInfo FromFfi(ffi::LoginInfo login_info); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t user_id_; |
| std::optional<std::string> access_token_; |
| std::optional<std::uint64_t> access_token_expiry_; |
| }; |
| |
| /** |
| * @brief Identifier for a server resource. |
| * |
| * Create an identifier from a server-assigned numeric ID or a resource name. |
| * Resource names must contain between 1 and 255 bytes. A numeric ID of zero is |
| * valid. |
| */ |
| class Identifier final { |
| public: |
| /** @brief Maximum encoded length of a name-based identifier. */ |
| static constexpr std::size_t kMaxIdentifierLength = 255; |
| |
| /** @brief Selects the representation stored by an Identifier. */ |
| enum class Kind : std::uint8_t { Numeric, String }; |
| |
| /** |
| * @brief Creates a numeric identifier. |
| * @param id Numeric server ID. |
| * @return Identifier that addresses @p id. |
| */ |
| static Identifier Numeric(std::uint32_t id) { return Identifier(Kind::Numeric, id); } |
| |
| /** |
| * @brief Creates a name-based identifier. |
| * @param name Resource name. |
| * @return Identifier that addresses @p name. |
| * @throws IggyException if @p name is empty or exceeds 255 bytes. |
| */ |
| static Identifier String(std::string name) { |
| if (name.empty() || name.size() > kMaxIdentifierLength) { |
| throw IggyException("Identifier name must contain 1 to 255 bytes"); |
| } |
| return Identifier(Kind::String, std::move(name)); |
| } |
| |
| /** |
| * @brief Returns this identifier's representation. |
| * @return Kind::Numeric or Kind::String. |
| */ |
| [[nodiscard]] Kind Type() const noexcept { return kind_; } |
| |
| /** |
| * @brief Returns the identifier payload. |
| * @return Reference to the owning payload containing the numeric ID for |
| * Kind::Numeric or the name for Kind::String. The reference |
| * remains valid while this Identifier remains alive. |
| */ |
| [[nodiscard]] const std::variant<std::uint32_t, std::string> &Value() const noexcept { return value_; } |
| |
| private: |
| Identifier(Kind kind, std::variant<std::uint32_t, std::string> value) : kind_(kind), value_(std::move(value)) {} |
| |
| [[nodiscard]] ffi::Identifier ToFfi() const; |
| |
| friend class IggyBlockingClient; |
| |
| Kind kind_; |
| std::variant<std::uint32_t, std::string> value_; |
| }; |
| |
| /** |
| * @brief Controls whether a user may authenticate. |
| */ |
| enum class UserStatus : std::uint8_t { |
| Active = 1, ///< The user may authenticate. |
| Inactive = 2, ///< Authentication for the user is rejected. |
| }; |
| |
| /** |
| * @brief Cluster-wide permissions assigned to a user. |
| * |
| * Global grants apply without naming individual streams or topics. Management |
| * grants include the corresponding read grants. Stream and topic grants form a |
| * hierarchy: managing streams includes managing topics, reading streams |
| * includes reading topics, and reading topics includes polling messages and |
| * managing consumer groups. Managing streams or topics also authorizes sending |
| * messages; SendMessages() can grant sending without management permission. |
| * |
| * A default-constructed value has every flag disabled. The setters record the |
| * supplied flags without expanding implied grants; the server applies the |
| * hierarchy when authorizing a request. |
| */ |
| class GlobalPermissions final { |
| public: |
| /** |
| * @brief Returns the configured cluster-management flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageServers() const noexcept { return manage_servers_; } |
| |
| /** |
| * @brief Returns the configured server-information read flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadServers() const noexcept { return read_servers_; } |
| |
| /** |
| * @brief Returns the configured user-management flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageUsers() const noexcept { return manage_users_; } |
| |
| /** |
| * @brief Returns the configured user-information read flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadUsers() const noexcept { return read_users_; } |
| |
| /** |
| * @brief Returns the configured all-stream management flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageStreams() const noexcept { return manage_streams_; } |
| |
| /** |
| * @brief Returns the configured all-stream read flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadStreams() const noexcept { return read_streams_; } |
| |
| /** |
| * @brief Returns the configured all-topic management flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageTopics() const noexcept { return manage_topics_; } |
| |
| /** |
| * @brief Returns the configured all-topic read flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadTopics() const noexcept { return read_topics_; } |
| |
| /** |
| * @brief Returns the configured all-topic message-polling flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool PollMessages() const noexcept { return poll_messages_; } |
| |
| /** |
| * @brief Returns the configured all-topic message-sending flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool SendMessages() const noexcept { return send_messages_; } |
| |
| /** |
| * @brief Enables or disables cluster-management permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetManageServers(bool enabled) { |
| manage_servers_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables permission to read server information. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetReadServers(bool enabled) { |
| read_servers_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables user-management permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetManageUsers(bool enabled) { |
| manage_users_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables permission to read user information. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetReadUsers(bool enabled) { |
| read_users_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables management permission for every stream. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetManageStreams(bool enabled) { |
| manage_streams_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables read permission for every stream. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetReadStreams(bool enabled) { |
| read_streams_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables management permission for every topic. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetManageTopics(bool enabled) { |
| manage_topics_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables read permission for every topic. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetReadTopics(bool enabled) { |
| read_topics_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables polling permission for every topic. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetPollMessages(bool enabled) { |
| poll_messages_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables sending permission for every topic. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| GlobalPermissions &SetSendMessages(bool enabled) { |
| send_messages_ = enabled; |
| return *this; |
| } |
| |
| private: |
| [[nodiscard]] ffi::GlobalPermissions ToFfi() const; |
| static GlobalPermissions FromFfi(ffi::GlobalPermissions permissions); |
| |
| friend class Permissions; |
| |
| bool manage_servers_{}; |
| bool read_servers_{}; |
| bool manage_users_{}; |
| bool read_users_{}; |
| bool manage_streams_{}; |
| bool read_streams_{}; |
| bool manage_topics_{}; |
| bool read_topics_{}; |
| bool poll_messages_{}; |
| bool send_messages_{}; |
| }; |
| |
| /** |
| * @brief Permissions extending a user's access to one topic. |
| * |
| * These flags grant access in addition to enclosing stream and global grants; |
| * a disabled flag does not revoke access granted at a broader scope. Managing |
| * a topic includes reading it. Reading a topic includes polling messages and |
| * managing its consumer groups. Managing a topic also authorizes sending; |
| * SetSendMessages() can grant sending without management permission. |
| * |
| * A default-constructed value has every flag disabled. |
| */ |
| class TopicPermissions final { |
| public: |
| /** |
| * @brief Returns the configured topic-management flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageTopic() const noexcept { return manage_topic_; } |
| |
| /** |
| * @brief Returns the configured topic-read flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadTopic() const noexcept { return read_topic_; } |
| |
| /** |
| * @brief Returns the configured message-polling flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool PollMessages() const noexcept { return poll_messages_; } |
| |
| /** |
| * @brief Returns the configured message-sending flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool SendMessages() const noexcept { return send_messages_; } |
| |
| /** |
| * @brief Enables or disables topic-management permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| TopicPermissions &SetManageTopic(bool enabled) { |
| manage_topic_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables topic-read permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| TopicPermissions &SetReadTopic(bool enabled) { |
| read_topic_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables message-polling permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| TopicPermissions &SetPollMessages(bool enabled) { |
| poll_messages_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables message-sending permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| TopicPermissions &SetSendMessages(bool enabled) { |
| send_messages_ = enabled; |
| return *this; |
| } |
| |
| private: |
| [[nodiscard]] ffi::TopicPermissions ToFfi() const; |
| static TopicPermissions FromFfi(ffi::TopicPermissions permissions); |
| |
| friend class StreamPermissions; |
| |
| bool manage_topic_{}; |
| bool read_topic_{}; |
| bool poll_messages_{}; |
| bool send_messages_{}; |
| }; |
| |
| /** |
| * @brief Permissions extending a user's access to one stream. |
| * |
| * Stream grants apply to the stream identified by the containing Permissions |
| * map. Topic-specific grants are keyed by numeric topic ID. These flags extend |
| * broader grants and cannot revoke permissions granted globally. Managing a |
| * stream includes reading it and managing its topics; reading a stream includes |
| * reading its topics. Managing a stream or its topics also authorizes sending; |
| * SetSendMessages() can grant sending without management permission. |
| * |
| * A default-constructed value has every flag disabled and no topic entries. |
| */ |
| class StreamPermissions final { |
| public: |
| /** |
| * @brief Returns the configured stream-management flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageStream() const noexcept { return manage_stream_; } |
| |
| /** |
| * @brief Returns the configured stream-read flag. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadStream() const noexcept { return read_stream_; } |
| |
| /** |
| * @brief Returns the configured management flag for all stream topics. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ManageTopics() const noexcept { return manage_topics_; } |
| |
| /** |
| * @brief Returns the configured read flag for all stream topics. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool ReadTopics() const noexcept { return read_topics_; } |
| |
| /** |
| * @brief Returns the configured polling flag for all stream topics. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool PollMessages() const noexcept { return poll_messages_; } |
| |
| /** |
| * @brief Returns the configured sending flag for all stream topics. |
| * @return Configured flag value. |
| */ |
| [[nodiscard]] bool SendMessages() const noexcept { return send_messages_; } |
| |
| /** |
| * @brief Returns topic-specific grants keyed by numeric topic ID. |
| * @return Map owned by this value. |
| */ |
| [[nodiscard]] const std::map<std::uint32_t, TopicPermissions> &Topics() const noexcept { return topics_; } |
| |
| /** |
| * @brief Enables or disables stream-management permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetManageStream(bool enabled) { |
| manage_stream_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables stream-read permission. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetReadStream(bool enabled) { |
| read_stream_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables management permission for all stream topics. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetManageTopics(bool enabled) { |
| manage_topics_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables read permission for all stream topics. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetReadTopics(bool enabled) { |
| read_topics_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables polling permission for all stream topics. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetPollMessages(bool enabled) { |
| poll_messages_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Enables or disables sending permission for all stream topics. |
| * @param enabled Requested flag value. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetSendMessages(bool enabled) { |
| send_messages_ = enabled; |
| return *this; |
| } |
| |
| /** |
| * @brief Replaces the topic-specific permission map. |
| * @param topics Grants keyed by numeric topic ID. |
| * @return Reference to this permissions object. |
| */ |
| StreamPermissions &SetTopics(std::map<std::uint32_t, TopicPermissions> topics) { |
| topics_ = std::move(topics); |
| return *this; |
| } |
| |
| private: |
| [[nodiscard]] ffi::StreamPermissions ToFfi() const; |
| static StreamPermissions FromFfi(ffi::StreamPermissions permissions); |
| |
| friend class Permissions; |
| |
| bool manage_stream_{}; |
| bool read_stream_{}; |
| bool manage_topics_{}; |
| bool read_topics_{}; |
| bool poll_messages_{}; |
| bool send_messages_{}; |
| std::map<std::uint32_t, TopicPermissions> topics_; |
| }; |
| |
| /** |
| * @brief Complete permission assignment for a user. |
| * |
| * Global permissions apply cluster-wide. Stream entries are keyed by numeric |
| * stream ID and add narrower grants, including optional topic-specific grants. |
| * Narrower scopes extend broader scopes and do not deny an inherited grant. |
| * |
| * A default-constructed value contains no grants. Passing such a value to |
| * CreateUser() assigns an explicit but empty permission set; passing |
| * `std::nullopt` assigns no permission object. |
| */ |
| class Permissions final { |
| public: |
| /** |
| * @brief Returns the cluster-wide grants. |
| * @return Global permissions owned by this value. |
| */ |
| [[nodiscard]] const GlobalPermissions &Global() const noexcept { return global_; } |
| |
| /** |
| * @brief Returns stream-specific grants keyed by numeric stream ID. |
| * @return Map owned by this value. |
| */ |
| [[nodiscard]] const std::map<std::uint32_t, StreamPermissions> &Streams() const noexcept { return streams_; } |
| |
| /** |
| * @brief Replaces the cluster-wide grants. |
| * @param global New global permissions. |
| * @return Reference to this permissions object. |
| */ |
| Permissions &SetGlobal(GlobalPermissions global) { |
| global_ = global; |
| return *this; |
| } |
| |
| /** |
| * @brief Replaces the stream-specific grants. |
| * @param streams Grants keyed by numeric stream ID. |
| * @return Reference to this permissions object. |
| */ |
| Permissions &SetStreams(std::map<std::uint32_t, StreamPermissions> streams) { |
| streams_ = std::move(streams); |
| return *this; |
| } |
| |
| private: |
| [[nodiscard]] ffi::Permissions ToFfi() const; |
| static Permissions FromFfi(ffi::Permissions permissions); |
| |
| friend class IggyBlockingClient; |
| friend class UserInfoDetails; |
| |
| GlobalPermissions global_; |
| std::map<std::uint32_t, StreamPermissions> streams_; |
| }; |
| |
| /** |
| * @brief Identifies the owner of a stored consumer offset. |
| * |
| * A consumer offset belongs either to an individual consumer or to a consumer |
| * group. Create a value with Single() or Group(), then pass it to the consumer |
| * offset operations on IggyBlockingClient. |
| */ |
| class Consumer final { |
| public: |
| /** @brief Selects an individual consumer or consumer-group identity. */ |
| enum class Kind : std::uint8_t { Single, Group }; |
| |
| /** |
| * @brief Identifies an individual consumer. |
| * @param id Consumer ID or name. |
| * @return Individual consumer identity. |
| */ |
| static Consumer Single(Identifier id) { return Consumer(Kind::Single, std::move(id)); } |
| |
| /** |
| * @brief Identifies a consumer group. |
| * @param id Consumer group ID or name. |
| * @return Consumer group identity. |
| */ |
| static Consumer Group(Identifier id) { return Consumer(Kind::Group, std::move(id)); } |
| |
| /** |
| * @brief Returns the kind of consumer represented by this value. |
| * @return Kind::Single for an individual consumer or Kind::Group for a |
| * consumer group. |
| */ |
| [[nodiscard]] Kind Type() const noexcept { return kind_; } |
| |
| /** |
| * @brief Returns the consumer or consumer group identifier. |
| * @return Identifier owned by this value. The reference remains valid while |
| * this Consumer remains alive. |
| */ |
| [[nodiscard]] const Identifier &Id() const noexcept { return id_; } |
| |
| private: |
| Consumer(Kind kind, Identifier id) : kind_(kind), id_(std::move(id)) {} |
| |
| [[nodiscard]] std::string_view KindName() const noexcept { |
| return kind_ == Kind::Single ? "consumer" : "consumer_group"; |
| } |
| |
| friend class IggyBlockingClient; |
| |
| Kind kind_; |
| Identifier id_; |
| }; |
| |
| /** |
| * @brief Snapshot of a consumer offset and its partition state. |
| * |
| * GetConsumerOffset() returns this value for an individual consumer or a |
| * consumer group. The partition's current offset can advance immediately after |
| * the request completes, while the stored offset changes only when explicitly |
| * stored or deleted. |
| */ |
| class ConsumerOffsetInfo final { |
| public: |
| /** |
| * @brief Returns the partition associated with the stored offset. |
| * @return Numeric partition ID. |
| */ |
| [[nodiscard]] std::uint32_t PartitionId() const noexcept { return partition_id_; } |
| |
| /** |
| * @brief Returns the partition's current message offset. |
| * @return Current message offset observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint64_t CurrentOffset() const noexcept { return current_offset_; } |
| |
| /** |
| * @brief Returns the offset stored for the consumer identity. |
| * @return Stored consumer offset observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint64_t StoredOffset() const noexcept { return stored_offset_; } |
| |
| private: |
| ConsumerOffsetInfo(std::uint32_t partition_id, std::uint64_t current_offset, std::uint64_t stored_offset) |
| : partition_id_(partition_id), current_offset_(current_offset), stored_offset_(stored_offset) {} |
| |
| static ConsumerOffsetInfo FromFfi(ffi::ConsumerOffsetInfo offset); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t partition_id_; |
| std::uint64_t current_offset_; |
| std::uint64_t stored_offset_; |
| }; |
| |
| /** |
| * @brief Type tag for a HeaderField payload. |
| * |
| * Specifies how a HeaderField payload is encoded. Each field stores a type tag |
| * and its corresponding bytes. Numeric payloads use little-endian byte order. |
| */ |
| enum class HeaderKind : std::uint8_t { |
| Raw = 1, |
| String = 2, |
| Bool = 3, |
| Int8 = 4, |
| Int16 = 5, |
| Int32 = 6, |
| Int64 = 7, |
| Int128 = 8, |
| Uint8 = 9, |
| Uint16 = 10, |
| Uint32 = 11, |
| Uint64 = 12, |
| Uint128 = 13, |
| Float32 = 14, |
| Float64 = 15, |
| }; |
| |
| /** |
| * @brief One typed header key or value. |
| * |
| * Create() preserves the supplied bytes without validating that they match the |
| * specified type. Invalid key or value encodings are rejected when the client |
| * sends a request. |
| */ |
| class HeaderField final { |
| public: |
| /** |
| * @brief Creates a typed header field from wire-encoded bytes. |
| * @param kind Type tag for @p value. |
| * @param value Payload encoded according to @p kind. |
| * @return Header field containing the supplied type and bytes. |
| */ |
| static HeaderField Create(HeaderKind kind, std::vector<std::uint8_t> value) { |
| return HeaderField(kind, std::move(value)); |
| } |
| |
| /** |
| * @brief Returns the wire type of Value(). |
| * @return Header type tag. |
| */ |
| [[nodiscard]] HeaderKind Kind() const noexcept { return kind_; } |
| |
| /** |
| * @brief Returns bytes owned by this field. |
| * @return Payload encoded according to Kind(). |
| */ |
| [[nodiscard]] const std::vector<std::uint8_t> &Value() const noexcept { return value_; } |
| |
| private: |
| HeaderField(HeaderKind kind, std::vector<std::uint8_t> value) : kind_(kind), value_(std::move(value)) {} |
| |
| static HeaderField FromFfi(ffi::HeaderField field); |
| |
| friend class HeaderEntry; |
| |
| HeaderKind kind_; |
| std::vector<std::uint8_t> value_; |
| }; |
| |
| /** |
| * @brief One typed header key-value pair. |
| * |
| * Topic options and message user headers use the same typed key-value format. |
| */ |
| class HeaderEntry final { |
| public: |
| /** |
| * @brief Creates a header entry from its typed key and value. |
| * @param key Typed entry key. |
| * @param value Typed entry value. |
| * @return Header entry containing @p key and @p value. |
| */ |
| static HeaderEntry Create(HeaderField key, HeaderField value) { |
| return HeaderEntry(std::move(key), std::move(value)); |
| } |
| |
| /** |
| * @brief Returns the typed key. |
| * @return Key owned by this entry. |
| */ |
| [[nodiscard]] const HeaderField &Key() const noexcept { return key_; } |
| |
| /** |
| * @brief Returns the typed value. |
| * @return Value owned by this entry. |
| */ |
| [[nodiscard]] const HeaderField &Value() const noexcept { return value_; } |
| |
| private: |
| HeaderEntry(HeaderField key, HeaderField value) : key_(std::move(key)), value_(std::move(value)) {} |
| |
| static HeaderEntry FromFfi(ffi::HeaderEntry entry); |
| |
| friend class IggyMessagePolled; |
| friend class ResourceOptions; |
| |
| HeaderField key_; |
| HeaderField value_; |
| }; |
| |
| /** |
| * @brief Message payload and user headers prepared for sending. |
| * |
| * Create() owns the supplied payload and headers. Validation is deferred until |
| * the message is sent. A valid payload contains between 1 and 64,000,000 bytes, |
| * and the encoded user headers occupy no more than 100,000 bytes. Header keys |
| * must be unique. Header insertion order is not preserved during transmission; |
| * headers are ordered by their typed keys. |
| * |
| * The message ID is application-defined and defaults to zero. IDs do not need |
| * to be unique. |
| */ |
| class IggyMessageToSend final { |
| public: |
| /** |
| * @brief Creates a message for a send operation. |
| * @param payload Binary message payload. |
| * @param user_headers Optional typed user headers. Keys must be unique. |
| * @param id Application-defined message ID. |
| * @return Message owning @p payload and @p user_headers. |
| * @note Payload and header constraints are validated when the message is |
| * sent, not by this function. |
| */ |
| static IggyMessageToSend Create(std::vector<std::uint8_t> payload, |
| std::vector<HeaderEntry> user_headers = {}, |
| absl::uint128 id = 0) { |
| return IggyMessageToSend(id, std::move(payload), std::move(user_headers)); |
| } |
| |
| /** |
| * @brief Returns the application-defined message ID. |
| * @return Message ID supplied to Create(), or zero when omitted. |
| */ |
| [[nodiscard]] absl::uint128 Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the binary message payload. |
| * @return Payload owned by this value. The reference remains valid while |
| * this IggyMessageToSend remains alive. |
| */ |
| [[nodiscard]] const std::vector<std::uint8_t> &Payload() const noexcept { return payload_; } |
| |
| /** |
| * @brief Returns the typed user headers. |
| * @return Headers owned by this value in their original insertion order. |
| * The reference remains valid while this IggyMessageToSend remains |
| * alive. |
| */ |
| [[nodiscard]] const std::vector<HeaderEntry> &UserHeaders() const noexcept { return user_headers_; } |
| |
| private: |
| IggyMessageToSend(absl::uint128 id, std::vector<std::uint8_t> payload, std::vector<HeaderEntry> user_headers) |
| : id_(id), payload_(std::move(payload)), user_headers_(std::move(user_headers)) {} |
| |
| [[nodiscard]] ffi::IggyMessageToSend ToFfi() const; |
| |
| friend class IggyBlockingClient; |
| |
| absl::uint128 id_; |
| std::vector<std::uint8_t> payload_; |
| std::vector<HeaderEntry> user_headers_; |
| }; |
| |
| /** |
| * @brief Message and metadata returned by a poll operation. |
| * |
| * This value owns its payload and decoded user headers. Header entries are |
| * returned in their encoded order. Malformed encoded headers are reported as |
| * an empty collection rather than making the message unreadable. |
| */ |
| class IggyMessagePolled final { |
| public: |
| /** |
| * @brief Returns the stored message checksum. |
| * @return Checksum covering the message fields after the checksum field. |
| */ |
| [[nodiscard]] std::uint64_t Checksum() const noexcept { return checksum_; } |
| |
| /** |
| * @brief Returns the application-defined message ID. |
| * @return Message ID supplied when the message was sent. |
| */ |
| [[nodiscard]] absl::uint128 Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the message offset within its partition. |
| * @return Offset assigned by the server. |
| */ |
| [[nodiscard]] std::uint64_t Offset() const noexcept { return offset_; } |
| |
| /** |
| * @brief Returns the timestamp assigned when the message was stored. |
| * @return Server timestamp in microseconds since the Unix epoch. |
| */ |
| [[nodiscard]] std::uint64_t Timestamp() const noexcept { return timestamp_; } |
| |
| /** |
| * @brief Returns the timestamp recorded when the message was created. |
| * @return Origin timestamp in microseconds since the Unix epoch. |
| */ |
| [[nodiscard]] std::uint64_t OriginTimestamp() const noexcept { return origin_timestamp_; } |
| |
| /** |
| * @brief Returns the encoded size of the user-header section. |
| * @return Encoded user-header length in bytes. |
| */ |
| [[nodiscard]] std::uint32_t UserHeadersLength() const noexcept { return user_headers_length_; } |
| |
| /** |
| * @brief Returns the payload length recorded in the message header. |
| * @return Payload length in bytes. |
| */ |
| [[nodiscard]] std::uint32_t PayloadLength() const noexcept { return payload_length_; } |
| |
| /** |
| * @brief Returns the message header's reserved field. |
| * @return Reserved value, currently zero. |
| */ |
| [[nodiscard]] std::uint64_t Reserved() const noexcept { return reserved_; } |
| |
| /** |
| * @brief Returns the binary message payload. |
| * @return Payload owned by this value. The reference remains valid while |
| * this IggyMessagePolled remains alive. |
| */ |
| [[nodiscard]] const std::vector<std::uint8_t> &Payload() const noexcept { return payload_; } |
| |
| /** |
| * @brief Returns the decoded typed user headers. |
| * @return Headers owned by this value in their encoded order. The reference |
| * remains valid while this IggyMessagePolled remains alive. |
| */ |
| [[nodiscard]] const std::vector<HeaderEntry> &UserHeaders() const noexcept { return user_headers_; } |
| |
| private: |
| IggyMessagePolled(std::uint64_t checksum, |
| absl::uint128 id, |
| std::uint64_t offset, |
| std::uint64_t timestamp, |
| std::uint64_t origin_timestamp, |
| std::uint32_t user_headers_length, |
| std::uint32_t payload_length, |
| std::uint64_t reserved, |
| std::vector<std::uint8_t> payload, |
| std::vector<HeaderEntry> user_headers) |
| : checksum_(checksum), |
| id_(id), |
| offset_(offset), |
| timestamp_(timestamp), |
| origin_timestamp_(origin_timestamp), |
| user_headers_length_(user_headers_length), |
| payload_length_(payload_length), |
| reserved_(reserved), |
| payload_(std::move(payload)), |
| user_headers_(std::move(user_headers)) {} |
| |
| static IggyMessagePolled FromFfi(ffi::IggyMessagePolled message); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint64_t checksum_; |
| absl::uint128 id_; |
| std::uint64_t offset_; |
| std::uint64_t timestamp_; |
| std::uint64_t origin_timestamp_; |
| std::uint32_t user_headers_length_; |
| std::uint32_t payload_length_; |
| std::uint64_t reserved_; |
| std::vector<std::uint8_t> payload_; |
| std::vector<HeaderEntry> user_headers_; |
| }; |
| |
| /** |
| * @brief Options recorded for a stream or topic. |
| * |
| * Explicit() contains values supplied when the resource was created. Derived() |
| * contains values resolved from the server configuration at that time. Derived |
| * values describe the resource's creation settings and can differ when the |
| * resource is recreated with a different server configuration. |
| * |
| * This is a response-only model returned by Options(). Use TopicCreateOptions |
| * to configure a new topic. Stream creation currently accepts only a name. |
| */ |
| class ResourceOptions final { |
| public: |
| /** |
| * @brief Returns entries supplied explicitly at resource creation. |
| * @return Explicit entries as map from option name to typed value. |
| */ |
| [[nodiscard]] const std::map<std::string, HeaderField> &Explicit() const noexcept { return explicit_; } |
| |
| /** |
| * @brief Returns entries derived from configured defaults at admission. |
| * @return Derived entries as map from option name to typed value. |
| * @note Stream responses currently expose explicit entries only, so this |
| * collection is empty for Stream and StreamDetails. |
| */ |
| [[nodiscard]] const std::map<std::string, HeaderField> &Derived() const noexcept { return derived_; } |
| |
| private: |
| ResourceOptions(std::map<std::string, HeaderField> explicit_entries, |
| std::map<std::string, HeaderField> derived_entries) |
| : explicit_(std::move(explicit_entries)), derived_(std::move(derived_entries)) {} |
| |
| static ResourceOptions FromFfi(rust::Vec<ffi::HeaderEntry> explicit_entries, |
| rust::Vec<ffi::HeaderEntry> derived_entries); |
| |
| friend class IggyBlockingClient; |
| friend class Topic; |
| friend class TopicDetails; |
| friend class Stream; |
| friend class StreamDetails; |
| friend class UserInfo; |
| friend class UserInfoDetails; |
| |
| std::map<std::string, HeaderField> explicit_; |
| std::map<std::string, HeaderField> derived_; |
| }; |
| |
| /** |
| * @brief Snapshot of basic user metadata. |
| * |
| * GetUsers() returns one value for each user visible to the caller. This |
| * summary omits permissions. User IDs remain assigned to the same user until |
| * that user is deleted. CreatedAt() is expressed in microseconds since the |
| * Unix epoch. |
| */ |
| class UserInfo final { |
| public: |
| /** |
| * @brief Returns the server-assigned numeric user ID. |
| * @return Numeric user ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the creation timestamp. |
| * @return Timestamp in microseconds since the Unix epoch. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns whether the user is active or inactive. |
| * @return Current user status observed for this request. |
| */ |
| [[nodiscard]] UserStatus Status() const noexcept { return status_; } |
| |
| /** |
| * @brief Returns the unique user name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Username() const noexcept { return username_; } |
| |
| [[nodiscard]] const ResourceOptions &Options() const noexcept { return options_; } |
| |
| private: |
| UserInfo(std::uint32_t id, |
| std::uint64_t created_at, |
| UserStatus status, |
| std::string username, |
| ResourceOptions options) |
| : id_(id), |
| created_at_(created_at), |
| status_(status), |
| username_(std::move(username)), |
| options_(std::move(options)) {} |
| |
| static UserInfo FromFfi(ffi::UserInfo user); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| UserStatus status_; |
| std::string username_; |
| ResourceOptions options_; |
| }; |
| |
| /** |
| * @brief Snapshot of user metadata and assigned permissions. |
| * |
| * GetUser() and CreateUser() return this detailed form. Permissions() is empty |
| * when the user has no permission object. An engaged Permissions value can |
| * still contain no enabled grants. |
| */ |
| class UserInfoDetails final { |
| public: |
| /** |
| * @brief Returns the server-assigned numeric user ID. |
| * @return Numeric user ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the creation timestamp. |
| * @return Timestamp in microseconds since the Unix epoch. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns whether the user is active or inactive. |
| * @return Current user status observed for this request. |
| */ |
| [[nodiscard]] UserStatus Status() const noexcept { return status_; } |
| |
| /** |
| * @brief Returns the unique user name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Username() const noexcept { return username_; } |
| |
| /** |
| * @brief Returns the user's explicit permission assignment. |
| * @return Empty when no permission object is assigned; otherwise the |
| * permissions owned by this value. |
| */ |
| [[nodiscard]] const std::optional<::iggy::Permissions> &Permissions() const noexcept { return permissions_; } |
| |
| [[nodiscard]] const ResourceOptions &Options() const noexcept { return options_; } |
| |
| private: |
| UserInfoDetails(std::uint32_t id, |
| std::uint64_t created_at, |
| UserStatus status, |
| std::string username, |
| std::optional<::iggy::Permissions> permissions, |
| ResourceOptions options) |
| : id_(id), |
| created_at_(created_at), |
| status_(status), |
| username_(std::move(username)), |
| permissions_(std::move(permissions)), |
| options_(std::move(options)) {} |
| |
| static UserInfoDetails FromFfi(ffi::UserInfoDetails user); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| UserStatus status_; |
| std::string username_; |
| std::optional<::iggy::Permissions> permissions_; |
| ResourceOptions options_; |
| }; |
| |
| /** |
| * @brief Snapshot of one topic's metadata and aggregate statistics. |
| * |
| * GetStream() returns one of these values for each observed topic. It owns its |
| * name and option data. |
| * |
| * The value describes the topic state observed by the server for one request. |
| * It is not a live view. SizeBytes(), MessagesCount(), and PartitionsCount() |
| * can become stale immediately after the request completes when another client |
| * changes the topic. |
| * |
| * Use GetTopic() to retrieve partition summaries. Topic IDs identify a topic |
| * within its stream for its lifetime and remain stable when it is renamed. |
| * CreatedAt() is the server timestamp, in microseconds, recorded when the |
| * topic was created. |
| */ |
| class Topic final { |
| public: |
| /** |
| * @brief Returns the numeric topic ID assigned within its stream. |
| * @return Numeric topic ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the server creation timestamp. |
| * @return Timestamp in microseconds. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns the topic name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Name() const noexcept { return name_; } |
| |
| /** |
| * @brief Returns the aggregate retained topic size. |
| * @return Size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t SizeBytes() const noexcept { return size_bytes_; } |
| |
| /** |
| * @brief Returns the server-encoded message retention value. |
| * @return Retention value in microseconds or a protocol sentinel. |
| */ |
| [[nodiscard]] std::uint64_t MessageExpiry() const noexcept { return message_expiry_; } |
| |
| /** |
| * @brief Returns the server-selected storage compression algorithm. |
| * @return Algorithm name owned by this value. |
| */ |
| [[nodiscard]] const std::string &CompressionAlgorithm() const noexcept { return compression_algorithm_; } |
| |
| /** |
| * @brief Returns the configured maximum retained topic size. |
| * @return Maximum size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t MaxTopicSize() const noexcept { return max_topic_size_; } |
| |
| /** |
| * @brief Returns the aggregate number of retained messages. |
| * @return Message count. |
| */ |
| [[nodiscard]] std::uint64_t MessagesCount() const noexcept { return messages_count_; } |
| |
| /** |
| * @brief Returns the number of partitions belonging to this topic. |
| * @return Partition count. |
| */ |
| [[nodiscard]] std::uint32_t PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Returns topic creation options and their admission provenance. |
| * @return Options owned by this value. |
| */ |
| [[nodiscard]] const ResourceOptions &Options() const noexcept { return options_; } |
| |
| private: |
| Topic(std::uint32_t id, |
| std::uint64_t created_at, |
| std::string name, |
| std::uint64_t size_bytes, |
| std::uint64_t message_expiry, |
| std::string compression_algorithm, |
| std::uint64_t max_topic_size, |
| std::uint64_t messages_count, |
| std::uint32_t partitions_count, |
| ResourceOptions options) |
| : id_(id), |
| created_at_(created_at), |
| name_(std::move(name)), |
| size_bytes_(size_bytes), |
| message_expiry_(message_expiry), |
| compression_algorithm_(std::move(compression_algorithm)), |
| max_topic_size_(max_topic_size), |
| messages_count_(messages_count), |
| partitions_count_(partitions_count), |
| options_(std::move(options)) {} |
| |
| static Topic FromFfi(ffi::Topic topic); |
| |
| friend class IggyBlockingClient; |
| friend class StreamDetails; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| std::string name_; |
| std::uint64_t size_bytes_; |
| std::uint64_t message_expiry_; |
| std::string compression_algorithm_; |
| std::uint64_t max_topic_size_; |
| std::uint64_t messages_count_; |
| std::uint32_t partitions_count_; |
| ResourceOptions options_; |
| }; |
| |
| /** |
| * @brief Partition metadata returned within TopicDetails. |
| * |
| * Represents the state of a partition when its topic was retrieved. This is a |
| * snapshot, not a live view, so offsets and statistics can change after |
| * GetTopic() returns. |
| */ |
| class Partition final { |
| public: |
| /** |
| * @brief Returns the numeric partition ID within its topic. |
| * @return Numeric partition ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the server creation timestamp. |
| * @return Timestamp in microseconds. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns the number of retained storage segments. |
| * @return Segment count. |
| */ |
| [[nodiscard]] std::uint32_t SegmentsCount() const noexcept { return segments_count_; } |
| |
| /** |
| * @brief Returns the current server-observed message offset. |
| * @return Current message offset. |
| */ |
| [[nodiscard]] std::uint64_t CurrentOffset() const noexcept { return current_offset_; } |
| |
| /** |
| * @brief Returns the retained partition size. |
| * @return Size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t SizeBytes() const noexcept { return size_bytes_; } |
| |
| /** |
| * @brief Returns the number of retained messages. |
| * @return Message count. |
| */ |
| [[nodiscard]] std::uint64_t MessagesCount() const noexcept { return messages_count_; } |
| |
| private: |
| Partition(std::uint32_t id, |
| std::uint64_t created_at, |
| std::uint32_t segments_count, |
| std::uint64_t current_offset, |
| std::uint64_t size_bytes, |
| std::uint64_t messages_count) |
| : id_(id), |
| created_at_(created_at), |
| segments_count_(segments_count), |
| current_offset_(current_offset), |
| size_bytes_(size_bytes), |
| messages_count_(messages_count) {} |
| |
| static Partition FromFfi(ffi::Partition partition); |
| |
| friend class TopicDetails; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| std::uint32_t segments_count_; |
| std::uint64_t current_offset_; |
| std::uint64_t size_bytes_; |
| std::uint64_t messages_count_; |
| }; |
| |
| /** |
| * @brief Snapshot of one topic's metadata, aggregate statistics, and partitions. |
| * |
| * GetTopic() returns this value. It owns its name, partition summaries, and |
| * option data. |
| * |
| * The value describes the topic state observed by the server for one request. |
| * It is not a live view. Its metadata and partition summaries can become stale |
| * immediately after the request completes when another client changes the |
| * topic. |
| * |
| * Topic IDs identify a topic within its stream for its lifetime and remain |
| * stable when it is renamed. CreatedAt() is the server timestamp, in |
| * microseconds, recorded when the topic was created. |
| */ |
| class TopicDetails final { |
| public: |
| /** |
| * @brief Returns the numeric topic ID within its stream. |
| * @return Numeric topic ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the server creation timestamp. |
| * @return Timestamp in microseconds. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns the topic name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Name() const noexcept { return name_; } |
| |
| /** |
| * @brief Returns the aggregate retained topic size. |
| * @return Size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t SizeBytes() const noexcept { return size_bytes_; } |
| |
| /** |
| * @brief Returns the server-encoded message retention value. |
| * @return Retention value in microseconds or a protocol sentinel. |
| */ |
| [[nodiscard]] std::uint64_t MessageExpiry() const noexcept { return message_expiry_; } |
| |
| /** |
| * @brief Returns the storage compression algorithm selected for this topic. |
| * @return Algorithm name owned by this value. |
| */ |
| [[nodiscard]] const std::string &CompressionAlgorithm() const noexcept { return compression_algorithm_; } |
| |
| /** |
| * @brief Returns the maximum retained size configured for this topic. |
| * @return Maximum size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t MaxTopicSize() const noexcept { return max_topic_size_; } |
| |
| /** |
| * @brief Returns the aggregate number of retained messages. |
| * @return Message count. |
| */ |
| [[nodiscard]] std::uint64_t MessagesCount() const noexcept { return messages_count_; } |
| |
| /** |
| * @brief Returns the number of partitions belonging to this topic. |
| * @return Partition count. |
| */ |
| [[nodiscard]] std::uint32_t PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Returns one summary for each partition in the topic. |
| * |
| * The summaries do not include segment metadata, messages, consumer |
| * offsets, or consumer-group membership. |
| * @return Partition summaries owned by this value. |
| */ |
| [[nodiscard]] const std::vector<Partition> &Partitions() const noexcept { return partitions_; } |
| |
| /** |
| * @brief Returns topic creation options and their admission provenance. |
| * @return Options owned by this value. |
| */ |
| [[nodiscard]] const ResourceOptions &Options() const noexcept { return options_; } |
| |
| private: |
| TopicDetails(std::uint32_t id, |
| std::uint64_t created_at, |
| std::string name, |
| std::uint64_t size_bytes, |
| std::uint64_t message_expiry, |
| std::string compression_algorithm, |
| std::uint64_t max_topic_size, |
| std::uint64_t messages_count, |
| std::uint32_t partitions_count, |
| std::vector<Partition> partitions, |
| ResourceOptions options) |
| : id_(id), |
| created_at_(created_at), |
| name_(std::move(name)), |
| size_bytes_(size_bytes), |
| message_expiry_(message_expiry), |
| compression_algorithm_(std::move(compression_algorithm)), |
| max_topic_size_(max_topic_size), |
| messages_count_(messages_count), |
| partitions_count_(partitions_count), |
| partitions_(std::move(partitions)), |
| options_(std::move(options)) {} |
| |
| static TopicDetails FromFfi(ffi::TopicDetails topic); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| std::string name_; |
| std::uint64_t size_bytes_; |
| std::uint64_t message_expiry_; |
| std::string compression_algorithm_; |
| std::uint64_t max_topic_size_; |
| std::uint64_t messages_count_; |
| std::uint32_t partitions_count_; |
| std::vector<Partition> partitions_; |
| ResourceOptions options_; |
| }; |
| |
| /** |
| * @brief Snapshot of one stream's metadata and aggregate statistics. |
| * |
| * CreateStream() and GetStream() return this value. |
| * |
| * The value describes the stream state observed by the server for one request. |
| * It is not a live view or an atomic snapshot of later stream, topic, or |
| * message activity. SizeBytes(), MessagesCount(), TopicsCount(), and Topics() |
| * can become stale immediately after the request completes when another client |
| * changes the stream. |
| * |
| * A newly created stream has no topics or messages, so CreateStream() returns |
| * zero for SizeBytes(), MessagesCount(), and TopicsCount(), with an empty |
| * Topics() collection. GetStream() returns the same aggregate fields and one |
| * Topic summary for each observed topic. |
| * |
| * Stream IDs identify a stream for its lifetime and remain stable when it is |
| * renamed. CreatedAt() is the server timestamp, in microseconds, recorded when |
| * the stream was created. |
| */ |
| class StreamDetails final { |
| public: |
| /** |
| * @brief Returns the numeric ID assigned by the server. |
| * |
| * This value can be passed to GetStream() while the stream exists. It is |
| * unchanged by a stream rename. |
| * @return Numeric stream ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the server-recorded creation timestamp. |
| * @return Timestamp in microseconds. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns the unique stream name observed by the server. |
| * @return Reference owned by this value. It remains valid until this |
| * StreamDetails object is modified or destroyed. |
| */ |
| [[nodiscard]] const std::string &Name() const noexcept { return name_; } |
| |
| /** |
| * @brief Returns the aggregate retained size of all stream topics. |
| * @return Size in bytes observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint64_t SizeBytes() const noexcept { return size_bytes_; } |
| |
| /** |
| * @brief Returns the aggregate number of messages in all stream topics. |
| * @return Message count observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint64_t MessagesCount() const noexcept { return messages_count_; } |
| |
| /** |
| * @brief Returns the number of topics belonging to the stream. |
| * @return Topic count observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint32_t TopicsCount() const noexcept { return topics_count_; } |
| |
| /** |
| * @brief Returns the topic summaries observed by the server. |
| * @return Topic values owned by this StreamDetails object. |
| */ |
| [[nodiscard]] const std::vector<Topic> &Topics() const noexcept { return topics_; } |
| |
| /** |
| * @brief Returns explicit stream creation options. |
| * @return Options owned by this value. |
| * @note The current bridge does not return derived stream options. |
| */ |
| [[nodiscard]] const ResourceOptions &Options() const noexcept { return options_; } |
| |
| private: |
| StreamDetails(std::uint32_t id, |
| std::uint64_t created_at, |
| std::string name, |
| std::uint64_t size_bytes, |
| std::uint64_t messages_count, |
| std::uint32_t topics_count, |
| std::vector<Topic> topics, |
| ResourceOptions options) |
| : id_(id), |
| created_at_(created_at), |
| name_(std::move(name)), |
| size_bytes_(size_bytes), |
| messages_count_(messages_count), |
| topics_count_(topics_count), |
| topics_(std::move(topics)), |
| options_(std::move(options)) {} |
| |
| static StreamDetails FromFfi(ffi::StreamDetails stream); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| std::string name_; |
| std::uint64_t size_bytes_; |
| std::uint64_t messages_count_; |
| std::uint32_t topics_count_; |
| std::vector<Topic> topics_; |
| ResourceOptions options_; |
| }; |
| |
| /** |
| * @brief Snapshot of one stream's metadata and aggregate statistics. |
| * |
| * GetStreams() returns one of these values for each observed stream. |
| * |
| * The value describes the stream state observed by the server for one request. |
| * It is not a live view. SizeBytes(), MessagesCount(), and TopicsCount() can |
| * become stale immediately after the request completes when another client |
| * changes the stream. |
| * |
| * Use GetStream() to retrieve topic summaries for a stream. |
| */ |
| class Stream final { |
| public: |
| /** |
| * @brief Returns the numeric ID assigned by the server. |
| * @return Numeric stream ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the server-recorded creation timestamp. |
| * @return Timestamp in microseconds. |
| */ |
| [[nodiscard]] std::uint64_t CreatedAt() const noexcept { return created_at_; } |
| |
| /** |
| * @brief Returns the stream name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Name() const noexcept { return name_; } |
| |
| /** |
| * @brief Returns the aggregate retained stream size. |
| * @return Size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t SizeBytes() const noexcept { return size_bytes_; } |
| |
| /** |
| * @brief Returns the aggregate number of retained stream messages. |
| * @return Message count. |
| */ |
| [[nodiscard]] std::uint64_t MessagesCount() const noexcept { return messages_count_; } |
| |
| /** |
| * @brief Returns the number of topics belonging to the stream. |
| * @return Topic count. |
| */ |
| [[nodiscard]] std::uint32_t TopicsCount() const noexcept { return topics_count_; } |
| |
| /** |
| * @brief Returns explicit stream creation options. |
| * @return Options owned by this value. |
| * @note The current bridge does not return derived stream options. |
| */ |
| [[nodiscard]] const ResourceOptions &Options() const noexcept { return options_; } |
| |
| private: |
| Stream(std::uint32_t id, |
| std::uint64_t created_at, |
| std::string name, |
| std::uint64_t size_bytes, |
| std::uint64_t messages_count, |
| std::uint32_t topics_count, |
| ResourceOptions options) |
| : id_(id), |
| created_at_(created_at), |
| name_(std::move(name)), |
| size_bytes_(size_bytes), |
| messages_count_(messages_count), |
| topics_count_(topics_count), |
| options_(std::move(options)) {} |
| |
| static Stream FromFfi(ffi::Stream stream); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::uint64_t created_at_; |
| std::string name_; |
| std::uint64_t size_bytes_; |
| std::uint64_t messages_count_; |
| std::uint32_t topics_count_; |
| ResourceOptions options_; |
| }; |
| |
| /** |
| * @brief Snapshot of a consumer group member and its partition assignments. |
| * |
| * ConsumerGroupDetails contains one of these values for every member observed |
| * by the server. Membership and partition assignments can change immediately |
| * after the request completes. |
| */ |
| class ConsumerGroupMember final { |
| public: |
| /** |
| * @brief Returns the numeric ID of the consumer group member. |
| * @return Numeric member ID assigned by the server. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the server-reported number of partitions assigned to this member. |
| * @return Partition count reported by the server. |
| */ |
| [[nodiscard]] std::uint32_t PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Returns the partitions assigned to this member. |
| * @return Partition IDs owned by this value. The reference remains valid |
| * while this ConsumerGroupMember remains alive. |
| */ |
| [[nodiscard]] const std::vector<std::uint32_t> &Partitions() const noexcept { return partitions_; } |
| |
| private: |
| ConsumerGroupMember(std::uint32_t id, std::uint32_t partitions_count, std::vector<std::uint32_t> partitions) |
| : id_(id), partitions_count_(partitions_count), partitions_(std::move(partitions)) {} |
| |
| static ConsumerGroupMember FromFfi(ffi::ConsumerGroupMember member); |
| |
| friend class ConsumerGroupDetails; |
| |
| std::uint32_t id_; |
| std::uint32_t partitions_count_; |
| std::vector<std::uint32_t> partitions_; |
| }; |
| |
| /** |
| * @brief Snapshot of consumer group metadata. |
| * |
| * GetConsumerGroups() returns one summary for each consumer group observed in |
| * a topic. Use GetConsumerGroup() when individual member and partition |
| * assignment details are needed. |
| */ |
| class ConsumerGroup final { |
| public: |
| /** |
| * @brief Returns the numeric ID assigned to the consumer group. |
| * @return Numeric consumer group ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the consumer group name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Name() const noexcept { return name_; } |
| |
| /** |
| * @brief Returns the number of partitions consumed by the group. |
| * @return Partition count observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint32_t PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Returns the number of members in the group. |
| * @return Member count observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint32_t MembersCount() const noexcept { return members_count_; } |
| |
| private: |
| ConsumerGroup(std::uint32_t id, std::string name, std::uint32_t partitions_count, std::uint32_t members_count) |
| : id_(id), name_(std::move(name)), partitions_count_(partitions_count), members_count_(members_count) {} |
| |
| static ConsumerGroup FromFfi(ffi::ConsumerGroup group); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::string name_; |
| std::uint32_t partitions_count_; |
| std::uint32_t members_count_; |
| }; |
| |
| /** |
| * @brief Snapshot of consumer group metadata and member details. |
| * |
| * CreateConsumerGroup() and GetConsumerGroup() return this value. Membership |
| * and partition assignments can change immediately after the request |
| * completes. |
| */ |
| class ConsumerGroupDetails final { |
| public: |
| /** |
| * @brief Returns the numeric ID assigned to the consumer group. |
| * @return Numeric consumer group ID. |
| */ |
| [[nodiscard]] std::uint32_t Id() const noexcept { return id_; } |
| |
| /** |
| * @brief Returns the consumer group name. |
| * @return Name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Name() const noexcept { return name_; } |
| |
| /** |
| * @brief Returns the number of partitions consumed by the group. |
| * @return Partition count observed by the server for this request. |
| */ |
| [[nodiscard]] std::uint32_t PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Returns the server-reported number of members in the group. |
| * @return Member count reported by the server. |
| */ |
| [[nodiscard]] std::uint32_t MembersCount() const noexcept { return members_count_; } |
| |
| /** |
| * @brief Returns the consumer group members and their partition assignments. |
| * @return Member details owned by this value. The reference remains valid |
| * while this ConsumerGroupDetails remains alive. |
| */ |
| [[nodiscard]] const std::vector<ConsumerGroupMember> &Members() const noexcept { return members_; } |
| |
| private: |
| ConsumerGroupDetails(std::uint32_t id, |
| std::string name, |
| std::uint32_t partitions_count, |
| std::uint32_t members_count, |
| std::vector<ConsumerGroupMember> members) |
| : id_(id), |
| name_(std::move(name)), |
| partitions_count_(partitions_count), |
| members_count_(members_count), |
| members_(std::move(members)) {} |
| |
| static ConsumerGroupDetails FromFfi(ffi::ConsumerGroupDetails group); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t id_; |
| std::string name_; |
| std::uint32_t partitions_count_; |
| std::uint32_t members_count_; |
| std::vector<ConsumerGroupMember> members_; |
| }; |
| |
| /** |
| * @brief Identifies one consumer-group membership of a connected client. |
| * |
| * ClientInfoDetails returns these numeric identifiers for each membership |
| * observed by the server. The membership can change immediately after the |
| * client information is retrieved. |
| */ |
| class ConsumerGroupInfo final { |
| public: |
| /** |
| * @brief Returns the numeric ID of the member group's stream. |
| * @return Numeric stream ID. |
| */ |
| [[nodiscard]] std::uint32_t StreamId() const noexcept { return stream_id_; } |
| |
| /** |
| * @brief Returns the numeric ID of the member group's topic. |
| * @return Numeric topic ID. |
| */ |
| [[nodiscard]] std::uint32_t TopicId() const noexcept { return topic_id_; } |
| |
| /** |
| * @brief Returns the numeric consumer group ID. |
| * @return Numeric consumer group ID. |
| */ |
| [[nodiscard]] std::uint32_t GroupId() const noexcept { return group_id_; } |
| |
| private: |
| ConsumerGroupInfo(std::uint32_t stream_id, std::uint32_t topic_id, std::uint32_t group_id) |
| : stream_id_(stream_id), topic_id_(topic_id), group_id_(group_id) {} |
| |
| static ConsumerGroupInfo FromFfi(ffi::ConsumerGroupInfo info); |
| |
| friend class ClientInfoDetails; |
| |
| std::uint32_t stream_id_; |
| std::uint32_t topic_id_; |
| std::uint32_t group_id_; |
| }; |
| |
| /** |
| * @brief Snapshot summary of a client connection known to the server. |
| * |
| * GetClients() returns one summary for each connection observed by the server. |
| * A client is a transport connection, not an Iggy user. Connections can close, |
| * authenticate, or change consumer-group membership immediately after the |
| * request completes. |
| */ |
| class ClientInfo final { |
| public: |
| /** |
| * @brief Returns the server-assigned connection ID. |
| * @return Numeric client ID accepted by GetClient() while the connection |
| * remains known to the server. |
| */ |
| [[nodiscard]] std::uint32_t ClientId() const noexcept { return client_id_; } |
| |
| /** |
| * @brief Returns the authenticated user ID for this connection. |
| * @return Empty when the client has not authenticated. |
| */ |
| [[nodiscard]] const std::optional<std::uint32_t> &UserId() const noexcept { return user_id_; } |
| |
| /** |
| * @brief Returns the remote address reported by the server. |
| * @return Address owned by this value. |
| */ |
| [[nodiscard]] const std::string &Address() const noexcept { return address_; } |
| |
| /** |
| * @brief Returns the transport name reported by the server. |
| * @return Transport name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Transport() const noexcept { return transport_; } |
| |
| /** |
| * @brief Returns the number of consumer groups joined by this client. |
| * @return Membership count observed for this request. |
| */ |
| [[nodiscard]] std::uint32_t ConsumerGroupsCount() const noexcept { return consumer_groups_count_; } |
| |
| private: |
| ClientInfo(std::uint32_t client_id, |
| std::optional<std::uint32_t> user_id, |
| std::string address, |
| std::string transport, |
| std::uint32_t consumer_groups_count) |
| : client_id_(client_id), |
| user_id_(user_id), |
| address_(std::move(address)), |
| transport_(std::move(transport)), |
| consumer_groups_count_(consumer_groups_count) {} |
| |
| static ClientInfo FromFfi(ffi::ClientInfo info); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t client_id_; |
| std::optional<std::uint32_t> user_id_; |
| std::string address_; |
| std::string transport_; |
| std::uint32_t consumer_groups_count_; |
| }; |
| |
| /** |
| * @brief Snapshot of a client connection and its consumer-group memberships. |
| * |
| * GetMe() and GetClient() return this detailed form. The connection state and |
| * memberships are not live and can change immediately after retrieval. |
| */ |
| class ClientInfoDetails final { |
| public: |
| /** |
| * @brief Returns the server-assigned connection ID. |
| * @return Numeric client ID. |
| */ |
| [[nodiscard]] std::uint32_t ClientId() const noexcept { return client_id_; } |
| |
| /** |
| * @brief Returns the authenticated user ID for this connection. |
| * @return Empty when the client has not authenticated. |
| */ |
| [[nodiscard]] const std::optional<std::uint32_t> &UserId() const noexcept { return user_id_; } |
| |
| /** |
| * @brief Returns the remote address reported by the server. |
| * @return Address owned by this value. |
| */ |
| [[nodiscard]] const std::string &Address() const noexcept { return address_; } |
| |
| /** |
| * @brief Returns the transport name reported by the server. |
| * @return Transport name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Transport() const noexcept { return transport_; } |
| |
| /** |
| * @brief Returns the server-reported consumer-group membership count. |
| * @return Membership count observed for this request. |
| */ |
| [[nodiscard]] std::uint32_t ConsumerGroupsCount() const noexcept { return consumer_groups_count_; } |
| |
| /** |
| * @brief Returns the observed consumer-group memberships. |
| * @return Membership identifiers owned by this value. |
| */ |
| [[nodiscard]] const std::vector<ConsumerGroupInfo> &ConsumerGroups() const noexcept { return consumer_groups_; } |
| |
| private: |
| ClientInfoDetails(std::uint32_t client_id, |
| std::optional<std::uint32_t> user_id, |
| std::string address, |
| std::string transport, |
| std::uint32_t consumer_groups_count, |
| std::vector<ConsumerGroupInfo> consumer_groups) |
| : client_id_(client_id), |
| user_id_(user_id), |
| address_(std::move(address)), |
| transport_(std::move(transport)), |
| consumer_groups_count_(consumer_groups_count), |
| consumer_groups_(std::move(consumer_groups)) {} |
| |
| static ClientInfoDetails FromFfi(ffi::ClientInfoDetails info); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t client_id_; |
| std::optional<std::uint32_t> user_id_; |
| std::string address_; |
| std::string transport_; |
| std::uint32_t consumer_groups_count_; |
| std::vector<ConsumerGroupInfo> consumer_groups_; |
| }; |
| |
| /** |
| * @brief Cache counters for one stream, topic, and partition. |
| * |
| * Stats::CacheMetrics() contains these entries when the server implementation |
| * reports partition cache metrics. The current VSR server returns an empty |
| * cache-metrics collection. |
| */ |
| class CacheMetricEntry final { |
| public: |
| /** |
| * @brief Returns the numeric stream ID for this cache entry. |
| * @return Numeric stream ID. |
| */ |
| [[nodiscard]] std::uint32_t StreamId() const noexcept { return stream_id_; } |
| |
| /** |
| * @brief Returns the numeric topic ID for this cache entry. |
| * @return Numeric topic ID. |
| */ |
| [[nodiscard]] std::uint32_t TopicId() const noexcept { return topic_id_; } |
| |
| /** |
| * @brief Returns the numeric partition ID for this cache entry. |
| * @return Numeric partition ID. |
| */ |
| [[nodiscard]] std::uint32_t PartitionId() const noexcept { return partition_id_; } |
| |
| /** |
| * @brief Returns the cumulative number of cache hits reported by the server. |
| * @return Cache hit count. |
| */ |
| [[nodiscard]] std::uint64_t Hits() const noexcept { return hits_; } |
| |
| /** |
| * @brief Returns the cumulative number of cache misses reported by the server. |
| * @return Cache miss count. |
| */ |
| [[nodiscard]] std::uint64_t Misses() const noexcept { return misses_; } |
| |
| /** |
| * @brief Returns the server-reported ratio of hits to total cache lookups. |
| * @return Cache hit ratio. |
| */ |
| [[nodiscard]] float HitRatio() const noexcept { return hit_ratio_; } |
| |
| private: |
| CacheMetricEntry(std::uint32_t stream_id, |
| std::uint32_t topic_id, |
| std::uint32_t partition_id, |
| std::uint64_t hits, |
| std::uint64_t misses, |
| float hit_ratio) |
| : stream_id_(stream_id), |
| topic_id_(topic_id), |
| partition_id_(partition_id), |
| hits_(hits), |
| misses_(misses), |
| hit_ratio_(hit_ratio) {} |
| |
| static CacheMetricEntry FromFfi(ffi::CacheMetricEntry entry); |
| |
| friend class Stats; |
| |
| std::uint32_t stream_id_; |
| std::uint32_t topic_id_; |
| std::uint32_t partition_id_; |
| std::uint64_t hits_; |
| std::uint64_t misses_; |
| float hit_ratio_; |
| }; |
| |
| /** |
| * @brief Snapshot of server process, storage, and resource statistics. |
| * |
| * GetStats() returns process and host measurements from the serving server, |
| * together with metadata totals observed for one request. Values are not a |
| * live or transactional view. CPU measurements depend on the server's sampling |
| * history, and the first sample on a serving thread can report zero. Memory |
| * totals honor an effective cgroup limit when one applies. Disk-space values |
| * describe the volume containing the configured data directory and can be zero |
| * when the server cannot probe that volume. |
| */ |
| class Stats final { |
| public: |
| /** |
| * @brief Returns the operating-system process ID of the server. |
| * @return Numeric process ID. |
| */ |
| [[nodiscard]] std::uint32_t ProcessId() const noexcept { return process_id_; } |
| |
| /** |
| * @brief Returns the server process CPU usage. |
| * @return Process CPU usage as a percentage. |
| */ |
| [[nodiscard]] float CpuUsage() const noexcept { return cpu_usage_; } |
| |
| /** |
| * @brief Returns total CPU usage for the available CPU set. |
| * @return Total CPU usage as a percentage. |
| */ |
| [[nodiscard]] float TotalCpuUsage() const noexcept { return total_cpu_usage_; } |
| |
| /** |
| * @brief Returns server process memory usage. |
| * @return Process memory usage in bytes. |
| */ |
| [[nodiscard]] std::uint64_t MemoryUsage() const noexcept { return memory_usage_; } |
| |
| /** |
| * @brief Returns total host or effective cgroup memory. |
| * @return Total memory in bytes. |
| */ |
| [[nodiscard]] std::uint64_t TotalMemory() const noexcept { return total_memory_; } |
| |
| /** |
| * @brief Returns available host or effective cgroup memory. |
| * @return Available memory in bytes. |
| */ |
| [[nodiscard]] std::uint64_t AvailableMemory() const noexcept { return available_memory_; } |
| |
| /** |
| * @brief Returns server process uptime. |
| * @return Process uptime in microseconds. |
| */ |
| [[nodiscard]] std::uint64_t RunTimeMicros() const noexcept { return run_time_micros_; } |
| |
| /** |
| * @brief Returns the server process start time. |
| * @return Timestamp in microseconds since the Unix epoch. |
| */ |
| [[nodiscard]] std::uint64_t StartTimeEpochMicros() const noexcept { return start_time_epoch_micros_; } |
| |
| /** |
| * @brief Returns the server process read-byte count. |
| * @return Number of bytes read by the process. |
| */ |
| [[nodiscard]] std::uint64_t ReadBytes() const noexcept { return read_bytes_; } |
| |
| /** |
| * @brief Returns the server process written-byte count. |
| * @return Number of bytes written by the process. |
| */ |
| [[nodiscard]] std::uint64_t WrittenBytes() const noexcept { return written_bytes_; } |
| |
| /** |
| * @brief Returns the aggregate retained message size. |
| * @return Retained message size in bytes. |
| */ |
| [[nodiscard]] std::uint64_t MessagesSizeBytes() const noexcept { return messages_size_bytes_; } |
| |
| /** |
| * @brief Returns the observed number of streams. |
| * @return Stream count. |
| */ |
| [[nodiscard]] std::uint32_t StreamsCount() const noexcept { return streams_count_; } |
| |
| /** |
| * @brief Returns the observed number of topics. |
| * @return Topic count. |
| */ |
| [[nodiscard]] std::uint32_t TopicsCount() const noexcept { return topics_count_; } |
| |
| /** |
| * @brief Returns the observed number of partitions. |
| * @return Partition count. |
| */ |
| [[nodiscard]] std::uint32_t PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Returns the observed number of partition segments. |
| * @return Segment count. |
| */ |
| [[nodiscard]] std::uint32_t SegmentsCount() const noexcept { return segments_count_; } |
| |
| /** |
| * @brief Returns the observed number of retained messages. |
| * @return Message count. |
| */ |
| [[nodiscard]] std::uint64_t MessagesCount() const noexcept { return messages_count_; } |
| |
| /** |
| * @brief Returns the number of client connections observed by the server. |
| * @return Client connection count. |
| */ |
| [[nodiscard]] std::uint32_t ClientsCount() const noexcept { return clients_count_; } |
| |
| /** |
| * @brief Returns the observed number of consumer groups. |
| * @return Consumer group count. |
| */ |
| [[nodiscard]] std::uint32_t ConsumerGroupsCount() const noexcept { return consumer_groups_count_; } |
| |
| /** |
| * @brief Returns the server host name. |
| * @return Host name owned by this value. |
| */ |
| [[nodiscard]] const std::string &Hostname() const noexcept { return hostname_; } |
| |
| /** |
| * @brief Returns the server operating-system name. |
| * @return Operating-system name owned by this value. |
| */ |
| [[nodiscard]] const std::string &OsName() const noexcept { return os_name_; } |
| |
| /** |
| * @brief Returns the server operating-system version. |
| * @return Operating-system version owned by this value. |
| */ |
| [[nodiscard]] const std::string &OsVersion() const noexcept { return os_version_; } |
| |
| /** |
| * @brief Returns the server kernel version. |
| * @return Kernel version owned by this value. |
| */ |
| [[nodiscard]] const std::string &KernelVersion() const noexcept { return kernel_version_; } |
| |
| /** |
| * @brief Returns the human-readable Iggy server version. |
| * @return Version string owned by this value. |
| */ |
| [[nodiscard]] const std::string &IggyServerVersion() const noexcept { return iggy_server_version_; } |
| |
| /** |
| * @brief Returns the numeric semantic version when reported by the server. |
| * @return `major * 1,000,000 + minor * 1,000 + patch`, or `std::nullopt` |
| * when the server does not report a numeric version. |
| */ |
| [[nodiscard]] const std::optional<std::uint32_t> &ServerSemver() const noexcept { return server_semver_; } |
| |
| /** |
| * @brief Returns partition cache metrics reported by the server. |
| * @return Entries owned by this value. The current VSR server returns an |
| * empty collection. |
| */ |
| [[nodiscard]] const std::vector<CacheMetricEntry> &CacheMetrics() const noexcept { return cache_metrics_; } |
| |
| /** |
| * @brief Returns the number of threads in the server process. |
| * @return Process thread count. |
| */ |
| [[nodiscard]] std::uint32_t ThreadsCount() const noexcept { return threads_count_; } |
| |
| /** |
| * @brief Returns free space on the server data-directory volume. |
| * @return Free space in bytes, or zero when the probe is unavailable. |
| */ |
| [[nodiscard]] std::uint64_t FreeDiskSpace() const noexcept { return free_disk_space_; } |
| |
| /** |
| * @brief Returns total space on the server data-directory volume. |
| * @return Total space in bytes, or zero when the probe is unavailable. |
| */ |
| [[nodiscard]] std::uint64_t TotalDiskSpace() const noexcept { return total_disk_space_; } |
| |
| private: |
| Stats(std::uint32_t process_id, |
| float cpu_usage, |
| float total_cpu_usage, |
| std::uint64_t memory_usage, |
| std::uint64_t total_memory, |
| std::uint64_t available_memory, |
| std::uint64_t run_time_micros, |
| std::uint64_t start_time_epoch_micros, |
| std::uint64_t read_bytes, |
| std::uint64_t written_bytes, |
| std::uint64_t messages_size_bytes, |
| std::uint32_t streams_count, |
| std::uint32_t topics_count, |
| std::uint32_t partitions_count, |
| std::uint32_t segments_count, |
| std::uint64_t messages_count, |
| std::uint32_t clients_count, |
| std::uint32_t consumer_groups_count, |
| std::string hostname, |
| std::string os_name, |
| std::string os_version, |
| std::string kernel_version, |
| std::string iggy_server_version, |
| std::optional<std::uint32_t> server_semver, |
| std::vector<CacheMetricEntry> cache_metrics, |
| std::uint32_t threads_count, |
| std::uint64_t free_disk_space, |
| std::uint64_t total_disk_space) |
| : process_id_(process_id), |
| cpu_usage_(cpu_usage), |
| total_cpu_usage_(total_cpu_usage), |
| memory_usage_(memory_usage), |
| total_memory_(total_memory), |
| available_memory_(available_memory), |
| run_time_micros_(run_time_micros), |
| start_time_epoch_micros_(start_time_epoch_micros), |
| read_bytes_(read_bytes), |
| written_bytes_(written_bytes), |
| messages_size_bytes_(messages_size_bytes), |
| streams_count_(streams_count), |
| topics_count_(topics_count), |
| partitions_count_(partitions_count), |
| segments_count_(segments_count), |
| messages_count_(messages_count), |
| clients_count_(clients_count), |
| consumer_groups_count_(consumer_groups_count), |
| hostname_(std::move(hostname)), |
| os_name_(std::move(os_name)), |
| os_version_(std::move(os_version)), |
| kernel_version_(std::move(kernel_version)), |
| iggy_server_version_(std::move(iggy_server_version)), |
| server_semver_(server_semver), |
| cache_metrics_(std::move(cache_metrics)), |
| threads_count_(threads_count), |
| free_disk_space_(free_disk_space), |
| total_disk_space_(total_disk_space) {} |
| |
| static Stats FromFfi(ffi::Stats stats); |
| |
| friend class IggyBlockingClient; |
| |
| std::uint32_t process_id_; |
| float cpu_usage_; |
| float total_cpu_usage_; |
| std::uint64_t memory_usage_; |
| std::uint64_t total_memory_; |
| std::uint64_t available_memory_; |
| std::uint64_t run_time_micros_; |
| std::uint64_t start_time_epoch_micros_; |
| std::uint64_t read_bytes_; |
| std::uint64_t written_bytes_; |
| std::uint64_t messages_size_bytes_; |
| std::uint32_t streams_count_; |
| std::uint32_t topics_count_; |
| std::uint32_t partitions_count_; |
| std::uint32_t segments_count_; |
| std::uint64_t messages_count_; |
| std::uint32_t clients_count_; |
| std::uint32_t consumer_groups_count_; |
| std::string hostname_; |
| std::string os_name_; |
| std::string os_version_; |
| std::string kernel_version_; |
| std::string iggy_server_version_; |
| std::optional<std::uint32_t> server_semver_; |
| std::vector<CacheMetricEntry> cache_metrics_; |
| std::uint32_t threads_count_; |
| std::uint64_t free_disk_space_; |
| std::uint64_t total_disk_space_; |
| }; |
| |
| /** |
| * @brief Compression algorithm used for topic messages. |
| * |
| * Selects whether messages in a topic are stored as-is or compressed with |
| * gzip. |
| * |
| * @note The value is passed across the Rust FFI as a string. The Rust client |
| * rejects unsupported values. |
| */ |
| class CompressionAlgorithm final : private detail::StringTag<CompressionAlgorithm> { |
| public: |
| /** @brief Returns the uncompressed storage option. */ |
| static CompressionAlgorithm None() { return CompressionAlgorithm("none"); } |
| |
| /** @brief Returns the gzip compression option. */ |
| static CompressionAlgorithm Gzip() { return CompressionAlgorithm("gzip"); } |
| |
| /** |
| * @brief Returns the compression algorithm name. |
| * @return Compression algorithm name. |
| */ |
| [[nodiscard]] std::string_view Value() const { return detail::StringTag<CompressionAlgorithm>::Value(); } |
| |
| private: |
| explicit CompressionAlgorithm(std::string algorithm) |
| : detail::StringTag<CompressionAlgorithm>(std::move(algorithm)) {} |
| }; |
| |
| /** |
| * @brief Compression algorithm used for system snapshot archives. |
| * |
| * Selects how snapshot data is compressed in the generated archive. |
| * |
| * @note The value is passed across the Rust FFI as a string. The Rust client |
| * rejects unsupported values. |
| */ |
| class SnapshotCompression final : private detail::StringTag<SnapshotCompression> { |
| public: |
| /** @brief Returns the uncompressed storage option. */ |
| static SnapshotCompression Stored() { return SnapshotCompression("stored"); } |
| |
| /** @brief Returns the Deflate compression option. */ |
| static SnapshotCompression Deflated() { return SnapshotCompression("deflated"); } |
| |
| /** @brief Uses bzip2 for better compression with slower processing. */ |
| static SnapshotCompression Bzip2() { return SnapshotCompression("bzip2"); } |
| |
| /** @brief Uses Zstandard for fast compression and decompression. */ |
| static SnapshotCompression Zstd() { return SnapshotCompression("zstd"); } |
| |
| /** @brief Uses LZMA for high compression, especially for larger files. */ |
| static SnapshotCompression Lzma() { return SnapshotCompression("lzma"); } |
| |
| /** @brief Uses XZ for LZMA-like compression with faster decompression. */ |
| static SnapshotCompression Xz() { return SnapshotCompression("xz"); } |
| |
| /** |
| * @brief Returns the snapshot compression algorithm name. |
| * @return Snapshot compression algorithm name. |
| */ |
| [[nodiscard]] std::string_view Value() const { return detail::StringTag<SnapshotCompression>::Value(); } |
| |
| private: |
| explicit SnapshotCompression(std::string snapshot_compression) |
| : detail::StringTag<SnapshotCompression>(std::move(snapshot_compression)) {} |
| }; |
| |
| /** |
| * @brief Selects data to include in a system snapshot. |
| */ |
| class SystemSnapshotType final : private detail::StringTag<SystemSnapshotType> { |
| public: |
| /** @brief Includes an overview of the file-system structure. */ |
| static SystemSnapshotType FilesystemOverview() { return SystemSnapshotType("filesystem_overview"); } |
| |
| /** @brief Includes currently running processes. */ |
| static SystemSnapshotType ProcessList() { return SystemSnapshotType("process_list"); } |
| |
| /** @brief Includes CPU, memory, and other resource usage statistics. */ |
| static SystemSnapshotType ResourceUsage() { return SystemSnapshotType("resource_usage"); } |
| |
| /** @brief Includes the test snapshot used for development and testing. */ |
| static SystemSnapshotType Test() { return SystemSnapshotType("test"); } |
| |
| /** @brief Includes server logs from the configured logging directory. */ |
| static SystemSnapshotType ServerLogs() { return SystemSnapshotType("server_logs"); } |
| |
| /** @brief Includes server configuration. */ |
| static SystemSnapshotType ServerConfig() { return SystemSnapshotType("server_config"); } |
| |
| /** @brief Includes all available snapshot data. */ |
| static SystemSnapshotType All() { return SystemSnapshotType("all"); } |
| |
| /** |
| * @brief Returns the value passed to the client implementation. |
| * @return System snapshot type name. |
| */ |
| [[nodiscard]] std::string_view SnapshotTypeValue() const { return Value(); } |
| |
| private: |
| explicit SystemSnapshotType(std::string snapshot_type) |
| : detail::StringTag<SystemSnapshotType>(std::move(snapshot_type)) {} |
| }; |
| |
| /** |
| * @brief Maximum retained size of a topic. |
| * |
| * A topic may use the server default, have no size limit, or use an explicit |
| * byte limit. |
| * |
| * Use ServerDefault(), Unlimited(), or FromBytes() to select the retention |
| * limit. |
| */ |
| class MaxTopicSize final : private detail::StringTag<MaxTopicSize> { |
| public: |
| /** @brief Returns the server-default size option. */ |
| static MaxTopicSize ServerDefault() { return MaxTopicSize("server_default"); } |
| |
| /** @brief Returns the unlimited size option. */ |
| static MaxTopicSize Unlimited() { return MaxTopicSize("unlimited"); } |
| |
| /** |
| * @brief Creates an explicit topic size limit. |
| * @param bytes Maximum topic size in bytes. |
| * @return Server-default size for zero, unlimited size for |
| * std::numeric_limits<std::uint64_t>::max(), or the requested limit. |
| * @note The configured limit cannot be smaller than the server segment size. |
| */ |
| static MaxTopicSize FromBytes(std::uint64_t bytes) { |
| if (bytes == 0) { |
| return ServerDefault(); |
| } |
| if (bytes == std::numeric_limits<std::uint64_t>::max()) { |
| return Unlimited(); |
| } |
| return MaxTopicSize(std::to_string(bytes)); |
| } |
| |
| /** |
| * @brief Returns the value passed to the client implementation. |
| * @return Topic size option or decimal byte count. |
| */ |
| [[nodiscard]] std::string_view Value() const { return detail::StringTag<MaxTopicSize>::Value(); } |
| |
| private: |
| explicit MaxTopicSize(std::string max_topic_size) : detail::StringTag<MaxTopicSize>(std::move(max_topic_size)) {} |
| }; |
| |
| /** |
| * @brief Message retention policy for a topic. |
| * |
| * Use ServerDefault(), NeverExpire(), or Duration() to select the retention |
| * policy. |
| */ |
| class Expiry final { |
| public: |
| /** @brief Returns the server-default expiry policy. */ |
| static Expiry ServerDefault() { return Expiry("server_default", 0); } |
| |
| /** |
| * @brief Keeps messages until another operation removes them, such as |
| * topic deletion. |
| */ |
| static Expiry NeverExpire() { return Expiry("never_expire", std::numeric_limits<std::uint64_t>::max()); } |
| |
| /** |
| * @brief Creates a time-based expiry policy. |
| * @param micros Message lifetime in microseconds. |
| * @return Time-based expiry policy. |
| * @throws std::invalid_argument if @p micros is zero. |
| */ |
| static Expiry Duration(std::uint64_t micros) { |
| if (micros == 0) { |
| throw std::invalid_argument("Expiry duration must be greater than zero"); |
| } |
| return Expiry("duration", micros); |
| } |
| |
| /** |
| * @brief Returns the expiry policy kind. |
| * @return One of server_default, never_expire, or duration. |
| */ |
| [[nodiscard]] std::string_view Kind() const { return expiry_kind_; } |
| |
| /** |
| * @brief Returns the value associated with the expiry policy. |
| * @return Duration in microseconds for Duration(), zero for ServerDefault(), |
| * or std::numeric_limits<std::uint64_t>::max() for NeverExpire(). |
| */ |
| [[nodiscard]] std::uint64_t Value() const { return expiry_value_; } |
| |
| private: |
| explicit Expiry(std::string expiry_kind, std::uint64_t expiry_value) |
| : expiry_kind_(std::move(expiry_kind)), expiry_value_(expiry_value) {} |
| |
| std::string expiry_kind_; |
| std::uint64_t expiry_value_; |
| }; |
| |
| /** |
| * @brief Storage guarantee required before an operation reports completion. |
| * |
| * Both policies persist data through the replicated journal. Replicated waits |
| * for quorum commit without an additional stable-storage barrier. Persisted |
| * also requires recoverable stable-storage copies on the quorum. Topic message |
| * durability and consumer-offset durability are configured independently. |
| */ |
| enum class Durability : std::uint8_t { |
| Replicated, ///< Wait for quorum commit. |
| Persisted, ///< Wait for quorum commit backed by stable storage. |
| }; |
| |
| /** |
| * @brief Returns the protocol option name for a durability policy. |
| * @param durability Durability policy to encode. |
| * @return `replicated` or `persisted`. |
| * @throws std::invalid_argument if @p durability is not a declared enumerator. |
| */ |
| constexpr std::string_view to_string(const Durability durability) { |
| switch (durability) { |
| case Durability::Replicated: |
| return "replicated"; |
| case Durability::Persisted: |
| return "persisted"; |
| } |
| throw std::invalid_argument("Unknown durability"); |
| } |
| |
| /** |
| * @brief Options for creating a topic. |
| * |
| * Use the typed setters to configure supported topic settings. Leave a setting |
| * unset to use the server default. Use SetRawEntries() for supported options |
| * that do not yet have a typed setter. When both specify the same option, the |
| * typed setting takes precedence. |
| */ |
| class TopicCreateOptions final { |
| public: |
| /** @brief Creates options with every setting left to the server default. */ |
| TopicCreateOptions() = default; |
| |
| /** |
| * @brief Returns the number of partitions to create. |
| * @return Configured partition count, or `std::nullopt` to default to 1. |
| */ |
| [[nodiscard]] std::optional<std::uint32_t> PartitionsCount() const noexcept { return partitions_count_; } |
| |
| /** |
| * @brief Sets the number of partitions to create. |
| * @param partitions_count Number of partitions, from 0 to 1,000 inclusive. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetPartitionsCount(std::uint32_t partitions_count) noexcept { |
| partitions_count_ = partitions_count; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the topic storage compression setting. |
| * @return Configured compression algorithm, or `std::nullopt` to use the |
| * server default. |
| */ |
| [[nodiscard]] const std::optional<::iggy::CompressionAlgorithm> &CompressionAlgorithm() const noexcept { |
| return compression_algorithm_; |
| } |
| |
| /** |
| * @brief Sets the topic storage compression algorithm. |
| * @param compression_algorithm Compression algorithm to use. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetCompressionAlgorithm(::iggy::CompressionAlgorithm compression_algorithm) { |
| compression_algorithm_ = std::move(compression_algorithm); |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the message retention policy. |
| * @return Configured expiry policy, or `std::nullopt` to use the server |
| * default. |
| */ |
| [[nodiscard]] const std::optional<::iggy::Expiry> &MessageExpiry() const noexcept { return message_expiry_; } |
| |
| /** |
| * @brief Sets the message retention policy. |
| * @param message_expiry Expiry policy to apply. Expiry::ServerDefault() |
| * clears an explicitly configured policy. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetMessageExpiry(::iggy::Expiry message_expiry) { |
| if (message_expiry.Kind() == "server_default") { |
| message_expiry_.reset(); |
| } else { |
| message_expiry_ = std::move(message_expiry); |
| } |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the maximum retained topic size. |
| * @return Configured size limit, or `std::nullopt` to use the server |
| * default. |
| */ |
| [[nodiscard]] const std::optional<::iggy::MaxTopicSize> &MaxTopicSize() const noexcept { return max_topic_size_; } |
| |
| /** |
| * @brief Sets the maximum retained topic size. |
| * @param max_topic_size Maximum size to retain. The limit cannot be smaller |
| * than the configured segment size. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetMaxTopicSize(::iggy::MaxTopicSize max_topic_size) { |
| if (max_topic_size.Value() == "server_default") { |
| max_topic_size_.reset(); |
| } else { |
| max_topic_size_ = std::move(max_topic_size); |
| } |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the partition segment size. |
| * @return Configured segment size in bytes, or `std::nullopt` to use the |
| * server default. |
| */ |
| [[nodiscard]] std::optional<std::uint64_t> SegmentSize() const noexcept { return segment_size_; } |
| |
| /** |
| * @brief Sets the size at which each partition segment rotates. |
| * @param segment_size Segment size in bytes. Specify zero to use the server |
| * default; otherwise it must be a multiple of 512 between 1 MiB and |
| * 1 GiB inclusive. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetSegmentSize(std::uint64_t segment_size) noexcept { |
| segment_size_ = segment_size; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the message completion policy. |
| * @return Configured policy, or `std::nullopt` to use the server default |
| * (`replicated`). |
| */ |
| [[nodiscard]] std::optional<::iggy::Durability> Durability() const noexcept { return durability_; } |
| |
| /** |
| * @brief Sets the message completion policy. |
| * @param durability `replicated` or `persisted`, independent of the |
| * consumer-offset policy. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetDurability(::iggy::Durability durability) noexcept { |
| durability_ = durability; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the consumer-offset completion policy. |
| * @return Configured policy, or `std::nullopt` to use the server default |
| * (`replicated`). |
| */ |
| [[nodiscard]] std::optional<::iggy::Durability> ConsumerOffsetDurability() const noexcept { |
| return consumer_offset_durability_; |
| } |
| |
| /** |
| * @brief Sets the consumer-offset completion policy. |
| * @param durability `replicated` or `persisted`, independent of the |
| * message policy. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetConsumerOffsetDurability(::iggy::Durability durability) noexcept { |
| consumer_offset_durability_ = durability; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the message-count threshold for flushing the journal. |
| * @return Configured threshold, or `std::nullopt` to use the server default. |
| */ |
| [[nodiscard]] std::optional<std::uint32_t> MessagesRequiredToSave() const noexcept { |
| return messages_required_to_save_; |
| } |
| |
| /** |
| * @brief Sets the message-count threshold for flushing the journal. |
| * |
| * The journal is flushed when this or the byte threshold is reached first. |
| * @param messages_required_to_save Number of messages, from 1 to 16,777,216 |
| * inclusive. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetMessagesRequiredToSave(std::uint32_t messages_required_to_save) noexcept { |
| messages_required_to_save_ = messages_required_to_save; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the byte threshold for flushing the journal. |
| * @return Configured threshold in bytes, or `std::nullopt` to use the |
| * server default. |
| */ |
| [[nodiscard]] std::optional<std::uint64_t> SizeOfMessagesRequiredToSave() const noexcept { |
| return size_of_messages_required_to_save_; |
| } |
| |
| /** |
| * @brief Sets the byte threshold for flushing the journal. |
| * |
| * The journal is flushed when this or the message-count threshold is reached |
| * first. |
| * @param size_of_messages_required_to_save Size in bytes. Specify zero to |
| * use the server default; otherwise it must be between 1 and 1 GiB |
| * inclusive. |
| * @return Reference to this options object. |
| */ |
| TopicCreateOptions &SetSizeOfMessagesRequiredToSave(std::uint64_t size_of_messages_required_to_save) noexcept { |
| size_of_messages_required_to_save_ = size_of_messages_required_to_save; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns whether partition segments are preallocated on disk. |
| * @return Configured setting, or `std::nullopt` to use the server default. |
| */ |
| [[nodiscard]] std::optional<bool> PreallocateSegments() const noexcept { return preallocate_segments_; } |
| |
| /** |
| * @brief Sets whether partition segments are preallocated on disk. |
| * @param preallocate_segments `true` to reserve segment space during topic |
| * creation; `false` otherwise. |
| * @return Reference to this options object. |
| * @note The total preallocated space cannot exceed 64 GiB. |
| */ |
| TopicCreateOptions &SetPreallocateSegments(bool preallocate_segments) noexcept { |
| preallocate_segments_ = preallocate_segments; |
| return *this; |
| } |
| |
| /** |
| * @brief Returns additional topic settings as key-value pairs. |
| * |
| * Use this for supported settings that do not have a dedicated setter. |
| * @return Ordered map of setting names and values. |
| * @note A dedicated setter takes precedence when it configures the same |
| * setting. |
| */ |
| [[nodiscard]] const std::map<std::string, std::string> &RawEntries() const noexcept { return raw_; } |
| |
| /** |
| * @brief Adds or replaces additional topic settings. |
| * @param entries Setting names and values to add. |
| * @return Reference to this options object. |
| * @note Unsupported names and invalid values are rejected when the topic is |
| * created. Use SetPartitionsCount() rather than an entry for the |
| * partition count. |
| */ |
| TopicCreateOptions &SetRawEntries(const std::map<std::string, std::string> &entries) { |
| for (const auto &entry : entries) { |
| raw_.insert_or_assign(entry.first, entry.second); |
| } |
| return *this; |
| } |
| /** |
| * @brief Adds or replaces additional topic settings. |
| * @param entries Setting names and values to move into this options object. |
| * @return Reference to this options object. |
| * @see SetRawEntries(const std::map<std::string, std::string>&) |
| */ |
| TopicCreateOptions &SetRawEntries(std::map<std::string, std::string> &&entries) { |
| while (!entries.empty()) { |
| auto node = entries.extract(entries.begin()); |
| raw_.erase(node.key()); |
| raw_.insert(std::move(node)); |
| } |
| return *this; |
| } |
| |
| private: |
| std::optional<std::uint32_t> partitions_count_; |
| std::optional<::iggy::CompressionAlgorithm> compression_algorithm_; |
| std::optional<::iggy::Expiry> message_expiry_; |
| std::optional<::iggy::MaxTopicSize> max_topic_size_; |
| std::optional<std::uint64_t> segment_size_; |
| std::optional<::iggy::Durability> durability_; |
| std::optional<::iggy::Durability> consumer_offset_durability_; |
| std::optional<std::uint32_t> messages_required_to_save_; |
| std::optional<std::uint64_t> size_of_messages_required_to_save_; |
| std::optional<bool> preallocate_segments_; |
| std::map<std::string, std::string> raw_; |
| |
| friend class IggyBlockingClient; |
| }; |
| |
| /** |
| * @brief Options for updating a topic. |
| * |
| * Use this class to change a topic's mutable settings. Leave a setting unset |
| * to retain its current value. Topic creation settings, such as the partition |
| * count and segment size, cannot be changed after the topic is created. |
| * |
| * Use the typed setters for supported settings. SetRawEntries() can configure |
| * other supported mutable settings. When both configure the same setting, the |
| * typed setting takes precedence. |
| */ |
| class TopicUpdateOptions final { |
| public: |
| /** @brief Creates an update that leaves every topic setting unchanged. */ |
| TopicUpdateOptions() = default; |
| |
| /** |
| * @brief Returns the requested storage compression update. |
| * @return Compression algorithm to apply, or `std::nullopt` when this |
| * update leaves compression unchanged. |
| */ |
| [[nodiscard]] const std::optional<::iggy::CompressionAlgorithm> &CompressionAlgorithm() const noexcept { |
| return compression_algorithm_; |
| } |
| |
| /** |
| * @brief Sets the storage compression algorithm. |
| * @param compression_algorithm Compression algorithm to apply. |
| * @return Reference to this options object. |
| */ |
| TopicUpdateOptions &SetCompressionAlgorithm(::iggy::CompressionAlgorithm compression_algorithm) { |
| compression_algorithm_ = std::move(compression_algorithm); |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the requested message retention update. |
| * @return Expiry policy to apply, or `std::nullopt` when this update leaves |
| * retention unchanged. |
| */ |
| [[nodiscard]] const std::optional<::iggy::Expiry> &MessageExpiry() const noexcept { return message_expiry_; } |
| |
| /** |
| * @brief Sets the message retention policy. |
| * @param message_expiry Expiry policy to apply. Expiry::ServerDefault() |
| * leaves the current policy unchanged. |
| * @return Reference to this options object. |
| */ |
| TopicUpdateOptions &SetMessageExpiry(::iggy::Expiry message_expiry) { |
| if (message_expiry.Kind() == "server_default") { |
| message_expiry_.reset(); |
| } else { |
| message_expiry_ = std::move(message_expiry); |
| } |
| return *this; |
| } |
| |
| /** |
| * @brief Returns the requested maximum retained-size update. |
| * @return Size limit to apply, or `std::nullopt` when this update leaves |
| * the limit unchanged. |
| */ |
| [[nodiscard]] const std::optional<::iggy::MaxTopicSize> &MaxTopicSize() const noexcept { return max_topic_size_; } |
| |
| /** |
| * @brief Sets the maximum retained topic size. |
| * @param max_topic_size Maximum size to retain. MaxTopicSize::ServerDefault() |
| * leaves the current limit unchanged. |
| * @return Reference to this options object. |
| */ |
| TopicUpdateOptions &SetMaxTopicSize(::iggy::MaxTopicSize max_topic_size) { |
| if (max_topic_size.Value() == "server_default") { |
| max_topic_size_.reset(); |
| } else { |
| max_topic_size_ = std::move(max_topic_size); |
| } |
| return *this; |
| } |
| |
| /** |
| * @brief Returns additional mutable topic settings as key-value pairs. |
| * |
| * Use this for supported settings that do not have a dedicated setter. |
| * @return Ordered map of setting names and values. |
| * @note A dedicated setter takes precedence when it configures the same |
| * setting. |
| */ |
| [[nodiscard]] const std::map<std::string, std::string> &RawEntries() const noexcept { return raw_; } |
| |
| /** |
| * @brief Adds or replaces additional mutable topic settings. |
| * @param entries Setting names and values to add. |
| * @return Reference to this options object. |
| * @note Unsupported, immutable, or invalid settings are rejected when the |
| * topic is updated. |
| */ |
| TopicUpdateOptions &SetRawEntries(const std::map<std::string, std::string> &entries) { |
| for (const auto &entry : entries) { |
| raw_.insert_or_assign(entry.first, entry.second); |
| } |
| return *this; |
| } |
| /** |
| * @brief Adds or replaces additional mutable topic settings. |
| * @param entries Setting names and values to move into this options object. |
| * @return Reference to this options object. |
| * @see SetRawEntries(const std::map<std::string, std::string>&) |
| */ |
| TopicUpdateOptions &SetRawEntries(std::map<std::string, std::string> &&entries) { |
| while (!entries.empty()) { |
| auto node = entries.extract(entries.begin()); |
| raw_.erase(node.key()); |
| raw_.insert(std::move(node)); |
| } |
| return *this; |
| } |
| |
| private: |
| std::optional<::iggy::CompressionAlgorithm> compression_algorithm_; |
| std::optional<::iggy::Expiry> message_expiry_; |
| std::optional<::iggy::MaxTopicSize> max_topic_size_; |
| std::map<std::string, std::string> raw_; |
| |
| friend class IggyBlockingClient; |
| }; |
| |
| /** |
| * @brief Options for updating a stream. |
| * |
| * Use this class to supply stream settings to UpdateStream(). Currently, Iggy |
| * does not support updating stream settings, so the server rejects every |
| * supplied setting. The raw entries are retained for compatibility with future |
| * server versions that add mutable stream settings. |
| */ |
| class StreamUpdateOptions final { |
| public: |
| /** @brief Creates an update with no requested stream settings. */ |
| StreamUpdateOptions() = default; |
| |
| /** |
| * @brief Returns the requested stream settings as key-value pairs. |
| * @return Ordered map of setting names and values. |
| * @note The server currently rejects all stream settings. |
| */ |
| [[nodiscard]] const std::map<std::string, std::string> &RawEntries() const noexcept { return raw_; } |
| |
| /** |
| * @brief Adds or replaces requested stream settings. |
| * @param entries Setting names and values to add. |
| * @return Reference to this options object. |
| * @note The server currently rejects all stream settings. |
| */ |
| StreamUpdateOptions &SetRawEntries(const std::map<std::string, std::string> &entries) { |
| for (const auto &entry : entries) { |
| raw_.insert_or_assign(entry.first, entry.second); |
| } |
| return *this; |
| } |
| /** |
| * @brief Adds or replaces requested stream settings. |
| * @param entries Setting names and values to move into this options object. |
| * @return Reference to this options object. |
| * @see SetRawEntries(const std::map<std::string, std::string>&) |
| * @note The server currently rejects all stream settings. |
| */ |
| StreamUpdateOptions &SetRawEntries(std::map<std::string, std::string> &&entries) { |
| while (!entries.empty()) { |
| auto node = entries.extract(entries.begin()); |
| raw_.erase(node.key()); |
| raw_.insert(std::move(node)); |
| } |
| return *this; |
| } |
| |
| private: |
| std::map<std::string, std::string> raw_; |
| |
| friend class IggyBlockingClient; |
| }; |
| |
| /** |
| * @brief Options for updating a user. |
| * |
| * Use this class to supply user settings to UpdateUser(). Updating a user |
| * patches only the supplied settings; omitted settings remain unchanged. |
| * Currently, Iggy does not support updating user settings, so the server |
| * rejects every supplied setting. The raw entries are retained for |
| * compatibility with future server versions that add mutable user settings. |
| */ |
| class UserUpdateOptions final { |
| public: |
| /** @brief Creates an update with no requested user settings. */ |
| UserUpdateOptions() = default; |
| |
| /** |
| * @brief Returns the requested user settings as key-value pairs. |
| * @return Ordered map of setting names and values. |
| * @note The server currently rejects all user settings. |
| */ |
| [[nodiscard]] const std::map<std::string, std::string> &RawEntries() const noexcept { return raw_; } |
| |
| /** |
| * @brief Adds or replaces requested user settings. |
| * @param entries Setting names and values to add. |
| * @return Reference to this options object. |
| * @note The server currently rejects all user settings. |
| */ |
| UserUpdateOptions &SetRawEntries(const std::map<std::string, std::string> &entries) { |
| for (const auto &entry : entries) { |
| raw_.insert_or_assign(entry.first, entry.second); |
| } |
| return *this; |
| } |
| /** |
| * @brief Adds or replaces requested user settings. |
| * @param entries Setting names and values to move into this options object. |
| * @return Reference to this options object. |
| * @see SetRawEntries(const std::map<std::string, std::string>&) |
| * @note The server currently rejects all user settings. |
| */ |
| UserUpdateOptions &SetRawEntries(std::map<std::string, std::string> &&entries) { |
| while (!entries.empty()) { |
| auto node = entries.extract(entries.begin()); |
| raw_.erase(node.key()); |
| raw_.insert(std::move(node)); |
| } |
| return *this; |
| } |
| |
| private: |
| std::map<std::string, std::string> raw_; |
| |
| friend class IggyBlockingClient; |
| }; |
| |
| /** |
| * @brief Starting position for polling messages. |
| * |
| * @note The strategy kind and value are passed across the Rust FFI as a pair. |
| * The Rust client rejects unsupported kinds. |
| */ |
| class PollingStrategy final { |
| public: |
| /** |
| * @brief Starts polling at a message offset. |
| * @param value Message offset. |
| * @return Offset-based polling strategy. |
| */ |
| static PollingStrategy Offset(std::uint64_t value) { return PollingStrategy("offset", value); } |
| |
| /** |
| * @brief Starts polling at a timestamp. |
| * @param value Timestamp value expected by the Iggy protocol. |
| * @return Timestamp-based polling strategy. |
| */ |
| static PollingStrategy Timestamp(std::uint64_t value) { return PollingStrategy("timestamp", value); } |
| |
| /** @brief Starts polling with the first message in the partition. */ |
| static PollingStrategy First() { return PollingStrategy("first", 0); } |
| |
| /** @brief Starts polling with the last available message in the partition. */ |
| static PollingStrategy Last() { return PollingStrategy("last", 0); } |
| |
| /** |
| * @brief Returns a strategy that starts after the stored consumer offset. |
| * @note Typically used with automatic offset commits enabled. |
| */ |
| static PollingStrategy Next() { return PollingStrategy("next", 0); } |
| |
| /** |
| * @brief Returns the polling strategy kind. |
| * @return One of offset, timestamp, first, last, or next. |
| */ |
| [[nodiscard]] std::string_view Kind() const { return polling_strategy_kind_; } |
| |
| /** |
| * @brief Returns the value associated with the polling strategy. |
| * @return Offset or timestamp for parameterized strategies; otherwise zero. |
| */ |
| [[nodiscard]] std::uint64_t Value() const { return polling_strategy_value_; } |
| |
| private: |
| explicit PollingStrategy(std::string kind, std::uint64_t value) |
| : polling_strategy_kind_(std::move(kind)), polling_strategy_value_(value) {} |
| |
| std::string polling_strategy_kind_; |
| std::uint64_t polling_strategy_value_; |
| }; |
| |
| /** |
| * @brief Owning client connection to an Apache Iggy server. |
| * |
| * Create instances with Builder or FromConnectionString(). The client owns a |
| * handle to the underlying Rust client. Destroying the C++ object releases that |
| * handle. The Rust client aborts its heartbeat task when it is dropped. |
| * |
| * Builder initializes a TCP client. To use QUIC, HTTP, or WebSocket, create the |
| * client with FromConnectionString(). |
| * |
| * @code{.cpp} |
| * auto client{iggy::IggyBlockingClient::Builder() |
| * .WithServerAddress("127.0.0.1:8090") |
| * .Build()}; |
| * client.Connect(); |
| * client.Login("iggy", "iggy"); |
| * client.Shutdown(); |
| * @endcode |
| */ |
| class IggyBlockingClient final { |
| public: |
| class Builder; |
| |
| /** @brief IggyBlockingClient is move-only. */ |
| IggyBlockingClient(const IggyBlockingClient &) = delete; |
| IggyBlockingClient &operator=(const IggyBlockingClient &) = delete; |
| |
| /** |
| * @brief Transfers ownership of a client. |
| * @param other Client whose connection ownership is transferred. |
| * |
| * The moved-from client may be destroyed or assigned a new value, but must |
| * not be used for client operations. |
| */ |
| IggyBlockingClient(IggyBlockingClient &&other) noexcept; |
| |
| /** |
| * @brief Replaces this client by taking ownership from another client. |
| * @param other Client whose connection ownership is transferred. |
| * @return Reference to this client. |
| * |
| * Any Rust client handle currently owned by this object is released first. |
| * Call Shutdown() before replacing a connected client. The moved-from |
| * client must not be used for client operations. |
| */ |
| IggyBlockingClient &operator=(IggyBlockingClient &&other) noexcept; |
| |
| /** |
| * @brief Releases the handle to the underlying Rust client. |
| * |
| * Dropping the underlying Rust client aborts its heartbeat task. Cleanup |
| * errors cannot be reported from the destructor. |
| */ |
| ~IggyBlockingClient(); |
| |
| /** |
| * @brief Creates a client from an Iggy connection string. |
| * |
| * Connection strings use one of these forms: |
| * |
| * - `iggy://<credentials>@<host>:<port>[?<options>]` for TCP. |
| * - `iggy+tcp://<credentials>@<host>:<port>[?<options>]` for TCP. |
| * - `iggy+quic://<credentials>@<host>:<port>[?<options>]` for QUIC. |
| * - `iggy+http://<credentials>@<host>:<port>[?<options>]` for HTTP. |
| * - `iggy+ws://<credentials>@<host>:<port>[?<options>]` for WebSocket. |
| * |
| * Credentials are either `<username>:<password>` or a personal access |
| * token. Multiple query parameters are separated with `&`. |
| * |
| * Connection string examples: |
| * |
| * - Username and password: |
| * `iggy+tcp://iggy:iggy@127.0.0.1:8090` |
| * - Personal access token: |
| * `iggy+tcp://iggypat-1234567890abcdef@127.0.0.1:8090` |
| * - TCP with TLS: |
| * `iggy+tcp://iggy:iggy@localhost:8090?tls=true&tls_domain=localhost` |
| * |
| * TCP accepts these query parameters: |
| * |
| * - `tls=<bool>` |
| * - `tls_domain=<string>` |
| * - `tls_ca_file=<path>` |
| * - `reconnection_retries=<uint32|unlimited>` |
| * - `reconnection_interval=<duration>` |
| * - `reestablish_after=<duration>` |
| * - `heartbeat_interval=<duration>` |
| * - `nodelay=<bool>` |
| * |
| * QUIC accepts these query parameters: |
| * |
| * - `response_buffer_size=<uint64>` |
| * - `max_concurrent_bidi_streams=<uint64>` |
| * - `datagram_send_buffer_size=<uint64>` |
| * - `initial_mtu=<uint16>` |
| * - `send_window=<uint64>` |
| * - `receive_window=<uint64>` |
| * - `keep_alive_interval=<uint64>` |
| * - `max_idle_timeout=<uint64>` |
| * - `validate_certificate=<bool>` |
| * - `heartbeat_interval=<duration>` |
| * - `reconnection_max_retries=<uint32|unlimited>` |
| * - `reconnection_interval=<duration>` |
| * - `reconnection_reestablish_after=<duration>` |
| * |
| * HTTP accepts these query parameters: |
| * |
| * - `heartbeat_interval=<duration>` |
| * - `retries=<uint32>` |
| * |
| * WebSocket accepts these query parameters: |
| * |
| * - `heartbeat_interval=<duration>` |
| * - `reconnection_retries=<uint32|unlimited>` |
| * - `reconnection_interval=<duration>` |
| * - `reestablish_after=<duration>` |
| * - `read_buffer_size=<unsigned integer>` |
| * - `write_buffer_size=<unsigned integer>` |
| * - `max_write_buffer_size=<unsigned integer>` |
| * - `max_message_size=<unsigned integer>` |
| * - `max_frame_size=<unsigned integer>` |
| * - `accept_unmasked_frames=<bool>` |
| * - `tls=<bool>` |
| * - `tls_domain=<string>` |
| * - `tls_ca_file=<path>` |
| * - `tls_validate_certificate=<bool>` |
| * |
| * Durations use Iggy duration syntax, such as `500ms`, `5s`, or `1min`. |
| * Boolean values are `true` or `false`. |
| * |
| * Credentials embedded in the connection string configure automatic login |
| * for Connect() and later reconnections. This method parses configuration |
| * but does not establish a network connection. |
| * |
| * @param connection_string Connection string containing client configuration. |
| * @return Configured, disconnected client. |
| * @throws IggyException if the connection string is invalid or the client |
| * cannot be created. |
| */ |
| static IggyBlockingClient FromConnectionString(std::string connection_string); |
| |
| /** |
| * @brief Connects to the configured Iggy server. |
| * |
| * Establishes the configured transport connection and starts heartbeat |
| * processing. If automatic login was configured, authentication is also |
| * performed. |
| * |
| * @note HTTP is stateless; connecting initializes heartbeat processing but |
| * does not open a persistent transport connection. |
| * @note Repeated calls do not start additional heartbeat tasks. An existing |
| * heartbeat task is reused while it is still running. |
| * @note The default reconnection limit is unlimited. If the server remains |
| * unavailable, this method keeps retrying and blocks the caller. Use |
| * WithReconnectionMaxRetries() to bound the wait. |
| * @throws IggyException if automatic authentication fails, or if a finite |
| * reconnection limit is configured and exhausted. |
| */ |
| void Connect(); |
| |
| /** |
| * @brief Disconnects from the configured Iggy server. |
| * |
| * Disconnect is temporary. It drops the active transport connection and |
| * changes the client state to disconnected, but keeps the client reusable. |
| * Call Connect() to establish a new connection. Configured automatic login |
| * is applied when reconnecting. |
| * |
| * @note Disconnect() does not stop the existing heartbeat task. With |
| * automatic login configured, a heartbeat may reconnect and |
| * authenticate the client in the background. |
| * @note The HTTP transport is stateless and treats this operation as a |
| * no-op. |
| * @throws IggyException if the client cannot disconnect cleanly. |
| * @see Shutdown() |
| */ |
| void Disconnect(); |
| |
| /** |
| * @brief Shuts down the client and its background tasks. |
| * |
| * Shutdown is terminal for stateful transports. It gracefully closes the |
| * active transport where supported, releases transport resources, and |
| * changes the client state to shutdown. Binary operations then fail with a |
| * client-shutdown error. The background heartbeat task stops when it next |
| * observes that error. Create a new client instead of reusing a shut-down |
| * client. |
| * |
| * @note The HTTP transport is stateless and treats this operation as a |
| * no-op. |
| * @throws IggyException if shutdown fails. |
| * @see Disconnect() |
| */ |
| void Shutdown(); |
| |
| /** |
| * @brief Authenticates with a username and password. |
| * |
| * For TCP, QUIC, and WebSocket, call Connect() first. A successful login |
| * leaves the transport connected and marks the session authenticated. For |
| * HTTP, the returned access token is stored by the client and used for |
| * subsequent authenticated requests. |
| * |
| * @param username Iggy user name. |
| * @param password Iggy user password. |
| * @return Information about the authenticated session. |
| * @throws IggyException if authentication fails. |
| */ |
| LoginInfo Login(std::string username, std::string password); |
| |
| /** |
| * @brief Ends the current authenticated session. |
| * |
| * Logout does not disconnect the transport. For binary transports, the |
| * client returns to the connected but unauthenticated state. For HTTP, the |
| * stored access token is cleared after the server accepts the logout. |
| * Protected operations require another successful Login() or an automatic |
| * login during reconnection. |
| * |
| * @throws IggyException if logout fails. |
| * @see Disconnect() |
| */ |
| void Logout(); |
| |
| /** |
| * @brief Retrieves one user by numeric ID or name. |
| * |
| * An authenticated user may retrieve its own account without the global |
| * read-users grant. Reading another account requires read-users or |
| * manage-users permission. The result is a snapshot and includes the |
| * target user's optional permission assignment. |
| * |
| * @param user User to retrieve, addressed by numeric ID or name. |
| * @return Details for the requested user. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the identifier is invalid; the user does not exist; the caller |
| * lacks permission; or the request fails. |
| */ |
| UserInfoDetails GetUser(const Identifier &user); |
| |
| /** |
| * @brief Lists user summaries visible to the authenticated caller. |
| * |
| * The summaries omit permissions. Use GetUser() to retrieve one user's |
| * permission assignment. |
| * |
| * @return User summaries observed by the server for this request. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the caller lacks read-users or manage-users permission; or the |
| * request fails. |
| */ |
| std::vector<UserInfo> GetUsers(); |
| |
| /** |
| * @brief Creates a user account. |
| * |
| * User names must contain between 3 and 50 bytes and be unique. Passwords |
| * must contain between 3 and 100 bytes. An inactive account is created but |
| * cannot authenticate. Passing `std::nullopt` assigns no permission object; |
| * passing a default-constructed Permissions assigns an explicit permission |
| * object with no enabled grants. |
| * |
| * A failed or unknown transport outcome can leave the user created. Query |
| * the account by name before retrying this request. |
| * |
| * @param username Unique user name. |
| * @param password Initial user password. |
| * @param status Initial authentication status. |
| * @param permissions Optional permission assignment. |
| * @return Details of the newly created user. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the name, password, status, or permissions are invalid; the name |
| * is already in use; the caller lacks manage-users permission; or |
| * the request fails. |
| */ |
| UserInfoDetails CreateUser(std::string username, |
| std::string password, |
| UserStatus status, |
| const std::optional<Permissions> &permissions = std::nullopt); |
| |
| /** |
| * @brief Deletes a user account. |
| * |
| * The root user cannot be deleted. Deleting another user also removes its |
| * permission assignment and personal access tokens. A failed or unknown |
| * transport outcome can leave the deletion committed; look up the user |
| * before retrying. |
| * |
| * @param user User to delete, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the identifier is invalid; the user does not exist or is the |
| * root user; the caller lacks manage-users permission; or the |
| * request fails. |
| */ |
| void DeleteUser(const Identifier &user); |
| |
| /** |
| * @brief Changes a user's name, status, and mutable settings. |
| * |
| * A supplied name must contain between 3 and 50 bytes and remain unique. |
| * Setting the status to inactive prevents subsequent authentication. |
| * Passing `std::nullopt` for the name or status leaves that field |
| * unchanged. The supplied UserUpdateOptions changes only the settings it |
| * contains; settings left unset retain their current values. User settings |
| * are currently not mutable, so the options object must be empty. Passing |
| * `std::nullopt` for both fields and an empty options object is accepted as |
| * a no-op. |
| * |
| * A failed or unknown transport outcome can leave the update committed. |
| * Retrieve the user before retrying with different values. |
| * |
| * @param user User to update, addressed by numeric ID or name. |
| * @param username New unique name, or `std::nullopt` to retain the name. |
| * @param status New authentication status, or `std::nullopt` to retain the |
| * status. |
| * @param options User update options. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier, name, status, or option is invalid; an option is |
| * unsupported; the user does not exist; the name is already in |
| * use; the caller lacks manage-users permission; or the request |
| * fails. |
| */ |
| void UpdateUser(const Identifier &user, |
| std::optional<std::string> username, |
| std::optional<UserStatus> status, |
| const UserUpdateOptions &options); |
| |
| /** |
| * @brief Creates a top-level stream in the cluster metadata. |
| * |
| * A stream is the top-level namespace for topics. This creates no topics, |
| * partitions, or messages. Its name must be unique, non-empty, and no more |
| * than 255 UTF-8 bytes. |
| * |
| * A transport failure after submission can leave the stream created. Look |
| * it up by name before retrying or choosing another name. |
| * |
| * @param name Unique stream name. |
| * @return Details of the newly created, topic-less stream. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the name is invalid or already in use; the caller lacks |
| * stream-management permission; or the request fails. |
| */ |
| StreamDetails CreateStream(std::string name); |
| |
| /** |
| * @brief Renames a stream. |
| * |
| * @param stream Stream to rename, addressed by numeric ID or name. |
| * @param name New unique stream name. |
| * @param options Stream update options (currently no updatable keys; `raw` |
| * carries forward-compatible keys, each rejected until catalogued). |
| * @throws IggyException if the client is unavailable, the caller lacks |
| * stream-management permission, either value is invalid, the stream |
| * does not exist, the name is already taken, or the request fails. |
| */ |
| void UpdateStream(const Identifier &stream, std::string name, const StreamUpdateOptions &options = {}); |
| |
| /** |
| * @brief Lists stream summaries visible to the authenticated user. |
| * |
| * The summaries exclude per-topic details. Use GetStream() for those. |
| * @return Stream summaries visible to the authenticated user. |
| * @throws IggyException if the client is unavailable, the caller lacks |
| * permission to read streams, or the request fails. |
| */ |
| std::vector<Stream> GetStreams(); |
| |
| /** |
| * @brief Retrieves one stream by numeric ID or name. |
| * |
| * The result includes observed aggregate statistics and topic summaries. |
| * It does not include partition details or messages, and its statistics can |
| * become stale immediately after the request completes. |
| * |
| * @param stream Stream to retrieve. Numeric IDs remain stable if a stream |
| * is renamed. |
| * @return Details for the requested stream. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the stream does not exist; the caller lacks read permission; or |
| * the metadata read fails. |
| */ |
| StreamDetails GetStream(const Identifier &stream); |
| |
| /** |
| * @brief Deletes a stream and all of its topics, partitions, and messages. |
| * |
| * This is irreversible. A transport failure after submission can leave the |
| * deletion committed, so query the stream before retrying this request. |
| * |
| * @param stream Stream to delete, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable, the caller lacks |
| * stream-management permission, the stream does not exist, or the |
| * request fails. |
| */ |
| void DeleteStream(const Identifier &stream); |
| |
| /** |
| * @brief Removes all messages from every topic in a stream. |
| * |
| * The stream, its topics, and topic configuration remain available. A |
| * transport failure after submission can still leave the purge committed. |
| * @param stream Stream to purge, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable, the caller lacks |
| * stream-management permission, the stream does not exist, or the |
| * request fails. |
| */ |
| void PurgeStream(const Identifier &stream); |
| |
| /** |
| * @brief Creates a topic and its initial partitions in a stream. |
| * |
| * The server creates the topic's initial partitions and applies the |
| * supplied TopicCreateOptions. Settings left unset use the server default. |
| * Use SetRawEntries() for supported settings without a dedicated setter. |
| * A dedicated setter takes precedence when it configures the same setting. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param name Unique topic name within @p stream. |
| * @param options Topic creation options. |
| * @return Metadata and initial partition summaries for the created topic. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier, name, partition count, or option is invalid; the |
| * stream does not exist; the caller lacks topic-management |
| * permission; or the server rejects or cannot commit the write. |
| */ |
| TopicDetails CreateTopic(const Identifier &stream, std::string name, const TopicCreateOptions &options = {}); |
| |
| /** |
| * @brief Renames a topic and updates its mutable configuration. |
| * |
| * The supplied TopicUpdateOptions changes only the settings it contains; |
| * settings left unset retain their current values. Topic creation settings, |
| * such as the partition count and segment size, cannot be changed after the |
| * topic is created. Use SetRawEntries() for supported mutable settings |
| * without a dedicated setter. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Topic to update, addressed by numeric ID or name. |
| * @param name New unique topic name within @p stream. |
| * @param options Topic update options. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier, name, setting, or option is invalid; the stream or |
| * topic does not exist; the caller lacks permission; or the server |
| * rejects or cannot commit the write. |
| */ |
| void UpdateTopic(const Identifier &stream, |
| const Identifier &topic, |
| std::string name, |
| const TopicUpdateOptions &options = {}); |
| |
| /** |
| * @brief Lists topic summaries in a stream. |
| * |
| * The returned summaries do not include partition details. Use GetTopic() |
| * when partition offsets, sizes, and segment counts are needed. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @return Topic summaries visible to the authenticated user. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the stream does not exist; the caller lacks read permission; or |
| * the metadata read fails. |
| */ |
| std::vector<Topic> GetTopics(const Identifier &stream); |
| |
| /** |
| * @brief Retrieves one topic and its partition summaries. |
| * |
| * The result is an observed metadata read. Partition offsets and retained |
| * statistics can change immediately after this call returns. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Topic to retrieve, addressed by numeric ID or name. |
| * @return Topic metadata and one summary per partition. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the stream or topic does not exist; the caller lacks read |
| * permission; or the metadata read fails. |
| */ |
| TopicDetails GetTopic(const Identifier &stream, const Identifier &topic); |
| |
| /** |
| * @brief Deletes a topic, its partitions, and retained messages. |
| * |
| * A failed or unknown transport outcome can leave the deletion committed. |
| * Query the topic before retrying a destructive request. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Topic to delete, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the stream or topic does not exist; the caller lacks |
| * topic-management permission; or the server rejects or cannot |
| * commit the write. |
| */ |
| void DeleteTopic(const Identifier &stream, const Identifier &topic); |
| |
| /** |
| * @brief Removes retained messages from every partition of a topic. |
| * |
| * The topic, its partitions, names, and configuration remain. New messages |
| * can be sent after a purge. A failed or unknown transport outcome can |
| * still leave the purge committed. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Topic to purge, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the stream or topic does not exist; the caller lacks |
| * topic-management permission; or the server rejects or cannot |
| * commit the write. |
| */ |
| void PurgeTopic(const Identifier &stream, const Identifier &topic); |
| |
| /** |
| * @brief Adds partitions to a topic. |
| * |
| * New partitions receive IDs after the topic's existing partitions. The |
| * requested count must be between 1 and 1000. A transport failure after |
| * submission can still leave the partitions created. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Topic to extend, addressed by numeric ID or name. |
| * @param partitions_count Number of partitions to add. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier or count is invalid; the stream or topic does not |
| * exist; the caller lacks topic-management permission; or the |
| * request fails. |
| */ |
| void CreatePartitions(const Identifier &stream, const Identifier &topic, std::uint32_t partitions_count); |
| |
| /** |
| * @brief Deletes the highest-numbered partitions from a topic. |
| * |
| * The deleted partitions and their retained messages are removed. The |
| * requested count must be between 1 and 1000. A transport failure after |
| * submission can still leave the deletion committed. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Topic to shrink, addressed by numeric ID or name. |
| * @param partitions_count Number of partitions to delete. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier or count is invalid; the stream or topic does not |
| * exist; the caller lacks topic-management permission; or the |
| * request fails. |
| */ |
| void DeletePartitions(const Identifier &stream, const Identifier &topic, std::uint32_t partitions_count); |
| |
| /** |
| * @brief Deletes the oldest sealed segments from one partition. |
| * |
| * The active segment is never deleted. If fewer sealed segments exist than |
| * requested, every sealed segment is selected. A count of zero, or a |
| * partition with no sealed segments, succeeds without deleting data. The |
| * server commits a truncation watermark before local replicas remove the |
| * selected segment files. |
| * |
| * A failed or unknown transport outcome can leave the truncation committed. |
| * Inspect the partition before retrying this destructive request. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param partition_id Numeric partition ID. |
| * @param segments_count Maximum number of oldest sealed segments to delete. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier or partition is invalid; the stream, topic, or |
| * partition does not exist; the caller lacks topic-management |
| * permission; or the request fails. |
| */ |
| void DeleteSegments(const Identifier &stream, |
| const Identifier &topic, |
| std::uint32_t partition_id, |
| std::uint32_t segments_count); |
| |
| /** |
| * @brief Creates a consumer group for a topic. |
| * |
| * The group name must be unique within the topic, non-empty, and no more |
| * than 255 UTF-8 bytes. The new group initially has no members. |
| * |
| * The VSR server assigns consumer group IDs monotonically. Deleting a |
| * group and recreating it with the same name is allowed, but the recreated |
| * group receives a new ID rather than reusing the deleted group's ID. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param name Unique consumer group name within @p topic. |
| * @return Details of the newly created consumer group. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier or the name is invalid; the stream or topic does |
| * not exist; the name is already in use; the caller lacks |
| * stream- or topic-management permission; or the request fails. |
| */ |
| ConsumerGroupDetails CreateConsumerGroup(const Identifier &stream, const Identifier &topic, std::string name); |
| |
| /** |
| * @brief Retrieves one consumer group and its current members. |
| * |
| * The returned details are a snapshot. Membership and partition |
| * assignments can change immediately after this call returns. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param group Consumer group to retrieve, addressed by numeric ID or name. |
| * @return Consumer group metadata and member details. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier is invalid; the stream, topic, or consumer group |
| * does not exist; the caller lacks read permission; or the |
| * metadata read fails. |
| */ |
| ConsumerGroupDetails GetConsumerGroup(const Identifier &stream, const Identifier &topic, const Identifier &group); |
| |
| /** |
| * @brief Lists consumer group summaries for a topic. |
| * |
| * The summaries include member and partition counts but omit individual |
| * member details. Use GetConsumerGroup() to retrieve those details. |
| * |
| * The VSR server reports a missing parent stream or topic as an error. This |
| * differs from the legacy server, which returned an empty list, so an empty |
| * result does not establish whether the parent resources exist across |
| * server implementations. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @return Consumer group summaries for the requested topic. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier is invalid; the stream or topic does not exist; |
| * the caller lacks read permission; or the metadata read fails. |
| */ |
| std::vector<ConsumerGroup> GetConsumerGroups(const Identifier &stream, const Identifier &topic); |
| |
| /** |
| * @brief Deletes a consumer group from a topic. |
| * |
| * A failed or unknown transport outcome can leave the deletion committed. |
| * Query the topic's consumer groups before retrying this request. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param group Consumer group to delete, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier is invalid; the stream, topic, or consumer group |
| * does not exist; the caller lacks stream- or topic-management |
| * permission; or the request fails. |
| */ |
| void DeleteConsumerGroup(const Identifier &stream, const Identifier &topic, const Identifier &group); |
| |
| /** |
| * @brief Joins the current client to a consumer group. |
| * |
| * The server assigns topic partitions among the group's members. Joining |
| * the same group again does not add a second membership for this client. |
| * Joining consumer groups over HTTP is not supported. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param group Consumer group to join, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier is invalid; the stream, topic, or consumer group |
| * does not exist; the caller lacks read permission; the transport |
| * does not support group membership; or the request fails. |
| */ |
| void JoinConsumerGroup(const Identifier &stream, const Identifier &topic, const Identifier &group); |
| |
| /** |
| * @brief Removes the current client from a consumer group. |
| * |
| * The server reassigns partitions among the remaining group members. |
| * The client must currently belong to the group; leaving twice or leaving |
| * without first joining fails. Leaving consumer groups over HTTP is not |
| * supported. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param group Consumer group to leave, addressed by numeric ID or name. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier is invalid; the stream, topic, or consumer group |
| * does not exist; this client is not a member; the caller lacks |
| * read permission; the transport does not support group |
| * membership; or the request fails. |
| */ |
| void LeaveConsumerGroup(const Identifier &stream, const Identifier &topic, const Identifier &group); |
| |
| /** |
| * @brief Stores an offset for a consumer or consumer group. |
| * |
| * The server accepts offsets from zero through the partition's current |
| * offset, inclusive. It rejects every offset for an empty partition and |
| * any offset beyond the current offset. Storing another value for the same |
| * consumer and partition replaces the previous value. |
| * |
| * For a consumer group, the group must exist and the current client must |
| * own @p partition_id in that group. This ownership fence does not apply to |
| * individual consumers. |
| * |
| * @param consumer Consumer identity that owns the offset. |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param partition_id Partition whose offset is stored, or `std::nullopt` |
| * to omit the partition from the request. The maximum |
| * `std::uint32_t` value is rejected because it is reserved by the |
| * FFI representation. |
| * @param offset Message offset to store. |
| * @throws IggyException if an identifier, partition, or offset is invalid; |
| * the resource does not exist; the client is unauthenticated; the |
| * caller lacks permission; or the request fails. |
| */ |
| void StoreConsumerOffset(const Consumer &consumer, |
| const Identifier &stream, |
| const Identifier &topic, |
| std::optional<std::uint32_t> partition_id, |
| std::uint64_t offset); |
| |
| /** |
| * @brief Retrieves the stored offset for a consumer or consumer group. |
| * |
| * This method throws IggyException when no offset has been stored. A |
| * consumer group offset can be read by an authenticated caller with poll |
| * permission even when that client is not a member of the group. |
| * |
| * An offset created by an auto-commit poll is visible through this method. |
| * A local auto-commit cursor can be visible before its durable store has |
| * committed. |
| * |
| * @param consumer Consumer identity that owns the offset. |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param partition_id Partition whose offset is retrieved, or |
| * `std::nullopt` to omit the partition from the request. The |
| * maximum `std::uint32_t` value is rejected because it is reserved |
| * by the FFI representation. |
| * @return Partition state and the stored consumer offset. |
| * @throws IggyException if an identifier or partition is invalid; the |
| * resource or stored offset does not exist; the client is |
| * unauthenticated; the caller lacks permission; or the request |
| * fails. |
| */ |
| ConsumerOffsetInfo GetConsumerOffset(const Consumer &consumer, |
| const Identifier &stream, |
| const Identifier &topic, |
| std::optional<std::uint32_t> partition_id = std::nullopt); |
| |
| /** |
| * @brief Deletes the stored offset for a consumer or consumer group. |
| * |
| * Deletion is not idempotent: deleting an offset that was never stored, or |
| * deleting the same offset again, fails. A failed or unknown transport |
| * outcome can leave the deletion committed, in which case a retry can fail |
| * because the offset is already absent. |
| * |
| * For a consumer group, the group must exist and the current client must |
| * own @p partition_id in that group. This ownership fence does not apply to |
| * individual consumers. |
| * |
| * @param consumer Consumer identity that owns the offset. |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param partition_id Partition whose offset is deleted, or `std::nullopt` |
| * to omit the partition from the request. The maximum |
| * `std::uint32_t` value is rejected because it is reserved by the |
| * FFI representation. |
| * @throws IggyException if an identifier or partition is invalid; the |
| * resource or stored offset does not exist; the client is |
| * unauthenticated; the caller lacks permission; or the request |
| * fails. |
| */ |
| void DeleteConsumerOffset(const Consumer &consumer, |
| const Identifier &stream, |
| const Identifier &topic, |
| std::optional<std::uint32_t> partition_id = std::nullopt); |
| |
| /** |
| * @brief Retrieves details for this client connection. |
| * |
| * The result includes consumer-group memberships observed for the current |
| * authenticated connection. HTTP is stateless and does not expose a |
| * persistent current connection, so the HTTP transport reports this |
| * operation as unavailable. |
| * |
| * @return Details for the current client connection. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the transport does not support the operation; or the request |
| * fails. |
| */ |
| ClientInfoDetails GetMe(); |
| |
| /** |
| * @brief Retrieves one currently connected client by numeric ID. |
| * |
| * The result is a snapshot containing the connection's observed consumer- |
| * group memberships. The connection can disappear immediately after the |
| * request completes. |
| * |
| * @param client_id Server-assigned connection ID. |
| * @return Details for the requested client connection. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the requested connection does not exist; the caller lacks |
| * read-servers or manage-servers permission; or the request fails. |
| */ |
| ClientInfoDetails GetClient(std::uint32_t client_id); |
| |
| /** |
| * @brief Lists client connections currently known to the server. |
| * |
| * Each entry is a snapshot summary and omits individual consumer-group |
| * identifiers. Use GetClient() for membership details. |
| * |
| * @return Client connection summaries observed for this request. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the caller lacks read-servers or manage-servers permission; or |
| * the request fails. |
| */ |
| std::vector<ClientInfo> GetClients(); |
| |
| /** |
| * @brief Requests an immediate flush of a partition's unsaved buffer. |
| * |
| * When supported, the server writes buffered messages to storage and also |
| * requests an operating-system synchronization when @p fsync is true. The |
| * current VSR server does not expose this maintenance primitive and returns |
| * a feature-unavailable error; its HTTP API has no matching route. |
| * |
| * @param stream Parent stream, addressed by numeric ID or name. |
| * @param topic Parent topic, addressed by numeric ID or name. |
| * @param partition_id Numeric partition ID. |
| * @param fsync Whether to request synchronization to stable storage. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * an identifier or partition is invalid; the server or transport |
| * does not support the operation; the caller lacks permission; or |
| * the request fails. |
| */ |
| void FlushUnsavedBuffer(const Identifier &stream, const Identifier &topic, std::uint32_t partition_id, bool fsync); |
| |
| /** |
| * @brief Retrieves server process, storage, and resource statistics. |
| * |
| * The returned fields are an observed snapshot and can change immediately. |
| * Process and host measurements describe the server that handles the |
| * request; metadata totals describe the state visible to that server. |
| * |
| * @return Statistics observed for this request. |
| * @throws IggyException if the client is unavailable or unauthenticated; |
| * the caller lacks read-servers or manage-servers permission; or |
| * the request fails. |
| */ |
| Stats GetStats(); |
| |
| private: |
| explicit IggyBlockingClient(ffi::Client *client); |
| |
| template <typename Operation> |
| static decltype(auto) RethrowAsIggyException(Operation &&operation) { |
| try { |
| return std::forward<Operation>(operation)(); |
| } catch (const std::exception &error) { |
| throw IggyException(error.what()); |
| } |
| } |
| |
| [[nodiscard]] ffi::Client *Handle() const; |
| void Reset() noexcept; |
| |
| ffi::Client *client_; |
| }; |
| |
| /** |
| * @brief Fluent builder for IggyBlockingClient. |
| * |
| * The builder creates TCP clients only. Use |
| * IggyBlockingClient::FromConnectionString() to select another transport. |
| * Configuration methods return the builder by reference and may be chained. |
| * Unless documented otherwise, settings are validated and applied by Build(). |
| */ |
| class IggyBlockingClient::Builder final { |
| public: |
| /** |
| * @brief Creates a builder with the default TCP endpoint, 127.0.0.1:8090. |
| * |
| * Automatic login and TLS are disabled. Reconnection is enabled with |
| * unlimited retries, a one-second retry interval, and a five-second delay |
| * before reestablishing a previously working connection. The heartbeat |
| * interval is five seconds. TCP_NODELAY is disabled. Build() always returns |
| * a disconnected client. |
| */ |
| Builder(); |
| |
| /** |
| * @brief Sets the TCP server address. |
| * |
| * The address is trimmed and validated during Build(). Host names, IPv4, |
| * and bracketed IPv6 are accepted. A non-zero port is required. |
| * |
| * @param server_address Server address in host:port form. |
| * @return Reference to this builder. |
| * @throws IggyException if @p server_address is empty. |
| * @note Build() throws IggyException if the address is invalid. |
| */ |
| Builder &WithServerAddress(std::string server_address); |
| |
| /** |
| * @brief Enables automatic authentication with user credentials. |
| * |
| * The credentials are used whenever Connect() establishes a connection, |
| * including reconnections. This replaces a previously configured personal |
| * access token. |
| * |
| * @param username Iggy user name. |
| * @param password Iggy user password. |
| * @return Reference to this builder. |
| * @throws IggyException if either credential is empty. |
| * @see IggyBlockingClient::Connect() |
| * @see IggyBlockingClient::Login() |
| */ |
| Builder &WithAutoLogin(std::string username, std::string password); |
| |
| /** |
| * @brief Enables automatic authentication with a personal access token. |
| * |
| * The token is used whenever Connect() establishes a connection, including |
| * reconnections. This replaces previously configured username and password |
| * credentials. |
| * |
| * @param token Personal access token. |
| * @return Reference to this builder. |
| * @throws IggyException if the token is empty. |
| * @see IggyBlockingClient::Connect() |
| */ |
| Builder &WithPersonalAccessToken(std::string token); |
| |
| /** |
| * @brief Sets the maximum number of reconnection attempts. |
| * |
| * Reconnection is enabled by default. A value of zero disables retries |
| * after the initial connection attempt. This replaces a previous call to |
| * WithoutReconnectionLimit(). |
| * |
| * @param retries Maximum number of attempts. |
| * @return Reference to this builder. |
| */ |
| Builder &WithReconnectionMaxRetries(std::uint32_t retries); |
| |
| /** |
| * @brief Removes the limit on reconnection attempts. |
| * |
| * This is the default and replaces a previous finite retry limit. |
| * |
| * @return Reference to this builder. |
| */ |
| Builder &WithoutReconnectionLimit(); |
| |
| /** |
| * @brief Sets the delay between reconnection attempts. |
| * |
| * The default interval is one second. This interval applies between failed |
| * connection attempts. |
| * |
| * @param interval Non-negative reconnection interval. |
| * @return Reference to this builder. |
| * @throws IggyException if @p interval is negative. |
| */ |
| Builder &WithReconnectionInterval(std::chrono::microseconds interval); |
| |
| /** |
| * @brief Sets the delay before restoring a lost established connection. |
| * |
| * The default delay is five seconds. This cooldown is distinct from the |
| * interval between failed connection attempts. |
| * |
| * @param duration Non-negative delay. |
| * @return Reference to this builder. |
| * @throws IggyException if @p duration is negative. |
| */ |
| Builder &WithReestablishAfter(std::chrono::microseconds duration); |
| |
| /** |
| * @brief Enables or disables TLS. |
| * |
| * TLS is disabled by default. TLS domain, CA file, and certificate |
| * validation settings require TLS to be enabled. |
| * |
| * @param enabled Whether TLS is enabled. |
| * @return Reference to this builder. |
| */ |
| Builder &WithTlsEnabled(bool enabled = true); |
| |
| /** |
| * @brief Sets the domain used for TLS server-name verification. |
| * |
| * When omitted, the domain is derived from the configured server address. |
| * Build() throws IggyException if this is set while TLS is disabled. |
| * |
| * @param domain TLS domain name. |
| * @return Reference to this builder. |
| * @throws IggyException if @p domain is empty. |
| */ |
| Builder &WithTlsDomain(std::string domain); |
| |
| /** |
| * @brief Sets the certificate-authority file used by TLS. |
| * |
| * When omitted, system root certificates are used. This setting has no |
| * effect unless TLS is enabled. Build() throws IggyException if a path is |
| * set while TLS is disabled. |
| * |
| * @param path Path to a PEM-encoded certificate-authority file. |
| * @return Reference to this builder. |
| * @throws IggyException if @p path is empty. |
| */ |
| Builder &WithTlsCaFile(std::string path); |
| |
| /** |
| * @brief Enables or disables TLS certificate validation. |
| * |
| * Certificate validation is enabled by default. Disabling it accepts |
| * certificates without verifying their trust chain or server identity and |
| * should be limited to controlled development environments. This setting |
| * requires TLS; Build() throws IggyException if certificate validation is |
| * configured while TLS is disabled. |
| * |
| * @param enabled Whether the server certificate is validated. |
| * @return Reference to this builder. |
| */ |
| Builder &WithTlsCertificateValidation(bool enabled = true); |
| |
| /** |
| * @brief Enables TCP_NODELAY on the client socket. |
| * |
| * TCP_NODELAY disables Nagle's algorithm to reduce latency for small |
| * writes, potentially increasing packet count. It is disabled by default. |
| * |
| * @return Reference to this builder. |
| */ |
| Builder &WithNoDelay(); |
| |
| /** |
| * @brief Builds an owning Iggy blocking client. |
| * |
| * Build() validates the TCP configuration and creates an independent |
| * client. The builder is not consumed and may be reused. The returned |
| * client is always disconnected; call IggyBlockingClient::Connect() |
| * explicitly before using operations that require a connection. |
| * |
| * @return Configured client. |
| * @throws IggyException if validation or client creation fails. |
| */ |
| [[nodiscard]] IggyBlockingClient Build() const; |
| |
| private: |
| std::string server_address_; |
| ffi::AutoLoginKind auto_login_kind_{ffi::AutoLoginKind::Disabled}; |
| std::string auto_login_username_; |
| std::string auto_login_password_; |
| std::string personal_access_token_; |
| std::optional<std::uint32_t> reconnection_max_retries_; |
| std::optional<std::uint64_t> reconnection_interval_micros_; |
| std::optional<std::uint64_t> reestablish_after_micros_; |
| bool tls_enabled_{}; |
| std::string tls_domain_; |
| std::string tls_ca_file_; |
| std::optional<bool> tls_validate_certificate_; |
| bool no_delay_{}; |
| }; |
| |
| } // namespace iggy |