Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RS-44: Support for Replication API #64

Merged
merged 9 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
- reductstore_version: "main"
exclude_api_version_tag: ""
- reductstore_version: "latest"
exclude_api_version_tag: "~[1_7]"
exclude_api_version_tag: "~[1_8]"

needs:
- build
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]


### Added

- RS-44: Replication API, [PR-64](https://github.com/reductstore/reduct-cpp/pull/64)

### Changed:

- docs: update link to new website, [PR-63](https://github.com/reductstore/reduct-cpp/pull/63)
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.18)

set(MAJOR_VERSION 1)
set(MINOR_VERSION 7)
set(PATCH_VERSION 1)
set(MINOR_VERSION 8)
set(PATCH_VERSION 0)
set(REDUCT_CPP_FULL_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION})

project(reductcpp VERSION ${REDUCT_CPP_FULL_VERSION})
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ in C++20. It allows developers to easily interact with the database from their C
## Features

* Written in C++20
* Support ReductStore HTTP API v1.7
* Support ReductStore HTTP API v1.8
* Support HTTP and HTTPS protocols
* Exception free
* Support Linux AMD64
Expand Down
16 changes: 8 additions & 8 deletions cmake/InstallDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,26 @@ else ()
include(FetchContent)
FetchContent_Declare(
fmt
URL https://github.com/fmtlib/fmt/archive/refs/tags/8.1.1.zip
URL_HASH MD5=fed2f2c5027a4034cc8351bf59aa8f7c
URL https://github.com/fmtlib/fmt/archive/refs/tags/10.2.1.zip
URL_HASH MD5=1bba4e8bdd7b0fa98f207559ffa380a3
)

FetchContent_Declare(
nlohmann_json
URL https://github.com/nlohmann/json/archive/refs/tags/v3.10.5.zip
URL_HASH MD5=accaeb6a75f5972f479ef9139fa65b9e
URL https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.zip
URL_HASH MD5=23712ebf3a4b4ccb39f2375521716ab3
)

FetchContent_Declare(
httplib
URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.10.7.zip
URL_HASH MD5=31497d5f3ff1e0df2f57195dbabd3198
URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.14.3.zip
URL_HASH MD5=af82eb38506ca531b6d1d53524ff7912
)

FetchContent_Declare(
concurrentqueue
URL https://github.com/cameron314/concurrentqueue/archive/refs/tags/v1.0.3.zip
URL_HASH MD5=6e879b14c833df7c011be5959e70cef7
URL https://github.com/cameron314/concurrentqueue/archive/refs/tags/v1.0.4.zip
URL_HASH MD5=814c5e121b29e37ee836312f0eb0328f
)

FetchContent_Declare(
Expand Down
12 changes: 6 additions & 6 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

class DriftFrameworkConan(ConanFile):
name = "reduct-cpp"
version = "1.7.1"
version = "1.8.0"
license = "MIT"
author = "Alexey Timin"
url = "https://github.com/reduct-storage/reduct-cpp"
Expand All @@ -15,11 +15,11 @@ class DriftFrameworkConan(ConanFile):
"date:header_only": True}
generators = "cmake"

requires = ("fmt/10.0.0",
"cpp-httplib/0.12.4",
"nlohmann_json/3.11.2",
"openssl/3.1.1",
"concurrentqueue/1.0.3",
requires = ("fmt/10.2.1",
"cpp-httplib/0.14.3",
"nlohmann_json/3.11.3",
"openssl/3.2.0",
"concurrentqueue/1.0.4",
"date/3.0.1")

def config_options(self):
Expand Down
4 changes: 2 additions & 2 deletions docs/api_reference/iclient.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ To create a new token, you should use `CreateToken` method with `IClient::Permis
```cpp
IClient::Permissions permissions{
.full_access = true,
.read = {"bucket_1"},
.write = {"bucket_2"},
.read = {"test_bucket_1"},
.write = {"test_bucket_2"},
};


Expand Down
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ find_package(OpenSSL)



find_package(ReductCpp 1.7.0)
find_package(ReductCpp 1.8.0)

add_executable(usage-example usage_example.cc)
add_executable(subscription subscription.cc)
Expand Down
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ set(PUBLIC_HEADERS
reduct/client.h
reduct/error.h
reduct/http_options.h
reduct/result.h)
reduct/result.h
reduct/diagnostics.h)


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
Expand Down
11 changes: 8 additions & 3 deletions src/reduct/bucket.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022-2023 Alexey Timin
// Copyright 2022-2024 Alexey Timin
#ifndef REDUCT_CPP_BUCKET_H
#define REDUCT_CPP_BUCKET_H

Expand All @@ -16,9 +16,14 @@
#include "reduct/result.h"

namespace reduct {

/**
* Provides Bucket HTTP API
* @class IBucket
* @brief Represents a bucket for storing and retrieving data.
*
* A Bucket object allows you to interact with a specific bucket in the storage system.
* You can perform operations like getting the bucket settings, updating the settings,
* getting bucket information, retrieving the list of entries, writing records to the bucket,
* and reading records from the bucket.
*/
class IBucket {
public:
Expand Down
42 changes: 42 additions & 0 deletions src/reduct/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,48 @@ class Client : public IClient {
}
}

Result<std::vector<ReplicationInfo>> GetReplicationList() const noexcept override {
auto [body, err] = client_->Get("/replications");
if (err) {
return {{}, std::move(err)};
}

try {
nlohmann::json data = nlohmann::json::parse(body);
return internal::ParseReplicationList(data);
} catch (const std::exception& e) {
return {{}, Error{.code = -1, .message = e.what()}};
}
}

Result<FullReplicationInfo> GetReplication(std::string_view name) const noexcept override {
auto [body, err] = client_->Get(fmt::format("/replications/{}", name));
if (err) {
return {{}, std::move(err)};
}

try {
nlohmann::json data = nlohmann::json::parse(body);
return internal::ParseFullReplicationInfo(data);
} catch (const std::exception& e) {
return {{}, Error{.code = -1, .message = e.what()}};
}
}

Error CreateReplication(std::string_view name, ReplicationSettings settings) const noexcept override {
auto json_data = internal::ReplicationSettingsToJsonString(std::move(settings));
return client_->Post(fmt::format("/replications/{}", name), json_data.dump());
}

Error UpdateReplication(std::string_view name, ReplicationSettings settings) const noexcept override {
auto json_data = internal::ReplicationSettingsToJsonString(std::move(settings));
return client_->Put(fmt::format("/replications/{}", name), json_data.dump());
}

Error RemoveReplication(std::string_view name) const noexcept override {
return client_->Delete(fmt::format("/replications/{}", name));
}

private:
HttpOptions options_;
std::unique_ptr<internal::IHttpClient> client_;
Expand Down
89 changes: 78 additions & 11 deletions src/reduct/client.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 Alexey Timin
// Copyright 2022-2024 Alexey Timin

#ifndef REDUCT_CPP_CLIENT_H
#define REDUCT_CPP_CLIENT_H
Expand All @@ -10,6 +10,7 @@
#include <string>
#include <vector>

#include "diagnostics.h"
#include "reduct/bucket.h"
#include "reduct/error.h"
#include "reduct/http_options.h"
Expand Down Expand Up @@ -151,19 +152,85 @@ class IClient {
* Makes a GET request to the '/me' endpoint using the client object stored as a member variable.
*
* @return A Result object containing a FullTokenInfo object or an Error object.
*
* Example:
*
* MyClass obj;
* auto [token_info, err] = obj.Me();
* if (err) {
* std::cerr << err << std::endl;
* } else {
* std::cout << token_info.name << std::endl;
* }
*/
[[nodiscard]] virtual Result<FullTokenInfo> Me() const noexcept = 0;

/**
* Replication information
*/
struct ReplicationInfo {
std::string name; // Replication name
bool is_active; // Remote instance is available and replication is active
bool is_provisioned; // Replication settings
uint64_t pending_records; // Number of records pending replication

bool operator<=>(const ReplicationInfo&) const = default;
};

/**
* Replication settings
*/
struct ReplicationSettings {
std::string src_bucket; // Source bucket
std::string dst_bucket; // Destination bucket
std::string dst_host; // Destination host URL (e.g. https://reductstore.com)
std::string dst_token; // Destination access token
std::vector<std::string>
entries; // Entries to replicate. If empty, all entries are replicated. Wildcards are supported.
IBucket::LabelMap include; // Labels to include
IBucket::LabelMap exclude; // Labels to exclude

bool operator<=>(const ReplicationSettings&) const = default;
};

/**
* Replication full info with settings and diagnostics
*/
struct FullReplicationInfo {
ReplicationInfo info; // Replication info
ReplicationSettings settings; // Replication settings
Diagnostics diagnostics; // Diagnostics

bool operator==(const FullReplicationInfo&) const = default;
};

/**
* @brief Get list of replications
* @return the list or an error
*/
[[nodiscard]] virtual Result<std::vector<ReplicationInfo>> GetReplicationList() const noexcept = 0;

/**
* @brief Get replication info with settings and diagnostics
* @param name name of replication
* @return the info or an error
*/
[[nodiscard]] virtual Result<FullReplicationInfo> GetReplication(std::string_view name) const noexcept = 0;

/**
* @brief Create a new replication
* @param name name of replication
* @param settings replication settings
* @return error
*/
[[nodiscard]] virtual Error CreateReplication(std::string_view name, ReplicationSettings settings) const noexcept = 0;

/**
* @brief Update replication settings
* @param name name of replication
* @param settings replication settings
* @return error
*/
[[nodiscard]] virtual Error UpdateReplication(std::string_view name, ReplicationSettings settings) const noexcept = 0;


/**
* @brief Remove replication
* @param name name of replication
* @return error
*/
[[nodiscard]] virtual Error RemoveReplication(std::string_view name) const noexcept = 0;

/**
* @brief Build a client
* @param url URL of React Storage
Expand Down
33 changes: 33 additions & 0 deletions src/reduct/diagnostics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 Alexey Timin

#ifndef REDUCT_CPP_DIAGNOSTICS_H
#define REDUCT_CPP_DIAGNOSTICS_H

#include <map>
#include <string>

namespace reduct {

struct DiagnosticsError {
uint64_t count; // Count of errors
std::string last_message; // Last error message

bool operator<=>(const DiagnosticsError&) const = default;
};

struct DiagnosticsItem {
uint64_t ok; // Count of successful operations
uint64_t errored; // Count of errored operations
std::map<int16_t, DiagnosticsError> errors; // Map of error codes to DiagnosticsError

bool operator==(const DiagnosticsItem&) const = default;
};

struct Diagnostics {
DiagnosticsItem hourly; // Hourly diagnostics item

bool operator==(const Diagnostics&) const = default;
};

} // namespace reduct
#endif // REDUCT_CPP_DIAGNOSTICS_H
Loading
Loading