blob: d874e010ded7b69c624b2a2c752f2e2c53f1cec9 [file]
/*
* 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 <cstdint>
#include <limits>
#include <stdexcept>
#include <string>
#include <string_view>
#include <utility>
namespace iggy {
/// Exception raised by the C++ client when an operation fails.
class IggyException : public std::runtime_error {
public:
explicit IggyException(const char *message) : std::runtime_error(message) {}
explicit IggyException(const std::string &message) : std::runtime_error(message) {}
};
namespace detail {
/// Internal helper used by string-backed option types in this header.
template <typename Tag>
class StringTag {
protected:
explicit StringTag(std::string value) : value_(std::move(value)) {}
~StringTag() = default;
std::string_view value() const { return value_; }
private:
std::string value_;
};
} // namespace detail
/// Compression setting for `Client::create_topic(...)`.
///
/// Use this type to choose whether messages in a topic are stored as-is or compressed with gzip.
///
/// Internally, this value is passed across the Rust FFI as a string.
/// Values outside the supported set are rejected by the Rust client.
class CompressionAlgorithm final : private detail::StringTag<CompressionAlgorithm> {
public:
/// Store messages without compression.
static CompressionAlgorithm none() { return CompressionAlgorithm("none"); }
/// Compress messages with gzip.
static CompressionAlgorithm gzip() { return CompressionAlgorithm("gzip"); }
std::string_view compression_algorithm_value() const { return value(); }
private:
explicit CompressionAlgorithm(std::string algorithm)
: detail::StringTag<CompressionAlgorithm>(std::move(algorithm)) {}
};
/// Compression setting for `Client::snapshot(...)`.
///
/// Use this type to choose how snapshot data is compressed in the generated archive.
///
/// Internally, this value is passed across the Rust FFI as a string.
/// Values outside the supported set are rejected by the Rust client.
class SnapshotCompression final : private detail::StringTag<SnapshotCompression> {
public:
/// Store snapshot files without compression.
static SnapshotCompression stored() { return SnapshotCompression("stored"); }
/// Use standard deflate compression.
static SnapshotCompression deflated() { return SnapshotCompression("deflated"); }
/// Use bzip2 for a higher compression ratio at the cost of slower processing.
static SnapshotCompression bzip2() { return SnapshotCompression("bzip2"); }
/// Use Zstandard for fast compression and decompression.
static SnapshotCompression zstd() { return SnapshotCompression("zstd"); }
/// Use LZMA for high compression, especially for larger files.
static SnapshotCompression lzma() { return SnapshotCompression("lzma"); }
/// Use XZ, which is similar to LZMA and often faster to decompress.
static SnapshotCompression xz() { return SnapshotCompression("xz"); }
std::string_view snapshot_compression_value() const { return value(); }
private:
explicit SnapshotCompression(std::string snapshot_compression)
: detail::StringTag<SnapshotCompression>(std::move(snapshot_compression)) {}
};
/// System snapshot selector for `Client::snapshot(...)`.
///
/// Use this type to choose which snapshot data the server should include.
///
/// Internally, each selected value is passed across the Rust FFI as a string.
/// Values outside the supported set are rejected by the Rust client.
class SystemSnapshotType final : private detail::StringTag<SystemSnapshotType> {
public:
/// Include an overview of the filesystem structure.
static SystemSnapshotType filesystem_overview() { return SystemSnapshotType("filesystem_overview"); }
/// Include the list of currently running processes.
static SystemSnapshotType process_list() { return SystemSnapshotType("process_list"); }
/// Include CPU, memory, and other system resource usage statistics.
static SystemSnapshotType resource_usage() { return SystemSnapshotType("resource_usage"); }
/// Include the test snapshot used for development and testing.
static SystemSnapshotType test() { return SystemSnapshotType("test"); }
/// Include server logs from the configured logging directory.
static SystemSnapshotType server_logs() { return SystemSnapshotType("server_logs"); }
/// Include the server configuration.
static SystemSnapshotType server_config() { return SystemSnapshotType("server_config"); }
/// Include all available snapshot types.
static SystemSnapshotType all() { return SystemSnapshotType("all"); }
std::string_view snapshot_type_value() const { return value(); }
private:
explicit SystemSnapshotType(std::string snapshot_type)
: detail::StringTag<SystemSnapshotType>(std::move(snapshot_type)) {}
};
/// Maximum retained size for a topic.
///
/// Use this type to choose whether a topic uses the server default limit, no limit, or an
/// explicit byte limit.
///
/// Internally, this value is passed across the Rust FFI as a string.
/// Values outside the supported set are rejected by the Rust client.
/// In addition to `server_default` and `unlimited`, the Rust parser also accepts
/// numeric size strings. A value of `0` is treated as `server_default`, and a
/// value of `std::numeric_limits<std::uint64_t>::max()` is treated as `unlimited`.
class MaxTopicSize final : private detail::StringTag<MaxTopicSize> {
public:
/// Use the server's default maximum topic size.
static MaxTopicSize server_default() { return MaxTopicSize("server_default"); }
/// Disable the maximum topic size limit.
static MaxTopicSize unlimited() { return MaxTopicSize("unlimited"); }
/// Set an explicit maximum topic size in bytes.
///
/// A value of `0` is treated as `server_default()`. A value of
/// `std::numeric_limits<std::uint64_t>::max()` is treated as `unlimited()`.
/// The configured limit cannot be lower than the server's segment size.
static MaxTopicSize from_bytes(std::uint64_t bytes) {
if (bytes == 0) {
return server_default();
}
if (bytes == std::numeric_limits<std::uint64_t>::max()) {
return unlimited();
}
return MaxTopicSize(std::to_string(bytes));
}
std::string_view max_topic_size() const { return value(); }
private:
explicit MaxTopicSize(std::string max_topic_size) : detail::StringTag<MaxTopicSize>(std::move(max_topic_size)) {}
};
// TODO(slbotbm): Add rust bindings for Identifier that will use IdKind
/// Describes whether an identifier is numeric or string-based.
///
/// Use this type to describe how an identifier is encoded.
///
/// This type is reserved for future identifier bindings and is not currently passed through the
/// Rust FFI.
class IdKind final : private detail::StringTag<IdKind> {
public:
/// A numeric identifier represented as a 32-bit integer.
static IdKind numeric() { return IdKind("numeric"); }
/// A string identifier represented by its text value.
static IdKind string() { return IdKind("string"); }
std::string_view id_kind_value() const { return value(); }
private:
explicit IdKind(std::string id_kind) : detail::StringTag<IdKind>(std::move(id_kind)) {}
};
/// Message expiry policy for `Client::create_topic(...)`.
///
/// Use this type to choose how long messages in a topic are retained.
///
/// `expiry_kind()` returns the selected mode. `expiry_value()` returns the associated payload:
/// the duration for `duration(micros)`, `0` for `server_default()`, or
/// `std::numeric_limits<std::uint64_t>::max()` for `never_expire()`.
///
/// Internally, this value is passed across the Rust FFI as a kind/value pair.
/// Unsupported kinds are rejected by the Rust client.
class Expiry final {
public:
/// Use the server's default message expiry policy.
static Expiry server_default() { return Expiry("server_default", 0); }
/// Keep messages until they are removed for some other reason, such as topic deletion.
static Expiry never_expire() { return Expiry("never_expire", std::numeric_limits<std::uint64_t>::max()); }
/// Expire messages after the given number of microseconds.
static Expiry duration(std::uint64_t micros) { return Expiry("duration", micros); }
std::string_view expiry_kind() const { return expiry_kind_; }
std::uint64_t expiry_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_;
};
/// Starting position for `Client::poll_messages(...)`.
///
/// Use this type to choose where the server should begin reading messages.
///
/// `polling_strategy_kind()` returns the selected mode. `polling_strategy_value()` returns the
/// associated offset or timestamp for the parameterized modes and `0` for the others.
///
/// Internally, this value is passed across the Rust FFI as a kind/value pair.
/// Unsupported kinds are rejected by the Rust client.
class PollingStrategy final {
public:
/// Start polling from a specific message offset.
static PollingStrategy offset(std::uint64_t value) { return PollingStrategy("offset", value); }
/// Start polling from a specific timestamp.
static PollingStrategy timestamp(std::uint64_t value) { return PollingStrategy("timestamp", value); }
/// Start polling from the first message in the partition.
static PollingStrategy first() { return PollingStrategy("first", 0); }
/// Start polling from the last message currently available in the partition.
static PollingStrategy last() { return PollingStrategy("last", 0); }
/// Start polling from the next message after the stored consumer offset.
///
/// This is typically used with automatic offset commits enabled.
static PollingStrategy next() { return PollingStrategy("next", 0); }
std::string_view polling_strategy_kind() const { return polling_strategy_kind_; }
std::uint64_t polling_strategy_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_;
};
} // namespace iggy