mirror of
https://github.com/XRPLF/clio.git
synced 2026-01-19 14:15:24 +00:00
Compare commits
10 Commits
2.5.0-rc1
...
update/pre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99a33777c9 | ||
|
|
379a44641b | ||
|
|
18b8fc7e5c | ||
|
|
be2d915df7 | ||
|
|
57dda8ac50 | ||
|
|
5cdd8a642f | ||
|
|
8abc9c6645 | ||
|
|
24e1aa9ae5 | ||
|
|
9bee023105 | ||
|
|
4ee3ef94d9 |
3
.github/workflows/clang-tidy.yml
vendored
3
.github/workflows/clang-tidy.yml
vendored
@@ -18,6 +18,7 @@ concurrency:
|
||||
|
||||
env:
|
||||
CONAN_PROFILE: clang
|
||||
LLVM_TOOLS_VERSION: 20
|
||||
|
||||
jobs:
|
||||
clang_tidy:
|
||||
@@ -61,7 +62,7 @@ jobs:
|
||||
shell: bash
|
||||
id: run_clang_tidy
|
||||
run: |
|
||||
run-clang-tidy-19 -p build -j "${{ steps.number_of_threads.outputs.threads_number }}" -fix -quiet 1>output.txt
|
||||
run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j "${{ steps.number_of_threads.outputs.threads_number }}" -fix -quiet 1>output.txt
|
||||
|
||||
- name: Fix local includes and clang-format style
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
|
||||
8
.github/workflows/pre-commit-autoupdate.yml
vendored
8
.github/workflows/pre-commit-autoupdate.yml
vendored
@@ -26,6 +26,14 @@ jobs:
|
||||
- run: pre-commit autoupdate --freeze
|
||||
- run: pre-commit run --all-files || true
|
||||
|
||||
- uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}
|
||||
git_user_signingkey: true
|
||||
git_commit_gpgsign: true
|
||||
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
if: always()
|
||||
env:
|
||||
|
||||
10
.github/workflows/release_impl.yml
vendored
10
.github/workflows/release_impl.yml
vendored
@@ -69,9 +69,9 @@ jobs:
|
||||
shell: bash
|
||||
if: ${{ inputs.generate_changelog }}
|
||||
run: |
|
||||
LAST_TAG=$(gh release view --json tagName -q .tagName)
|
||||
LAST_TAG_COMMIT=$(git rev-parse $LAST_TAG)
|
||||
BASE_COMMIT=$(git merge-base HEAD $LAST_TAG_COMMIT)
|
||||
LAST_TAG="$(gh release view --json tagName -q .tagName)"
|
||||
LAST_TAG_COMMIT="$(git rev-parse $LAST_TAG)"
|
||||
BASE_COMMIT="$(git merge-base HEAD $LAST_TAG_COMMIT)"
|
||||
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b"
|
||||
cat CHANGELOG.md >> "${RUNNER_TEMP}/release_notes.md"
|
||||
|
||||
@@ -108,10 +108,10 @@ jobs:
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
shell: bash
|
||||
run: |
|
||||
gh release create ${{ inputs.version }} \
|
||||
gh release create "${{ inputs.version }}" \
|
||||
${{ inputs.overwrite_release && '--prerelease' || '' }} \
|
||||
--title "${{ inputs.title }}" \
|
||||
--target $GITHUB_SHA \
|
||||
--target "${GITHUB_SHA}" \
|
||||
${{ inputs.draft && '--draft' || '' }} \
|
||||
--notes-file "${RUNNER_TEMP}/release_notes.md" \
|
||||
./release_artifacts/clio_server*
|
||||
|
||||
@@ -26,12 +26,12 @@ repos:
|
||||
|
||||
# Autoformat: YAML, JSON, Markdown, etc.
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: 787fb9f542b140ba0b2aced38e6a3e68021647a3 # frozen: v3.5.3
|
||||
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
||||
hooks:
|
||||
- id: prettier
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: 586c3ea3f51230da42bab657c6a32e9e66c364f0 # frozen: v0.44.0
|
||||
rev: 192ad822316c3a22fb3d3cc8aa6eafa0b8488360 # frozen: v0.45.0
|
||||
hooks:
|
||||
- id: markdownlint-fix
|
||||
exclude: LICENSE.md
|
||||
@@ -55,17 +55,32 @@ repos:
|
||||
--ignore-words=pre-commit-hooks/codespell_ignore.txt,
|
||||
]
|
||||
|
||||
# Running fix-local-includes before clang-format
|
||||
# to ensure that the include order is correct.
|
||||
# Running some C++ hooks before clang-format
|
||||
# to ensure that the style is consistent.
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: json-in-cpp
|
||||
name: Fix JSON style in C++
|
||||
entry: pre-commit-hooks/json_in_cpp.py
|
||||
types: [c++]
|
||||
language: python
|
||||
exclude: |
|
||||
(?x)^(
|
||||
tests/unit/etl/SubscriptionSourceTests.cpp|
|
||||
tests/unit/web/ServerTests.cpp|
|
||||
tests/unit/web/impl/ErrorHandlingTests.cpp|
|
||||
tests/unit/web/ng/ServerTests.cpp|
|
||||
tests/unit/web/ng/impl/ErrorHandlingTests.cpp
|
||||
)$
|
||||
|
||||
- id: fix-local-includes
|
||||
name: Fix Local Includes
|
||||
entry: pre-commit-hooks/fix-local-includes.sh
|
||||
types: [c++]
|
||||
language: script
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: f9a52e87b6cdcb01b0a62b8611d9ba9f2dad0067 # frozen: v19.1.7
|
||||
rev: 6b9072cd80691b1b48d80046d884409fb1d962d1 # frozen: v20.1.7
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [--style=file]
|
||||
|
||||
@@ -8,7 +8,7 @@ if (lint)
|
||||
endif ()
|
||||
message(STATUS "Using clang-tidy from CLIO_CLANG_TIDY_BIN")
|
||||
else ()
|
||||
find_program(_CLANG_TIDY_BIN NAMES "clang-tidy-19" "clang-tidy" REQUIRED)
|
||||
find_program(_CLANG_TIDY_BIN NAMES "clang-tidy-20" "clang-tidy" REQUIRED)
|
||||
endif ()
|
||||
|
||||
if (NOT _CLANG_TIDY_BIN)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"requires": [
|
||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1750263732.782",
|
||||
"xxhash/0.8.2#7856c968c985b2981b707ee8f2413b2b%1750263730.908",
|
||||
"xrpl/2.5.0#7880d1696f11fceb1d498570f1a184c8%1751035095.524809",
|
||||
"xrpl/2.5.0#7880d1696f11fceb1d498570f1a184c8%1751035267.743",
|
||||
"sqlite3/3.47.0#7a0904fd061f5f8a2366c294f9387830%1750263721.79",
|
||||
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1750263717.455",
|
||||
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1750263715.145",
|
||||
@@ -20,6 +20,7 @@
|
||||
"http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1750263668.751",
|
||||
"gtest/1.14.0#f8f0757a574a8dd747d16af62d6eb1b7%1750263666.833",
|
||||
"grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1750263646.614",
|
||||
"fmt/11.2.0#579bb2cdf4a7607621beea4eb4651e0f%1746298708.362",
|
||||
"fmt/10.1.1#021e170cf81db57da82b5f737b6906c1%1750263644.741",
|
||||
"date/3.0.3#cf28fe9c0aab99fe12da08aa42df65e1%1750263643.099",
|
||||
"cassandra-cpp-driver/2.17.0#e50919efac8418c26be6671fd702540a%1750263632.157",
|
||||
|
||||
@@ -26,7 +26,7 @@ class ClioConan(ConanFile):
|
||||
requires = [
|
||||
'boost/1.83.0',
|
||||
'cassandra-cpp-driver/2.17.0',
|
||||
'fmt/10.1.1',
|
||||
'fmt/11.2.0',
|
||||
'protobuf/3.21.12',
|
||||
'grpc/1.50.1',
|
||||
'openssl/1.1.1v',
|
||||
|
||||
@@ -16,7 +16,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
USER root
|
||||
WORKDIR /root
|
||||
|
||||
ARG LLVM_TOOLS_VERSION=19
|
||||
ARG LLVM_TOOLS_VERSION=20
|
||||
|
||||
# Add repositories
|
||||
RUN apt-get update \
|
||||
|
||||
@@ -8,4 +8,4 @@ compiler.version=16
|
||||
os=Linux
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={'c': '/usr/bin/clang-16', 'cpp': '/usr/bin/clang++-16'}
|
||||
tools.build:compiler_executables={"c": "/usr/bin/clang-16", "cpp": "/usr/bin/clang++-16"}
|
||||
|
||||
@@ -8,4 +8,4 @@ compiler.version=12
|
||||
os=Linux
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={'c': '/usr/bin/gcc-12', 'cpp': '/usr/bin/g++-12'}
|
||||
tools.build:compiler_executables={"c": "/usr/bin/gcc-12", "cpp": "/usr/bin/g++-12"}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
core.download:parallel={{os.cpu_count()}}
|
||||
core.upload:parallel={{os.cpu_count()}}
|
||||
tools.info.package_id:confs = ["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{% set compiler, sani = profile_name.split('.') %}
|
||||
|
||||
{% set sanitizer_opt_map = {'asan': 'address', 'tsan': 'thread', 'ubsan': 'undefined'} %}
|
||||
{% set sanitizer_opt_map = {"asan": "address", "tsan": "thread", "ubsan": "undefined"} %}
|
||||
{% set sanitizer = sanitizer_opt_map[sani] %}
|
||||
|
||||
{% set sanitizer_build_flags_str = "-fsanitize=" ~ sanitizer ~ " -g -O1 -fno-omit-frame-pointer" %}
|
||||
{% set sanitizer_build_flags = sanitizer_build_flags_str.split(' ') %}
|
||||
{% set sanitizer_link_flags_str = "-fsanitize=" ~ sanitizer %}
|
||||
@@ -10,11 +11,13 @@
|
||||
include({{ compiler }})
|
||||
|
||||
[options]
|
||||
boost/*:extra_b2_flags = "cxxflags=\"{{ sanitizer_build_flags_str }}\" linkflags=\"{{ sanitizer_link_flags_str }}\""
|
||||
boost/*:without_stacktrace = True
|
||||
boost/*:extra_b2_flags="cxxflags=\"{{ sanitizer_build_flags_str }}\" linkflags=\"{{ sanitizer_link_flags_str }}\""
|
||||
boost/*:without_stacktrace=True
|
||||
|
||||
[conf]
|
||||
tools.build:cflags += {{ sanitizer_build_flags }}
|
||||
tools.build:cxxflags += {{ sanitizer_build_flags }}
|
||||
tools.build:exelinkflags += {{ sanitizer_link_flags }}
|
||||
tools.build:sharedlinkflags += {{ sanitizer_link_flags }}
|
||||
tools.build:cflags+={{ sanitizer_build_flags }}
|
||||
tools.build:cxxflags+={{ sanitizer_build_flags }}
|
||||
tools.build:exelinkflags+={{ sanitizer_link_flags }}
|
||||
tools.build:sharedlinkflags+={{ sanitizer_link_flags }}
|
||||
|
||||
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
|
||||
|
||||
@@ -64,7 +64,7 @@ compiler.version=12
|
||||
os=Linux
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={'c': '/usr/bin/gcc-12', 'cpp': '/usr/bin/g++-12'}
|
||||
tools.build:compiler_executables={"c": "/usr/bin/gcc-12", "cpp": "/usr/bin/g++-12"}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
@@ -72,12 +72,11 @@ tools.build:compiler_executables={'c': '/usr/bin/gcc-12', 'cpp': '/usr/bin/g++-1
|
||||
|
||||
#### global.conf file
|
||||
|
||||
Add the following to the `~/.conan2/global.conf` file:
|
||||
To increase the speed of downloading and uploading packages, add the following to the `~/.conan2/global.conf` file:
|
||||
|
||||
```text
|
||||
core.download:parallel={{os.cpu_count()}}
|
||||
core.upload:parallel={{os.cpu_count()}}
|
||||
tools.info.package_id:confs = ["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
|
||||
```
|
||||
|
||||
#### Artifactory
|
||||
@@ -223,18 +222,16 @@ Sometimes, during development, you need to build against a custom version of `li
|
||||
|
||||
## Using `clang-tidy` for static analysis
|
||||
|
||||
The minimum [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) version required is 19.0.
|
||||
|
||||
Clang-tidy can be run by CMake when building the project.
|
||||
To achieve this, you just need to provide the option `-o '&:lint=True'` for the `conan install` command:
|
||||
|
||||
```sh
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True' -o '&:lint=True'
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True' -o '&:lint=True' --profile:all clang
|
||||
```
|
||||
|
||||
By default CMake will try to find `clang-tidy` automatically in your system.
|
||||
To force CMake to use your desired binary, set the `CLIO_CLANG_TIDY_BIN` environment variable to the path of the `clang-tidy` binary. For example:
|
||||
|
||||
```sh
|
||||
export CLIO_CLANG_TIDY_BIN=/opt/homebrew/opt/llvm@19/bin/clang-tidy
|
||||
export CLIO_CLANG_TIDY_BIN=/opt/homebrew/opt/llvm/bin/clang-tidy
|
||||
```
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
Clio needs access to a `rippled` server in order to work. The following configurations are required for Clio and `rippled` to communicate:
|
||||
|
||||
1. In the Clio config file, provide the following:
|
||||
|
||||
- The IP of the `rippled` server
|
||||
|
||||
- The port on which `rippled` is accepting unencrypted WebSocket connections
|
||||
@@ -13,7 +12,6 @@ Clio needs access to a `rippled` server in order to work. The following configur
|
||||
- The port on which `rippled` is handling gRPC requests
|
||||
|
||||
2. In the `rippled` config file, you need to open:
|
||||
|
||||
- A port to accept unencrypted WebSocket connections
|
||||
|
||||
- A port to handle gRPC requests, with the IP(s) of Clio specified in the `secure_gateway` entry
|
||||
|
||||
76
pre-commit-hooks/json_in_cpp.py
Executable file
76
pre-commit-hooks/json_in_cpp.py
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def fix_json_style(cpp_content: str) -> str:
|
||||
cpp_content = cpp_content.replace('R"json(', 'R"JSON(').replace(')json"', ')JSON"')
|
||||
|
||||
pattern = r'R"JSON\((.*?)\)JSON"'
|
||||
|
||||
def replace_json(match):
|
||||
raw_json = match.group(1)
|
||||
|
||||
raw_json = (
|
||||
raw_json.replace(" :", ":")
|
||||
.replace(" ,", ",")
|
||||
.replace(" null", "null")
|
||||
.replace(':"', ': "')
|
||||
.replace(',"', ', "')
|
||||
.replace('":{', '": {')
|
||||
.replace('":[', '": [')
|
||||
.replace('":true', '": true')
|
||||
.replace('":false', '": false')
|
||||
.replace('":null', '": null')
|
||||
)
|
||||
for digit in range(10):
|
||||
raw_json = raw_json.replace(f'":{digit}', f'": {digit}')
|
||||
return f'R"JSON({raw_json})JSON"'
|
||||
|
||||
return re.sub(pattern, replace_json, cpp_content, flags=re.DOTALL)
|
||||
|
||||
|
||||
def process_file(file_path: Path, dry_run: bool) -> bool:
|
||||
content = file_path.read_text(encoding="utf-8")
|
||||
new_content = fix_json_style(content)
|
||||
|
||||
if new_content != content:
|
||||
print(f"Processing file: {file_path}")
|
||||
if dry_run:
|
||||
print("Dry run: changes won't be written to the file.")
|
||||
else:
|
||||
print("Writing changes to file.")
|
||||
file_path.write_text(new_content, encoding="utf-8")
|
||||
return new_content == content
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Fix JSON style in C++ files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help="Don't modify files, just print what would be changed",
|
||||
)
|
||||
parser.add_argument(
|
||||
"files",
|
||||
nargs="*",
|
||||
help="Specific files to process",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
success = True
|
||||
for file in args.files:
|
||||
success = success and process_file(Path(file), dry_run=args.dry_run)
|
||||
if not success:
|
||||
print("Errors occurred while processing files.")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -60,17 +60,17 @@ CliArgs::parse(int argc, char const* argv[])
|
||||
po::store(po::command_line_parser(argc, argv).options(description).positional(positional).run(), parsed);
|
||||
po::notify(parsed);
|
||||
|
||||
if (parsed.count("help") != 0u) {
|
||||
if (parsed.contains("help")) {
|
||||
std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n" << description;
|
||||
return Action{Action::Exit{EXIT_SUCCESS}};
|
||||
}
|
||||
|
||||
if (parsed.count("version") != 0u) {
|
||||
if (parsed.contains("version")) {
|
||||
std::cout << util::build::getClioFullVersionString() << '\n';
|
||||
return Action{Action::Exit{EXIT_SUCCESS}};
|
||||
}
|
||||
|
||||
if (parsed.count("config-description") != 0u) {
|
||||
if (parsed.contains("config-description")) {
|
||||
std::filesystem::path const filePath = parsed["config-description"].as<std::string>();
|
||||
|
||||
auto const res = util::config::ClioConfigDescription::generateConfigDescriptionToFile(filePath);
|
||||
@@ -83,18 +83,17 @@ CliArgs::parse(int argc, char const* argv[])
|
||||
|
||||
auto configPath = parsed["conf"].as<std::string>();
|
||||
|
||||
if (parsed.count("migrate") != 0u) {
|
||||
if (parsed.contains("migrate")) {
|
||||
auto const opt = parsed["migrate"].as<std::string>();
|
||||
if (opt == "status")
|
||||
return Action{Action::Migrate{.configPath = std::move(configPath), .subCmd = MigrateSubCmd::status()}};
|
||||
return Action{Action::Migrate{.configPath = std::move(configPath), .subCmd = MigrateSubCmd::migration(opt)}};
|
||||
}
|
||||
|
||||
if (parsed.count("verify") != 0u)
|
||||
if (parsed.contains("verify"))
|
||||
return Action{Action::VerifyConfig{.configPath = std::move(configPath)}};
|
||||
|
||||
return Action{Action::Run{.configPath = std::move(configPath), .useNgWebServer = parsed.count("ng-web-server") != 0}
|
||||
};
|
||||
return Action{Action::Run{.configPath = std::move(configPath), .useNgWebServer = parsed.contains("ng-web-server")}};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
@@ -78,17 +78,20 @@ WritingAmendmentKey::WritingAmendmentKey(std::string amendmentName) : AmendmentK
|
||||
|
||||
} // namespace impl
|
||||
|
||||
AmendmentKey::operator std::string const&() const
|
||||
AmendmentKey::
|
||||
operator std::string const&() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
AmendmentKey::operator std::string_view() const
|
||||
AmendmentKey::
|
||||
operator std::string_view() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
AmendmentKey::operator ripple::uint256() const
|
||||
AmendmentKey::
|
||||
operator ripple::uint256() const
|
||||
{
|
||||
return Amendment::getAmendmentId(name);
|
||||
}
|
||||
|
||||
@@ -49,35 +49,45 @@ durationInMillisecondsSince(std::chrono::steady_clock::time_point const startTim
|
||||
using namespace util::prometheus;
|
||||
|
||||
BackendCounters::BackendCounters()
|
||||
: tooBusyCounter_(PrometheusService::counterInt(
|
||||
"backend_too_busy_total_number",
|
||||
Labels(),
|
||||
"The total number of times the backend was too busy to process a request"
|
||||
))
|
||||
, writeSyncCounter_(PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({Label{"operation", "write_sync"}}),
|
||||
"The total number of times the backend had to write synchronously"
|
||||
))
|
||||
, writeSyncRetryCounter_(PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({Label{"operation", "write_sync_retry"}}),
|
||||
"The total number of times the backend had to retry a synchronous write"
|
||||
))
|
||||
: tooBusyCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"backend_too_busy_total_number",
|
||||
Labels(),
|
||||
"The total number of times the backend was too busy to process a request"
|
||||
)
|
||||
)
|
||||
, writeSyncCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({Label{"operation", "write_sync"}}),
|
||||
"The total number of times the backend had to write synchronously"
|
||||
)
|
||||
)
|
||||
, writeSyncRetryCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({Label{"operation", "write_sync_retry"}}),
|
||||
"The total number of times the backend had to retry a synchronous write"
|
||||
)
|
||||
)
|
||||
, asyncWriteCounters_{"write_async"}
|
||||
, asyncReadCounters_{"read_async"}
|
||||
, readDurationHistogram_(PrometheusService::histogramInt(
|
||||
"backend_duration_milliseconds_histogram",
|
||||
Labels({Label{"operation", "read"}}),
|
||||
kHISTOGRAM_BUCKETS,
|
||||
"The duration of backend read operations including retries"
|
||||
))
|
||||
, writeDurationHistogram_(PrometheusService::histogramInt(
|
||||
"backend_duration_milliseconds_histogram",
|
||||
Labels({Label{"operation", "write"}}),
|
||||
kHISTOGRAM_BUCKETS,
|
||||
"The duration of backend write operations including retries"
|
||||
))
|
||||
, readDurationHistogram_(
|
||||
PrometheusService::histogramInt(
|
||||
"backend_duration_milliseconds_histogram",
|
||||
Labels({Label{"operation", "read"}}),
|
||||
kHISTOGRAM_BUCKETS,
|
||||
"The duration of backend read operations including retries"
|
||||
)
|
||||
)
|
||||
, writeDurationHistogram_(
|
||||
PrometheusService::histogramInt(
|
||||
"backend_duration_milliseconds_histogram",
|
||||
Labels({Label{"operation", "write"}}),
|
||||
kHISTOGRAM_BUCKETS,
|
||||
"The duration of backend write operations including retries"
|
||||
)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -170,26 +180,34 @@ BackendCounters::report() const
|
||||
|
||||
BackendCounters::AsyncOperationCounters::AsyncOperationCounters(std::string name)
|
||||
: name_(std::move(name))
|
||||
, pendingCounter_(PrometheusService::gaugeInt(
|
||||
"backend_operations_current_number",
|
||||
Labels({{"operation", name_}, {"status", "pending"}}),
|
||||
"The current number of pending " + name_ + " operations"
|
||||
))
|
||||
, completedCounter_(PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({{"operation", name_}, {"status", "completed"}}),
|
||||
"The total number of completed " + name_ + " operations"
|
||||
))
|
||||
, retryCounter_(PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({{"operation", name_}, {"status", "retry"}}),
|
||||
"The total number of retried " + name_ + " operations"
|
||||
))
|
||||
, errorCounter_(PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({{"operation", name_}, {"status", "error"}}),
|
||||
"The total number of errored " + name_ + " operations"
|
||||
))
|
||||
, pendingCounter_(
|
||||
PrometheusService::gaugeInt(
|
||||
"backend_operations_current_number",
|
||||
Labels({{"operation", name_}, {"status", "pending"}}),
|
||||
"The current number of pending " + name_ + " operations"
|
||||
)
|
||||
)
|
||||
, completedCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({{"operation", name_}, {"status", "completed"}}),
|
||||
"The total number of completed " + name_ + " operations"
|
||||
)
|
||||
)
|
||||
, retryCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({{"operation", name_}, {"status", "retry"}}),
|
||||
"The total number of retried " + name_ + " operations"
|
||||
)
|
||||
)
|
||||
, errorCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"backend_operations_total_number",
|
||||
Labels({{"operation", name_}, {"status", "error"}}),
|
||||
"The total number of errored " + name_ + " operations"
|
||||
)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -234,8 +234,12 @@ public:
|
||||
* @return A vector of ripple::uint256 representing the account roots
|
||||
*/
|
||||
virtual std::vector<ripple::uint256>
|
||||
fetchAccountRoots(std::uint32_t number, std::uint32_t pageSize, std::uint32_t seq, boost::asio::yield_context yield)
|
||||
const = 0;
|
||||
fetchAccountRoots(
|
||||
std::uint32_t number,
|
||||
std::uint32_t pageSize,
|
||||
std::uint32_t seq,
|
||||
boost::asio::yield_context yield
|
||||
) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Updates the range of sequences that are stored in the DB.
|
||||
@@ -459,8 +463,11 @@ public:
|
||||
* @return The sequence in unit32_t on success; nullopt otherwise
|
||||
*/
|
||||
virtual std::optional<std::uint32_t>
|
||||
doFetchLedgerObjectSeq(ripple::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield)
|
||||
const = 0;
|
||||
doFetchLedgerObjectSeq(
|
||||
ripple::uint256 const& key,
|
||||
std::uint32_t sequence,
|
||||
boost::asio::yield_context yield
|
||||
) const = 0;
|
||||
|
||||
/**
|
||||
* @brief The database-specific implementation for fetching ledger objects.
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <boost/uuid/string_generator.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <cassandra.h>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
@@ -361,8 +361,10 @@ public:
|
||||
}
|
||||
|
||||
std::vector<ripple::uint256>
|
||||
fetchAllTransactionHashesInLedger(std::uint32_t const ledgerSequence, boost::asio::yield_context yield)
|
||||
const override
|
||||
fetchAllTransactionHashesInLedger(
|
||||
std::uint32_t const ledgerSequence,
|
||||
boost::asio::yield_context yield
|
||||
) const override
|
||||
{
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto const res = executor_.read(yield, schema_->selectAllTransactionHashesInLedger, ledgerSequence);
|
||||
@@ -392,8 +394,11 @@ public:
|
||||
}
|
||||
|
||||
std::optional<NFT>
|
||||
fetchNFT(ripple::uint256 const& tokenID, std::uint32_t const ledgerSequence, boost::asio::yield_context yield)
|
||||
const override
|
||||
fetchNFT(
|
||||
ripple::uint256 const& tokenID,
|
||||
std::uint32_t const ledgerSequence,
|
||||
boost::asio::yield_context yield
|
||||
) const override
|
||||
{
|
||||
auto const res = executor_.read(yield, schema_->selectNFT, tokenID, ledgerSequence);
|
||||
if (not res)
|
||||
@@ -554,10 +559,9 @@ public:
|
||||
selectNFTStatements.reserve(nftIDs.size());
|
||||
|
||||
std::transform(
|
||||
std::cbegin(nftIDs),
|
||||
std::cend(nftIDs),
|
||||
std::back_inserter(selectNFTStatements),
|
||||
[&](auto const& nftID) { return schema_->selectNFT.bind(nftID, ledgerSequence); }
|
||||
std::cbegin(nftIDs), std::cend(nftIDs), std::back_inserter(selectNFTStatements), [&](auto const& nftID) {
|
||||
return schema_->selectNFT.bind(nftID, ledgerSequence);
|
||||
}
|
||||
);
|
||||
|
||||
auto const nftInfos = executor_.readEach(yield, selectNFTStatements);
|
||||
@@ -566,10 +570,9 @@ public:
|
||||
selectNFTURIStatements.reserve(nftIDs.size());
|
||||
|
||||
std::transform(
|
||||
std::cbegin(nftIDs),
|
||||
std::cend(nftIDs),
|
||||
std::back_inserter(selectNFTURIStatements),
|
||||
[&](auto const& nftID) { return schema_->selectNFTURI.bind(nftID, ledgerSequence); }
|
||||
std::cbegin(nftIDs), std::cend(nftIDs), std::back_inserter(selectNFTURIStatements), [&](auto const& nftID) {
|
||||
return schema_->selectNFTURI.bind(nftID, ledgerSequence);
|
||||
}
|
||||
);
|
||||
|
||||
auto const nftUris = executor_.readEach(yield, selectNFTURIStatements);
|
||||
@@ -626,8 +629,11 @@ public:
|
||||
}
|
||||
|
||||
std::optional<Blob>
|
||||
doFetchLedgerObject(ripple::uint256 const& key, std::uint32_t const sequence, boost::asio::yield_context yield)
|
||||
const override
|
||||
doFetchLedgerObject(
|
||||
ripple::uint256 const& key,
|
||||
std::uint32_t const sequence,
|
||||
boost::asio::yield_context yield
|
||||
) const override
|
||||
{
|
||||
LOG(log_.debug()) << "Fetching ledger object for seq " << sequence << ", key = " << ripple::to_string(key);
|
||||
if (auto const res = executor_.read(yield, schema_->selectObject, key, sequence); res) {
|
||||
@@ -645,8 +651,11 @@ public:
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t>
|
||||
doFetchLedgerObjectSeq(ripple::uint256 const& key, std::uint32_t const sequence, boost::asio::yield_context yield)
|
||||
const override
|
||||
doFetchLedgerObjectSeq(
|
||||
ripple::uint256 const& key,
|
||||
std::uint32_t const sequence,
|
||||
boost::asio::yield_context yield
|
||||
) const override
|
||||
{
|
||||
LOG(log_.debug()) << "Fetching ledger object for seq " << sequence << ", key = " << ripple::to_string(key);
|
||||
if (auto const res = executor_.read(yield, schema_->selectObject, key, sequence); res) {
|
||||
@@ -680,8 +689,11 @@ public:
|
||||
}
|
||||
|
||||
std::optional<ripple::uint256>
|
||||
doFetchSuccessorKey(ripple::uint256 key, std::uint32_t const ledgerSequence, boost::asio::yield_context yield)
|
||||
const override
|
||||
doFetchSuccessorKey(
|
||||
ripple::uint256 key,
|
||||
std::uint32_t const ledgerSequence,
|
||||
boost::asio::yield_context yield
|
||||
) const override
|
||||
{
|
||||
if (auto const res = executor_.read(yield, schema_->selectSuccessor, key, ledgerSequence); res) {
|
||||
if (auto const result = res->template get<ripple::uint256>(); result) {
|
||||
@@ -714,10 +726,9 @@ public:
|
||||
auto const timeDiff = util::timed([this, yield, &results, &hashes, &statements]() {
|
||||
// TODO: seems like a job for "hash IN (list of hashes)" instead?
|
||||
std::transform(
|
||||
std::cbegin(hashes),
|
||||
std::cend(hashes),
|
||||
std::back_inserter(statements),
|
||||
[this](auto const& hash) { return schema_->selectTransaction.bind(hash); }
|
||||
std::cbegin(hashes), std::cend(hashes), std::back_inserter(statements), [this](auto const& hash) {
|
||||
return schema_->selectTransaction.bind(hash);
|
||||
}
|
||||
);
|
||||
|
||||
auto const entries = executor_.readEach(yield, statements);
|
||||
@@ -761,18 +772,14 @@ public:
|
||||
|
||||
// TODO: seems like a job for "key IN (list of keys)" instead?
|
||||
std::transform(
|
||||
std::cbegin(keys),
|
||||
std::cend(keys),
|
||||
std::back_inserter(statements),
|
||||
[this, &sequence](auto const& key) { return schema_->selectObject.bind(key, sequence); }
|
||||
std::cbegin(keys), std::cend(keys), std::back_inserter(statements), [this, &sequence](auto const& key) {
|
||||
return schema_->selectObject.bind(key, sequence);
|
||||
}
|
||||
);
|
||||
|
||||
auto const entries = executor_.readEach(yield, statements);
|
||||
std::transform(
|
||||
std::cbegin(entries),
|
||||
std::cend(entries),
|
||||
std::back_inserter(results),
|
||||
[](auto const& res) -> Blob {
|
||||
std::cbegin(entries), std::cend(entries), std::back_inserter(results), [](auto const& res) -> Blob {
|
||||
if (auto const maybeValue = res.template get<Blob>(); maybeValue)
|
||||
return *maybeValue;
|
||||
|
||||
@@ -785,8 +792,12 @@ public:
|
||||
}
|
||||
|
||||
std::vector<ripple::uint256>
|
||||
fetchAccountRoots(std::uint32_t number, std::uint32_t pageSize, std::uint32_t seq, boost::asio::yield_context yield)
|
||||
const override
|
||||
fetchAccountRoots(
|
||||
std::uint32_t number,
|
||||
std::uint32_t pageSize,
|
||||
std::uint32_t seq,
|
||||
boost::asio::yield_context yield
|
||||
) const override
|
||||
{
|
||||
std::vector<ripple::uint256> liveAccounts;
|
||||
std::optional<ripple::AccountID> lastItem;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <cassandra.h>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@@ -45,7 +45,8 @@ Cluster::Cluster(Settings const& settings) : ManagedObject{cass_cluster_new(), k
|
||||
|
||||
cass_cluster_set_token_aware_routing(*this, cass_true);
|
||||
if (auto const rc = cass_cluster_set_protocol_version(*this, CASS_PROTOCOL_VERSION_V4); rc != CASS_OK) {
|
||||
throw std::runtime_error(fmt::format("Error setting cassandra protocol version to v4: {}", cass_error_desc(rc))
|
||||
throw std::runtime_error(
|
||||
fmt::format("Error setting cassandra protocol version to v4: {}", cass_error_desc(rc))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,13 @@ public:
|
||||
* @brief Create a new retry policy instance with the io_context provided
|
||||
*/
|
||||
ExponentialBackoffRetryPolicy(boost::asio::io_context& ioc)
|
||||
: retry_(util::makeRetryExponentialBackoff(
|
||||
std::chrono::milliseconds(1),
|
||||
std::chrono::seconds(1),
|
||||
boost::asio::make_strand(ioc)
|
||||
))
|
||||
: retry_(
|
||||
util::makeRetryExponentialBackoff(
|
||||
std::chrono::milliseconds(1),
|
||||
std::chrono::seconds(1),
|
||||
boost::asio::make_strand(ioc)
|
||||
)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#include <cassandra.h>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/STAccount.h>
|
||||
|
||||
@@ -171,9 +171,11 @@ ETLService::runETLPipeline(uint32_t startSequence, uint32_t numExtractors)
|
||||
auto pipe = DataPipeType{numExtractors, startSequence};
|
||||
|
||||
for (auto i = 0u; i < numExtractors; ++i) {
|
||||
extractors.push_back(std::make_unique<ExtractorType>(
|
||||
pipe, networkValidatedLedgers_, ledgerFetcher_, startSequence + i, finishSequence_, state_
|
||||
));
|
||||
extractors.push_back(
|
||||
std::make_unique<ExtractorType>(
|
||||
pipe, networkValidatedLedgers_, ledgerFetcher_, startSequence + i, finishSequence_, state_
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
auto transformer =
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -184,11 +184,14 @@ LoadBalancer::LoadBalancer(
|
||||
LOG(log_.warn()) << "Failed to fetch ETL state from source = " << source->toString()
|
||||
<< " Please check the configuration and network";
|
||||
} else if (etlState_ && etlState_->networkID != stateOpt->networkID) {
|
||||
checkOnETLFailure(fmt::format(
|
||||
"ETL sources must be on the same network. Source network id = {} does not match others network id = {}",
|
||||
stateOpt->networkID,
|
||||
etlState_->networkID
|
||||
));
|
||||
checkOnETLFailure(
|
||||
fmt::format(
|
||||
"ETL sources must be on the same network. Source network id = {} does not match others network id "
|
||||
"= {}",
|
||||
stateOpt->networkID,
|
||||
etlState_->networkID
|
||||
)
|
||||
);
|
||||
} else {
|
||||
etlState_ = stateOpt;
|
||||
}
|
||||
@@ -278,9 +281,8 @@ LoadBalancer::forwardToRippled(
|
||||
|
||||
if (forwardingCache_ and forwardingCache_->shouldCache(cmd)) {
|
||||
bool servedFromCache = true;
|
||||
auto updater =
|
||||
[this, &request, &clientIp, &servedFromCache, isAdmin](boost::asio::yield_context yield
|
||||
) -> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
|
||||
auto updater = [this, &request, &clientIp, &servedFromCache, isAdmin](boost::asio::yield_context yield)
|
||||
-> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
|
||||
servedFromCache = false;
|
||||
auto result = forwardToRippledImpl(request, clientIp, isAdmin, yield);
|
||||
if (result.has_value()) {
|
||||
@@ -294,10 +296,9 @@ LoadBalancer::forwardToRippled(
|
||||
};
|
||||
|
||||
auto result = forwardingCache_->getOrUpdate(
|
||||
yield,
|
||||
cmd,
|
||||
std::move(updater),
|
||||
[](util::ResponseExpirationCache::EntryData const& entry) { return not entry.response.contains("error"); }
|
||||
yield, cmd, std::move(updater), [](util::ResponseExpirationCache::EntryData const& entry) {
|
||||
return not entry.response.contains("error");
|
||||
}
|
||||
);
|
||||
if (servedFromCache) {
|
||||
++forwardingCounters_.cacheHit.get();
|
||||
|
||||
@@ -172,8 +172,10 @@ public:
|
||||
* @return A std::vector<std::string> The ledger data
|
||||
*/
|
||||
std::vector<std::string>
|
||||
loadInitialLedger(uint32_t sequence, std::chrono::steady_clock::duration retryAfter = std::chrono::seconds{2})
|
||||
override;
|
||||
loadInitialLedger(
|
||||
uint32_t sequence,
|
||||
std::chrono::steady_clock::duration retryAfter = std::chrono::seconds{2}
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Load the initial ledger, writing data to the queue.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "data/DBHelpers.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -138,7 +138,8 @@ getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
|
||||
// There should always be a difference so the returned finalIDs
|
||||
// iterator should never be end(). But better safe than sorry.
|
||||
if (finalIDs.size() != prevIDs.size() + 1 || diff.first == finalIDs.end() || !owner) {
|
||||
throw std::runtime_error(fmt::format(" - unexpected NFTokenMint data in tx {}", strHex(sttx.getTransactionID()))
|
||||
throw std::runtime_error(
|
||||
fmt::format(" - unexpected NFTokenMint data in tx {}", strHex(sttx.getTransactionID()))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,8 +94,8 @@ private:
|
||||
double totalTime = 0.0;
|
||||
auto currentSequence = startSequence_;
|
||||
|
||||
while (!shouldFinish(currentSequence) && networkValidatedLedgers_->waitUntilValidatedByNetwork(currentSequence)
|
||||
) {
|
||||
while (!shouldFinish(currentSequence) &&
|
||||
networkValidatedLedgers_->waitUntilValidatedByNetwork(currentSequence)) {
|
||||
auto [fetchResponse, time] = ::util::timed<std::chrono::duration<double>>([this, currentSequence]() {
|
||||
return ledgerFetcher_.get().fetchDataAndDiff(currentSequence);
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <grpcpp/client_context.h>
|
||||
#include <grpcpp/security/credentials.h>
|
||||
#include <grpcpp/support/channel_arguments.h>
|
||||
|
||||
@@ -209,47 +209,49 @@ public:
|
||||
size_t numWrites = 0;
|
||||
backend_->cache().setFull();
|
||||
|
||||
auto seconds = ::util::timed<std::chrono::seconds>([this, keys = std::move(edgeKeys), sequence, &numWrites](
|
||||
) mutable {
|
||||
for (auto& key : keys) {
|
||||
LOG(log_.debug()) << "Writing edge key = " << ripple::strHex(key);
|
||||
auto succ = backend_->cache().getSuccessor(*ripple::uint256::fromVoidChecked(key), sequence);
|
||||
if (succ)
|
||||
backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
|
||||
}
|
||||
|
||||
ripple::uint256 prev = data::kFIRST_KEY;
|
||||
while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
|
||||
ASSERT(cur.has_value(), "Successor for key {} must exist", ripple::strHex(prev));
|
||||
if (prev == data::kFIRST_KEY)
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
|
||||
|
||||
if (isBookDir(cur->key, cur->blob)) {
|
||||
auto base = getBookBase(cur->key);
|
||||
// make sure the base is not an actual object
|
||||
if (!backend_->cache().get(base, sequence)) {
|
||||
auto succ = backend_->cache().getSuccessor(base, sequence);
|
||||
ASSERT(succ.has_value(), "Book base {} must have a successor", ripple::strHex(base));
|
||||
if (succ->key == cur->key) {
|
||||
LOG(log_.debug()) << "Writing book successor = " << ripple::strHex(base) << " - "
|
||||
<< ripple::strHex(cur->key);
|
||||
|
||||
backend_->writeSuccessor(uint256ToString(base), sequence, uint256ToString(cur->key));
|
||||
}
|
||||
}
|
||||
|
||||
++numWrites;
|
||||
auto seconds =
|
||||
::util::timed<std::chrono::seconds>([this, keys = std::move(edgeKeys), sequence, &numWrites]() mutable {
|
||||
for (auto& key : keys) {
|
||||
LOG(log_.debug()) << "Writing edge key = " << ripple::strHex(key);
|
||||
auto succ = backend_->cache().getSuccessor(*ripple::uint256::fromVoidChecked(key), sequence);
|
||||
if (succ)
|
||||
backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
|
||||
}
|
||||
|
||||
prev = cur->key;
|
||||
static constexpr std::size_t kLOG_STRIDE = 100000;
|
||||
if (numWrites % kLOG_STRIDE == 0 && numWrites != 0)
|
||||
LOG(log_.info()) << "Wrote " << numWrites << " book successors";
|
||||
}
|
||||
ripple::uint256 prev = data::kFIRST_KEY;
|
||||
while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
|
||||
ASSERT(cur.has_value(), "Successor for key {} must exist", ripple::strHex(prev));
|
||||
if (prev == data::kFIRST_KEY)
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
|
||||
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::kLAST_KEY));
|
||||
++numWrites;
|
||||
});
|
||||
if (isBookDir(cur->key, cur->blob)) {
|
||||
auto base = getBookBase(cur->key);
|
||||
// make sure the base is not an actual object
|
||||
if (!backend_->cache().get(base, sequence)) {
|
||||
auto succ = backend_->cache().getSuccessor(base, sequence);
|
||||
ASSERT(succ.has_value(), "Book base {} must have a successor", ripple::strHex(base));
|
||||
if (succ->key == cur->key) {
|
||||
LOG(log_.debug()) << "Writing book successor = " << ripple::strHex(base) << " - "
|
||||
<< ripple::strHex(cur->key);
|
||||
|
||||
backend_->writeSuccessor(
|
||||
uint256ToString(base), sequence, uint256ToString(cur->key)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
++numWrites;
|
||||
}
|
||||
|
||||
prev = cur->key;
|
||||
static constexpr std::size_t kLOG_STRIDE = 100000;
|
||||
if (numWrites % kLOG_STRIDE == 0 && numWrites != 0)
|
||||
LOG(log_.info()) << "Wrote " << numWrites << " book successors";
|
||||
}
|
||||
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::kLAST_KEY));
|
||||
++numWrites;
|
||||
});
|
||||
|
||||
LOG(log_.info()) << "Looping through cache and submitting all writes took " << seconds
|
||||
<< " seconds. numWrites = " << std::to_string(numWrites);
|
||||
|
||||
@@ -249,8 +249,9 @@ public:
|
||||
std::chrono::time_point<std::chrono::system_clock>
|
||||
getLastPublish() const override
|
||||
{
|
||||
return std::chrono::time_point<std::chrono::system_clock>{std::chrono::seconds{lastPublishSeconds_.get().value()
|
||||
}};
|
||||
return std::chrono::time_point<std::chrono::system_clock>{
|
||||
std::chrono::seconds{lastPublishSeconds_.get().value()}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -79,11 +79,13 @@ SubscriptionSource::SubscriptionSource(
|
||||
, onConnect_(std::move(onConnect))
|
||||
, onDisconnect_(std::move(onDisconnect))
|
||||
, onLedgerClosed_(std::move(onLedgerClosed))
|
||||
, lastMessageTimeSecondsSinceEpoch_(PrometheusService::gaugeInt(
|
||||
"subscription_source_last_message_time",
|
||||
util::prometheus::Labels({{"source", fmt::format("{}:{}", ip, wsPort)}}),
|
||||
"Seconds since epoch of the last message received from rippled subscription streams"
|
||||
))
|
||||
, lastMessageTimeSecondsSinceEpoch_(
|
||||
PrometheusService::gaugeInt(
|
||||
"subscription_source_last_message_time",
|
||||
util::prometheus::Labels({{"source", fmt::format("{}:{}", ip, wsPort)}}),
|
||||
"Seconds since epoch of the last message received from rippled subscription streams"
|
||||
)
|
||||
)
|
||||
{
|
||||
wsConnectionBuilder_.addHeader({boost::beast::http::field::user_agent, "clio-client"})
|
||||
.addHeader({"X-User", "clio-client"})
|
||||
@@ -329,9 +331,13 @@ SubscriptionSource::setValidatedRange(std::string range)
|
||||
pairs.emplace_back(sequence, sequence);
|
||||
} else {
|
||||
if (minAndMax.size() != 2) {
|
||||
throw std::runtime_error(fmt::format(
|
||||
"Error parsing range: {}.Min and max should be of size 2. Got size = {}", range, minAndMax.size()
|
||||
));
|
||||
throw std::runtime_error(
|
||||
fmt::format(
|
||||
"Error parsing range: {}.Min and max should be of size 2. Got size = {}",
|
||||
range,
|
||||
minAndMax.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
uint32_t const min = std::stoll(minAndMax[0]);
|
||||
uint32_t const max = std::stoll(minAndMax[1]);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/beast/http/field.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/signals2/connection.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/signals2/connection.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -184,11 +184,14 @@ LoadBalancer::LoadBalancer(
|
||||
LOG(log_.warn()) << "Failed to fetch ETL state from source = " << source->toString()
|
||||
<< " Please check the configuration and network";
|
||||
} else if (etlState_ && etlState_->networkID != stateOpt->networkID) {
|
||||
checkOnETLFailure(fmt::format(
|
||||
"ETL sources must be on the same network. Source network id = {} does not match others network id = {}",
|
||||
stateOpt->networkID,
|
||||
etlState_->networkID
|
||||
));
|
||||
checkOnETLFailure(
|
||||
fmt::format(
|
||||
"ETL sources must be on the same network. Source network id = {} does not match others network id "
|
||||
"= {}",
|
||||
stateOpt->networkID,
|
||||
etlState_->networkID
|
||||
)
|
||||
);
|
||||
} else {
|
||||
etlState_ = stateOpt;
|
||||
}
|
||||
@@ -284,9 +287,8 @@ LoadBalancer::forwardToRippled(
|
||||
|
||||
if (forwardingCache_ and forwardingCache_->shouldCache(cmd)) {
|
||||
bool servedFromCache = true;
|
||||
auto updater =
|
||||
[this, &request, &clientIp, &servedFromCache, isAdmin](boost::asio::yield_context yield
|
||||
) -> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
|
||||
auto updater = [this, &request, &clientIp, &servedFromCache, isAdmin](boost::asio::yield_context yield)
|
||||
-> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
|
||||
servedFromCache = false;
|
||||
auto result = forwardToRippledImpl(request, clientIp, isAdmin, yield);
|
||||
if (result.has_value()) {
|
||||
@@ -300,10 +302,9 @@ LoadBalancer::forwardToRippled(
|
||||
};
|
||||
|
||||
auto result = forwardingCache_->getOrUpdate(
|
||||
yield,
|
||||
cmd,
|
||||
std::move(updater),
|
||||
[](util::ResponseExpirationCache::EntryData const& entry) { return not entry.response.contains("error"); }
|
||||
yield, cmd, std::move(updater), [](util::ResponseExpirationCache::EntryData const& entry) {
|
||||
return not entry.response.contains("error");
|
||||
}
|
||||
);
|
||||
if (servedFromCache) {
|
||||
++forwardingCounters_.cacheHit.get();
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "util/Concepts.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/proto/org/xrpl/rpc/v1/get_ledger.pb.h>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "web/Resolver.hpp"
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <grpcpp/client_context.h>
|
||||
#include <grpcpp/security/credentials.h>
|
||||
#include <grpcpp/support/channel_arguments.h>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/protocol/Fees.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
@@ -227,8 +227,9 @@ public:
|
||||
std::chrono::time_point<std::chrono::system_clock>
|
||||
getLastPublish() const override
|
||||
{
|
||||
return std::chrono::time_point<std::chrono::system_clock>{std::chrono::seconds{lastPublishSeconds_.get().value()
|
||||
}};
|
||||
return std::chrono::time_point<std::chrono::system_clock>{
|
||||
std::chrono::seconds{lastPublishSeconds_.get().value()}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -159,8 +159,10 @@ public:
|
||||
* @param transactions The transactions in the current ledger.
|
||||
*/
|
||||
void
|
||||
pubBookChanges(ripple::LedgerHeader const& lgrInfo, std::vector<data::TransactionAndMetadata> const& transactions)
|
||||
final;
|
||||
pubBookChanges(
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
std::vector<data::TransactionAndMetadata> const& transactions
|
||||
) final;
|
||||
|
||||
/**
|
||||
* @brief Subscribe to the proposed transactions feed.
|
||||
|
||||
@@ -57,9 +57,7 @@ ProposedTransactionFeed::sub(ripple::AccountID const& account, SubscriberSharedP
|
||||
{
|
||||
auto const weakPtr = std::weak_ptr(subscriber);
|
||||
auto const added = accountSignal_.connectTrackableSlot(
|
||||
subscriber,
|
||||
account,
|
||||
[this, weakPtr](std::shared_ptr<std::string> const& msg) {
|
||||
subscriber, account, [this, weakPtr](std::shared_ptr<std::string> const& msg) {
|
||||
if (auto connectionPtr = weakPtr.lock()) {
|
||||
// Check if this connection already sent
|
||||
if (notified_.contains(connectionPtr.get()))
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
|
||||
@@ -280,7 +280,7 @@ TransactionFeed::pub(
|
||||
data->getFieldAmount(ripple::sfTakerPays).issue(),
|
||||
(*data)[~ripple::sfDomainID]
|
||||
};
|
||||
if (affectedBooks.find(book) == affectedBooks.end()) {
|
||||
if (!affectedBooks.contains(book)) {
|
||||
affectedBooks.insert(book);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "util/prometheus/Label.hpp"
|
||||
#include "util/prometheus/Prometheus.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ Most indexes are based on either ledger states or transactions. We provide the `
|
||||
If you need to do full scan against other table, you can follow below steps:
|
||||
|
||||
- Describe the table which needs full scan in a struct. It has to satisfy the `TableSpec`(cassandra/Spec.hpp) concept, containing static member:
|
||||
|
||||
- Tuple type `Row`, it's the type of each field in a row. The order of types should match what database will return in a row. Key types should come first, followed by other field types sorted in alphabetical order.
|
||||
- `kPARTITION_KEY`, it's the name of the partition key of the table.
|
||||
- `kTABLE_NAME`
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "data/cassandra/SettingsProvider.hpp"
|
||||
#include "data/cassandra/Types.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
@@ -63,16 +63,18 @@ public:
|
||||
std::string const& key
|
||||
)
|
||||
{
|
||||
return handler.prepare(fmt::format(
|
||||
R"(
|
||||
return handler.prepare(
|
||||
fmt::format(
|
||||
R"(
|
||||
SELECT *
|
||||
FROM {}
|
||||
WHERE TOKEN({}) >= ? AND TOKEN({}) <= ?
|
||||
)",
|
||||
data::cassandra::qualifiedTableName<SettingsProviderType>(settingsProvider_.get(), tableName),
|
||||
key,
|
||||
key
|
||||
));
|
||||
data::cassandra::qualifiedTableName<SettingsProviderType>(settingsProvider_.get(), tableName),
|
||||
key,
|
||||
key
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,14 +86,16 @@ public:
|
||||
data::cassandra::PreparedStatement const&
|
||||
getPreparedInsertMigratedMigrator(data::cassandra::Handle const& handler)
|
||||
{
|
||||
static auto kPREPARED = handler.prepare(fmt::format(
|
||||
R"(
|
||||
static auto kPREPARED = handler.prepare(
|
||||
fmt::format(
|
||||
R"(
|
||||
INSERT INTO {}
|
||||
(migrator_name, status)
|
||||
VALUES (?, ?)
|
||||
)",
|
||||
data::cassandra::qualifiedTableName<SettingsProviderType>(settingsProvider_.get(), "migrator_status")
|
||||
));
|
||||
data::cassandra::qualifiedTableName<SettingsProviderType>(settingsProvider_.get(), "migrator_status")
|
||||
)
|
||||
);
|
||||
return kPREPARED;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "util/prometheus/Prometheus.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <chrono>
|
||||
@@ -40,41 +40,55 @@ using util::prometheus::Label;
|
||||
using util::prometheus::Labels;
|
||||
|
||||
Counters::MethodInfo::MethodInfo(std::string const& method)
|
||||
: started(PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "started"}, {"method", method}}},
|
||||
fmt::format("Total number of started calls to the method {}", method)
|
||||
))
|
||||
, finished(PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "finished"}, {"method", method}}},
|
||||
fmt::format("Total number of finished calls to the method {}", method)
|
||||
))
|
||||
, failed(PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "failed"}, {"method", method}}},
|
||||
fmt::format("Total number of failed calls to the method {}", method)
|
||||
))
|
||||
, errored(PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "errored"}, {"method", method}}},
|
||||
fmt::format("Total number of errored calls to the method {}", method)
|
||||
))
|
||||
, forwarded(PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "forwarded"}, {"method", method}}},
|
||||
fmt::format("Total number of forwarded calls to the method {}", method)
|
||||
))
|
||||
, failedForward(PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "failed_forward"}, {"method", method}}},
|
||||
fmt::format("Total number of failed forwarded calls to the method {}", method)
|
||||
))
|
||||
, duration(PrometheusService::counterInt(
|
||||
"rpc_method_duration_us",
|
||||
Labels({util::prometheus::Label{"method", method}}),
|
||||
fmt::format("Total duration of calls to the method {}", method)
|
||||
))
|
||||
: started(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "started"}, {"method", method}}},
|
||||
fmt::format("Total number of started calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
, finished(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "finished"}, {"method", method}}},
|
||||
fmt::format("Total number of finished calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
, failed(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "failed"}, {"method", method}}},
|
||||
fmt::format("Total number of failed calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
, errored(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "errored"}, {"method", method}}},
|
||||
fmt::format("Total number of errored calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
, forwarded(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "forwarded"}, {"method", method}}},
|
||||
fmt::format("Total number of forwarded calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
, failedForward(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_total_number",
|
||||
Labels{{{"status", "failed_forward"}, {"method", method}}},
|
||||
fmt::format("Total number of failed forwarded calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
, duration(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_method_duration_us",
|
||||
Labels({util::prometheus::Label{"method", method}}),
|
||||
fmt::format("Total duration of calls to the method {}", method)
|
||||
)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -89,31 +103,41 @@ Counters::getMethodInfo(std::string const& method)
|
||||
}
|
||||
|
||||
Counters::Counters(WorkQueue const& wq)
|
||||
: tooBusyCounter_(PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "too_busy"}}),
|
||||
"Total number of too busy errors"
|
||||
))
|
||||
, notReadyCounter_(PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "not_ready"}}),
|
||||
"Total number of not ready replyes"
|
||||
))
|
||||
, badSyntaxCounter_(PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "bad_syntax"}}),
|
||||
"Total number of bad syntax replyes"
|
||||
))
|
||||
, unknownCommandCounter_(PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "unknown_command"}}),
|
||||
"Total number of unknown command replyes"
|
||||
))
|
||||
, internalErrorCounter_(PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "internal_error"}}),
|
||||
"Total number of internal errors"
|
||||
))
|
||||
: tooBusyCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "too_busy"}}),
|
||||
"Total number of too busy errors"
|
||||
)
|
||||
)
|
||||
, notReadyCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "not_ready"}}),
|
||||
"Total number of not ready replyes"
|
||||
)
|
||||
)
|
||||
, badSyntaxCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "bad_syntax"}}),
|
||||
"Total number of bad syntax replyes"
|
||||
)
|
||||
)
|
||||
, unknownCommandCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "unknown_command"}}),
|
||||
"Total number of unknown command replyes"
|
||||
)
|
||||
)
|
||||
, internalErrorCounter_(
|
||||
PrometheusService::counterInt(
|
||||
"rpc_error_total_number",
|
||||
Labels({Label{"error_type", "internal_error"}}),
|
||||
"Total number of internal errors"
|
||||
)
|
||||
)
|
||||
, workQueue_(std::cref(wq))
|
||||
, startupTime_{std::chrono::system_clock::now()}
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@ See [tests/unit/rpc](https://github.com/XRPLF/clio/tree/develop/tests/unit/rpc)
|
||||
Handlers need to fulfil the requirements specified by the `SomeHandler` concept (see `rpc/common/Concepts.hpp`):
|
||||
|
||||
- Expose types:
|
||||
|
||||
- `Input` - The POD struct which acts as input for the handler
|
||||
|
||||
- `Output` - The POD struct which acts as output of a valid handler invocation
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/json.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
|
||||
@@ -159,9 +158,8 @@ public:
|
||||
}
|
||||
|
||||
if (not ctx.isAdmin and responseCache_ and responseCache_->shouldCache(ctx.method)) {
|
||||
auto updater =
|
||||
[this, &ctx](boost::asio::yield_context
|
||||
) -> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
|
||||
auto updater = [this, &ctx](boost::asio::yield_context)
|
||||
-> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
|
||||
auto result = buildResponseImpl(ctx);
|
||||
|
||||
auto const extracted =
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/lexical_cast/bad_lexical_cast.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
@@ -1283,9 +1283,10 @@ postProcessOrderBook(
|
||||
} else {
|
||||
saTakerGetsFunded = saOwnerFundsLimit;
|
||||
offerJson["taker_gets_funded"] = toBoostJson(saTakerGetsFunded.getJson(ripple::JsonOptions::none));
|
||||
offerJson["taker_pays_funded"] =
|
||||
toBoostJson(std::min(saTakerPays, ripple::multiply(saTakerGetsFunded, dirRate, saTakerPays.issue()))
|
||||
.getJson(ripple::JsonOptions::none));
|
||||
offerJson["taker_pays_funded"] = toBoostJson(
|
||||
std::min(saTakerPays, ripple::multiply(saTakerGetsFunded, dirRate, saTakerPays.issue()))
|
||||
.getJson(ripple::JsonOptions::none)
|
||||
);
|
||||
}
|
||||
|
||||
ripple::STAmount const saOwnerPays = (ripple::parityRate == offerRate)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/regex/v5/regex_fwd.hpp>
|
||||
#include <boost/regex/v5/regex_match.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
@@ -46,7 +46,8 @@ WorkQueue::OneTimeCallable::operator()()
|
||||
called_ = true;
|
||||
}
|
||||
}
|
||||
WorkQueue::OneTimeCallable::operator bool() const
|
||||
WorkQueue::OneTimeCallable::
|
||||
operator bool() const
|
||||
{
|
||||
return func_.operator bool();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "rpc/common/Types.hpp"
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@@ -107,8 +107,8 @@ public:
|
||||
template <SomeRequirement... Requirements>
|
||||
explicit IfType(Requirements&&... requirements)
|
||||
: processor_(
|
||||
[... r = std::forward<Requirements>(requirements
|
||||
)](boost::json::value& j, std::string_view key) -> MaybeError {
|
||||
[... r = std::forward<Requirements>(requirements)](boost::json::value& j, std::string_view key)
|
||||
-> MaybeError {
|
||||
std::optional<Status> firstFailure = std::nullopt;
|
||||
|
||||
// the check logic is the same as fieldspec
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
|
||||
@@ -457,7 +457,10 @@ public:
|
||||
checkIsU32Numeric(std::string_view sv);
|
||||
|
||||
template <class HexType>
|
||||
requires(std::is_same_v<HexType, ripple::uint160> || std::is_same_v<HexType, ripple::uint192> || std::is_same_v<HexType, ripple::uint256>)
|
||||
requires(
|
||||
std::is_same_v<HexType, ripple::uint160> || std::is_same_v<HexType, ripple::uint192> ||
|
||||
std::is_same_v<HexType, ripple::uint256>
|
||||
)
|
||||
MaybeError
|
||||
makeHexStringValidator(boost::json::value const& value, std::string_view key)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
|
||||
@@ -108,9 +108,11 @@ GetAggregatePriceHandler::process(GetAggregatePriceHandler::Input input, Context
|
||||
auto const scale =
|
||||
iter->isFieldPresent(ripple::sfScale) ? -static_cast<int>(iter->getFieldU8(ripple::sfScale)) : 0;
|
||||
|
||||
timestampPricesBiMap.insert(TimestampPricesBiMap::value_type(
|
||||
node.getFieldU32(ripple::sfLastUpdateTime), ripple::STAmount{ripple::noIssue(), price, scale}
|
||||
));
|
||||
timestampPricesBiMap.insert(
|
||||
TimestampPricesBiMap::value_type(
|
||||
node.getFieldU32(ripple::sfLastUpdateTime), ripple::STAmount{ripple::noIssue(), price, scale}
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -263,12 +265,14 @@ tag_invoke(boost::json::value_to_tag<GetAggregatePriceHandler::Input>, boost::js
|
||||
}
|
||||
|
||||
for (auto const& oracle : jsonObject.at(JS(oracles)).as_array()) {
|
||||
input.oracles.push_back(GetAggregatePriceHandler::Oracle{
|
||||
.documentId = boost::json::value_to<std::uint64_t>(oracle.as_object().at(JS(oracle_document_id))),
|
||||
.account = *util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(oracle.as_object().at(JS(account)))
|
||||
)
|
||||
});
|
||||
input.oracles.push_back(
|
||||
GetAggregatePriceHandler::Oracle{
|
||||
.documentId = boost::json::value_to<std::uint64_t>(oracle.as_object().at(JS(oracle_document_id))),
|
||||
.account = *util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(oracle.as_object().at(JS(account)))
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
input.baseAsset = boost::json::value_to<std::string>(jv.at(JS(base_asset)));
|
||||
input.quoteAsset = boost::json::value_to<std::string>(jv.at(JS(quote_asset)));
|
||||
|
||||
@@ -75,9 +75,9 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
|
||||
key = expectedkey.value();
|
||||
} else if (input.offer) {
|
||||
auto const id =
|
||||
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(input.offer->at(JS(account)))
|
||||
);
|
||||
auto const id = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(input.offer->at(JS(account)))
|
||||
);
|
||||
key = ripple::keylet::offer(*id, boost::json::value_to<std::uint32_t>(input.offer->at(JS(seq)))).key;
|
||||
} else if (input.rippleStateAccount) {
|
||||
auto const id1 = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
@@ -91,9 +91,9 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
|
||||
key = ripple::keylet::line(*id1, *id2, currency).key;
|
||||
} else if (input.escrow) {
|
||||
auto const id =
|
||||
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(input.escrow->at(JS(owner)))
|
||||
);
|
||||
auto const id = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(input.escrow->at(JS(owner)))
|
||||
);
|
||||
key = ripple::keylet::escrow(*id, input.escrow->at(JS(seq)).as_int64()).key;
|
||||
} else if (input.depositPreauth) {
|
||||
auto const owner = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
@@ -124,9 +124,9 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
key = ripple::keylet::depositPreauth(owner.value(), authCreds).key;
|
||||
}
|
||||
} else if (input.ticket) {
|
||||
auto const id =
|
||||
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(input.ticket->at(JS(account))
|
||||
));
|
||||
auto const id = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(input.ticket->at(JS(account)))
|
||||
);
|
||||
|
||||
key = ripple::getTicketIndex(*id, input.ticket->at(JS(ticket_seq)).as_int64());
|
||||
} else if (input.amm) {
|
||||
@@ -136,9 +136,9 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
if (ripple::isXRP(currency)) {
|
||||
return ripple::xrpIssue();
|
||||
}
|
||||
auto const issuer =
|
||||
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(assetJson.at(JS(issuer)))
|
||||
);
|
||||
auto const issuer = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(assetJson.at(JS(issuer)))
|
||||
);
|
||||
return ripple::Issue{currency, *issuer};
|
||||
};
|
||||
|
||||
@@ -174,9 +174,9 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
} else if (input.mptoken) {
|
||||
auto const holder =
|
||||
ripple::parseBase58<ripple::AccountID>(boost::json::value_to<std::string>(input.mptoken->at(JS(account))));
|
||||
auto const mptIssuanceID =
|
||||
ripple::uint192{std::string_view(boost::json::value_to<std::string>(input.mptoken->at(JS(mpt_issuance_id))))
|
||||
};
|
||||
auto const mptIssuanceID = ripple::uint192{
|
||||
std::string_view(boost::json::value_to<std::string>(input.mptoken->at(JS(mpt_issuance_id))))
|
||||
};
|
||||
key = ripple::keylet::mptoken(mptIssuanceID, *holder).key;
|
||||
} else if (input.permissionedDomain) {
|
||||
auto const account = ripple::parseBase58<ripple::AccountID>(
|
||||
@@ -192,9 +192,9 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
} else if (input.delegate) {
|
||||
auto const account =
|
||||
ripple::parseBase58<ripple::AccountID>(boost::json::value_to<std::string>(input.delegate->at(JS(account))));
|
||||
auto const authorize =
|
||||
ripple::parseBase58<ripple::AccountID>(boost::json::value_to<std::string>(input.delegate->at(JS(authorize)))
|
||||
);
|
||||
auto const authorize = ripple::parseBase58<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(input.delegate->at(JS(authorize)))
|
||||
);
|
||||
key = ripple::keylet::delegate(*account, *authorize).key;
|
||||
} else {
|
||||
// Must specify 1 of the following fields to indicate what type
|
||||
|
||||
@@ -146,12 +146,12 @@ public:
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, "malformedAccounts"}};
|
||||
}
|
||||
|
||||
auto const id1 =
|
||||
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(value.as_array()[0])
|
||||
);
|
||||
auto const id2 =
|
||||
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(value.as_array()[1])
|
||||
);
|
||||
auto const id1 = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(value.as_array()[0])
|
||||
);
|
||||
auto const id2 = util::parseBase58Wrapper<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(value.as_array()[1])
|
||||
);
|
||||
|
||||
if (!id1 || !id2)
|
||||
return Error{Status{ClioError::RpcMalformedAddress, "malformedAddresses"}};
|
||||
|
||||
@@ -138,14 +138,7 @@ NFTOffersHandlerBase::iterateOfferDirectory(
|
||||
}
|
||||
|
||||
auto result = traverseOwnedNodes(
|
||||
*sharedPtrBackend_,
|
||||
directory,
|
||||
cursor,
|
||||
startHint,
|
||||
lgrInfo.seq,
|
||||
reserve,
|
||||
yield,
|
||||
[&offers](ripple::SLE&& offer) {
|
||||
*sharedPtrBackend_, directory, cursor, startHint, lgrInfo.seq, reserve, yield, [&offers](ripple::SLE&& offer) {
|
||||
if (offer.getType() == ripple::ltNFTOKEN_OFFER) {
|
||||
offers.push_back(std::move(offer));
|
||||
return true;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/BuildInfo.h>
|
||||
|
||||
@@ -140,8 +140,10 @@ private:
|
||||
subscribeToAccounts(std::vector<std::string> const& accounts, feed::SubscriberSharedPtr const& session) const;
|
||||
|
||||
void
|
||||
subscribeToAccountsProposed(std::vector<std::string> const& accounts, feed::SubscriberSharedPtr const& session)
|
||||
const;
|
||||
subscribeToAccountsProposed(
|
||||
std::vector<std::string> const& accounts,
|
||||
feed::SubscriberSharedPtr const& session
|
||||
) const;
|
||||
|
||||
void
|
||||
subscribeToBooks(
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
|
||||
@@ -129,8 +129,10 @@ UnsubscribeHandler::unsubscribeFromStreams(
|
||||
}
|
||||
|
||||
void
|
||||
UnsubscribeHandler::unsubscribeFromAccounts(std::vector<std::string> accounts, feed::SubscriberSharedPtr const& session)
|
||||
const
|
||||
UnsubscribeHandler::unsubscribeFromAccounts(
|
||||
std::vector<std::string> accounts,
|
||||
feed::SubscriberSharedPtr const& session
|
||||
) const
|
||||
{
|
||||
for (auto const& account : accounts) {
|
||||
auto const accountID = accountFromStringStrict(account);
|
||||
@@ -150,8 +152,10 @@ UnsubscribeHandler::unsubscribeFromProposedAccounts(
|
||||
}
|
||||
}
|
||||
void
|
||||
UnsubscribeHandler::unsubscribeFromBooks(std::vector<OrderBook> const& books, feed::SubscriberSharedPtr const& session)
|
||||
const
|
||||
UnsubscribeHandler::unsubscribeFromBooks(
|
||||
std::vector<OrderBook> const& books,
|
||||
feed::SubscriberSharedPtr const& session
|
||||
) const
|
||||
{
|
||||
for (auto const& orderBook : books) {
|
||||
subscriptions_->unsubBook(orderBook.book, session);
|
||||
|
||||
@@ -106,8 +106,10 @@ private:
|
||||
unsubscribeFromAccounts(std::vector<std::string> accounts, feed::SubscriberSharedPtr const& session) const;
|
||||
|
||||
void
|
||||
unsubscribeFromProposedAccounts(std::vector<std::string> accountsProposed, feed::SubscriberSharedPtr const& session)
|
||||
const;
|
||||
unsubscribeFromProposedAccounts(
|
||||
std::vector<std::string> accountsProposed,
|
||||
feed::SubscriberSharedPtr const& session
|
||||
) const;
|
||||
|
||||
void
|
||||
unsubscribeFromBooks(std::vector<OrderBook> const& books, feed::SubscriberSharedPtr const& session) const;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <boost/stacktrace/stacktrace.hpp>
|
||||
#endif // CLIO_WITHOUT_STACKTRACE
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -134,8 +134,7 @@ public:
|
||||
return;
|
||||
|
||||
boost::asio::spawn(
|
||||
yield_,
|
||||
[signal = familySignal_, fn = std::move(fn)](boost::asio::yield_context yield) mutable {
|
||||
yield_, [signal = familySignal_, fn = std::move(fn)](boost::asio::yield_context yield) mutable {
|
||||
Coroutine coroutine(std::move(yield), std::move(signal));
|
||||
fn(coroutine);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ LedgerTypes::getLedgerEntryTypeFromStr(std::string const& entryName)
|
||||
return map;
|
||||
}();
|
||||
|
||||
if (kTYPE_MAP.find(entryName) == kTYPE_MAP.end())
|
||||
if (!kTYPE_MAP.contains(entryName))
|
||||
return ripple::ltANY;
|
||||
|
||||
return kTYPE_MAP.at(entryName);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "rpc/JS.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
|
||||
@@ -78,8 +78,7 @@ SignalsHandler::SignalsHandler(config::ClioConfigDefinition const& config, std::
|
||||
<< " milliseconds.";
|
||||
setHandler(impl::SignalsHandlerStatic::handleSecondSignal);
|
||||
timer_.emplace(context_.scheduleAfter(
|
||||
gracefulPeriod_,
|
||||
[forceExitHandler = std::move(forceExitHandler)](auto&& stopToken, bool canceled) {
|
||||
gracefulPeriod_, [forceExitHandler = std::move(forceExitHandler)](auto&& stopToken, bool canceled) {
|
||||
// TODO: Update this after https://github.com/XRPLF/clio/issues/1380
|
||||
if (not stopToken.isStopRequested() and not canceled) {
|
||||
LOG(LogService::warn()) << "Force exit at the end of graceful period.";
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <fmt/base.h>
|
||||
#include <fmt/chrono.h>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -166,17 +166,16 @@ public:
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(delay);
|
||||
return AnyOperation<RetType>(pimpl_->scheduleAfter(
|
||||
millis,
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) -> std::any {
|
||||
return AnyOperation<RetType>(
|
||||
pimpl_->scheduleAfter(millis, [fn = std::forward<decltype(fn)>(fn)](auto stopToken) -> std::any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
fn(std::move(stopToken));
|
||||
return {};
|
||||
} else {
|
||||
return std::make_any<RetType>(fn(std::move(stopToken)));
|
||||
}
|
||||
}
|
||||
));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,8 +196,7 @@ public:
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(delay);
|
||||
return AnyOperation<RetType>(pimpl_->scheduleAfter(
|
||||
millis,
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken, auto cancelled) -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)](auto stopToken, auto cancelled) -> std::any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
fn(std::move(stopToken), cancelled);
|
||||
return {};
|
||||
@@ -224,13 +222,10 @@ public:
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->executeRepeatedly(
|
||||
millis,
|
||||
[fn = std::forward<decltype(fn)>(fn)] -> std::any {
|
||||
fn();
|
||||
return {};
|
||||
}
|
||||
)
|
||||
pimpl_->executeRepeatedly(millis, [fn = std::forward<decltype(fn)>(fn)] -> std::any {
|
||||
fn();
|
||||
return {};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/std.h>
|
||||
|
||||
#include <any>
|
||||
|
||||
@@ -146,13 +146,10 @@ public:
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->executeRepeatedly(
|
||||
millis,
|
||||
[fn = std::forward<decltype(fn)>(fn)] -> std::any {
|
||||
fn();
|
||||
return {};
|
||||
}
|
||||
)
|
||||
pimpl_->executeRepeatedly(millis, [fn = std::forward<decltype(fn)>(fn)] -> std::any {
|
||||
fn();
|
||||
return {};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ template <typename T>
|
||||
concept SomeStdDuration = requires {
|
||||
// Thank you Ed Catmur for this trick.
|
||||
// See https://stackoverflow.com/questions/74383254/concept-that-models-only-the-stdchrono-duration-types
|
||||
[]<typename Rep, typename Period>( //
|
||||
[]<typename Rep, typename Period>( //
|
||||
std::type_identity<std::chrono::duration<Rep, Period>>
|
||||
) {}(std::type_identity<std::decay_t<T>>());
|
||||
};
|
||||
@@ -180,7 +180,7 @@ concept SomeStdDuration = requires {
|
||||
*/
|
||||
template <typename T>
|
||||
concept SomeStdOptional = requires {
|
||||
[]<typename Type>( //
|
||||
[]<typename Type>( //
|
||||
std::type_identity<std::optional<Type>>
|
||||
) {}(std::type_identity<std::decay_t<T>>());
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/std.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "util/async/context/impl/Cancellation.hpp"
|
||||
#include "util/async/context/impl/Timer.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/Error.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/std.h>
|
||||
|
||||
#include <exception>
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "util/config/Types.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include "util/config/Types.hpp"
|
||||
#include "util/config/ValueView.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
|
||||
@@ -259,8 +259,8 @@ private:
|
||||
* without default values must be present in the user's config file.
|
||||
*/
|
||||
static ClioConfigDefinition gClioConfig = ClioConfigDefinition{
|
||||
{{"database.type", ConfigValue{ConfigType::String}.defaultValue("cassandra").withConstraint(gValidateCassandraName)
|
||||
},
|
||||
{{"database.type",
|
||||
ConfigValue{ConfigType::String}.defaultValue("cassandra").withConstraint(gValidateCassandraName)},
|
||||
{"database.cassandra.contact_points", ConfigValue{ConfigType::String}.defaultValue("localhost")},
|
||||
{"database.cassandra.secure_connect_bundle", ConfigValue{ConfigType::String}.optional()},
|
||||
{"database.cassandra.port", ConfigValue{ConfigType::Integer}.withConstraint(gValidatePort).optional()},
|
||||
@@ -284,10 +284,10 @@ static ClioConfigDefinition gClioConfig = ClioConfigDefinition{
|
||||
{"database.cassandra.queue_size_io", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint16)},
|
||||
{"database.cassandra.write_batch_size",
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(20).withConstraint(gValidateUint16)},
|
||||
{"database.cassandra.connect_timeout", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)
|
||||
},
|
||||
{"database.cassandra.request_timeout", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)
|
||||
},
|
||||
{"database.cassandra.connect_timeout",
|
||||
ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)},
|
||||
{"database.cassandra.request_timeout",
|
||||
ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)},
|
||||
{"database.cassandra.username", ConfigValue{ConfigType::String}.optional()},
|
||||
{"database.cassandra.password", ConfigValue{ConfigType::String}.optional()},
|
||||
{"database.cassandra.certfile", ConfigValue{ConfigType::String}.optional()},
|
||||
@@ -308,8 +308,8 @@ static ClioConfigDefinition gClioConfig = ClioConfigDefinition{
|
||||
{"num_markers", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateNumMarkers)},
|
||||
|
||||
{"dos_guard.whitelist.[]", Array{ConfigValue{ConfigType::String}.optional()}},
|
||||
{"dos_guard.max_fetches", ConfigValue{ConfigType::Integer}.defaultValue(1000'000u).withConstraint(gValidateUint32)
|
||||
},
|
||||
{"dos_guard.max_fetches",
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(1000'000u).withConstraint(gValidateUint32)},
|
||||
{"dos_guard.max_connections", ConfigValue{ConfigType::Integer}.defaultValue(20u).withConstraint(gValidateUint32)},
|
||||
{"dos_guard.max_requests", ConfigValue{ConfigType::Integer}.defaultValue(20u).withConstraint(gValidateUint32)},
|
||||
{"dos_guard.sweep_interval",
|
||||
@@ -358,8 +358,8 @@ static ClioConfigDefinition gClioConfig = ClioConfigDefinition{
|
||||
{"cache.page_fetch_size", ConfigValue{ConfigType::Integer}.defaultValue(512).withConstraint(gValidateUint16)},
|
||||
{"cache.load", ConfigValue{ConfigType::String}.defaultValue("async").withConstraint(gValidateLoadMode)},
|
||||
|
||||
{"log_channels.[].channel", Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidateChannelName)}
|
||||
},
|
||||
{"log_channels.[].channel",
|
||||
Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidateChannelName)}},
|
||||
{"log_channels.[].log_level",
|
||||
Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidateLogLevelName)}},
|
||||
|
||||
@@ -376,8 +376,8 @@ static ClioConfigDefinition gClioConfig = ClioConfigDefinition{
|
||||
|
||||
{"log_rotation_size", ConfigValue{ConfigType::Integer}.defaultValue(2048).withConstraint(gValidateUint32)},
|
||||
|
||||
{"log_directory_max_size", ConfigValue{ConfigType::Integer}.defaultValue(50 * 1024).withConstraint(gValidateUint32)
|
||||
},
|
||||
{"log_directory_max_size",
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(50 * 1024).withConstraint(gValidateUint32)},
|
||||
|
||||
{"log_rotation_hour_interval", ConfigValue{ConfigType::Integer}.defaultValue(12).withConstraint(gValidateUint32)},
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "util/config/ConfigDefinition.hpp"
|
||||
#include "util/config/Error.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -134,10 +134,11 @@ public:
|
||||
|
||||
private:
|
||||
static constexpr auto kCONFIG_DESCRIPTION = std::array{
|
||||
KV{.key = "database.type",
|
||||
.value =
|
||||
"Specifies the type of database used for storing and retrieving data required by the Clio server. Both "
|
||||
"ScyllaDB and Cassandra can serve as backends for Clio; however, this value must be set to `cassandra`."
|
||||
KV{
|
||||
.key = "database.type",
|
||||
.value =
|
||||
"Specifies the type of database used for storing and retrieving data required by the Clio server. Both "
|
||||
"ScyllaDB and Cassandra can serve as backends for Clio; however, this value must be set to `cassandra`."
|
||||
},
|
||||
KV{.key = "database.cassandra.contact_points",
|
||||
.value = "A list of IP addresses or hostnames for the initial cluster nodes (Cassandra or ScyllaDB) that "
|
||||
@@ -190,9 +191,8 @@ private:
|
||||
.value = "Specifies the timeout duration (in seconds) for the forwarding cache used in `rippled` "
|
||||
"communication. A value of `0` means disabling this feature."},
|
||||
KV{.key = "forwarding.request_timeout",
|
||||
.value =
|
||||
"Specifies the timeout duration (in seconds) for the forwarding request used in `rippled` communication."
|
||||
},
|
||||
.value = "Specifies the timeout duration (in seconds) for the forwarding request used in `rippled` "
|
||||
"communication."},
|
||||
KV{.key = "rpc.cache_timeout",
|
||||
.value = "Specifies the timeout duration (in seconds) for RPC cache response to timeout. A value of `0` "
|
||||
"means disabling this feature."},
|
||||
@@ -201,16 +201,15 @@ private:
|
||||
KV{.key = "dos_guard.max_fetches", .value = "The maximum number of fetch operations allowed by DOS guard."},
|
||||
KV{.key = "dos_guard.max_connections",
|
||||
.value = "The maximum number of concurrent connections for a specific IP address."},
|
||||
KV{.key = "dos_guard.max_requests", .value = "The maximum number of requests allowed for a specific IP address."
|
||||
},
|
||||
KV{.key = "dos_guard.max_requests",
|
||||
.value = "The maximum number of requests allowed for a specific IP address."},
|
||||
KV{.key = "dos_guard.sweep_interval", .value = "Interval in seconds for DOS guard to sweep(clear) its state."},
|
||||
KV{.key = "workers", .value = "The number of threads used to process RPC requests."},
|
||||
KV{.key = "server.ip", .value = "The IP address of the Clio HTTP server."},
|
||||
KV{.key = "server.port", .value = "The port number of the Clio HTTP server."},
|
||||
KV{.key = "server.max_queue_size",
|
||||
.value =
|
||||
"The maximum size of the server's request queue. If set to `0`, this means there is no queue size limit."
|
||||
},
|
||||
.value = "The maximum size of the server's request queue. If set to `0`, this means there is no queue size "
|
||||
"limit."},
|
||||
KV{.key = "server.local_admin",
|
||||
.value = "Indicates if requests from `localhost` are allowed to call Clio admin-only APIs. Note that this "
|
||||
"setting cannot be enabled "
|
||||
@@ -232,8 +231,8 @@ private:
|
||||
"client is slow to receive it, ensuring delivery once the client is ready."},
|
||||
KV{.key = "prometheus.enabled", .value = "Enables or disables Prometheus metrics."},
|
||||
KV{.key = "prometheus.compress_reply", .value = "Enables or disables compression of Prometheus responses."},
|
||||
KV{.key = "io_threads", .value = "The number of input/output (I/O) threads. The value cannot be less than `1`."
|
||||
},
|
||||
KV{.key = "io_threads",
|
||||
.value = "The number of input/output (I/O) threads. The value cannot be less than `1`."},
|
||||
KV{.key = "subscription_workers",
|
||||
.value = "The number of worker threads or processes that are responsible for managing and processing "
|
||||
"subscription-based tasks from `rippled`."},
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/parse_options.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "util/config/Error.hpp"
|
||||
#include "util/config/Types.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "util/config/ConfigDefinition.hpp"
|
||||
#include "util/config/ValueView.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "util/config/ConfigValue.hpp"
|
||||
#include "util/config/Types.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <boost/log/utility/setup/console.hpp>
|
||||
#include <boost/log/utility/setup/file.hpp>
|
||||
#include <boost/log/utility/setup/formatter_parser.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "util/prometheus/Label.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
@@ -78,8 +78,12 @@ public:
|
||||
) override;
|
||||
|
||||
std::unique_ptr<MetricBase>
|
||||
operator()(std::string name, std::string labelsString, MetricType type, std::vector<double> const& buckets)
|
||||
override;
|
||||
operator()(
|
||||
std::string name,
|
||||
std::string labelsString,
|
||||
MetricType type,
|
||||
std::vector<double> const& buckets
|
||||
) override;
|
||||
|
||||
private:
|
||||
static std::unique_ptr<MetricBase>
|
||||
|
||||
@@ -75,10 +75,9 @@ public:
|
||||
{
|
||||
auto data = data_->template lock<std::scoped_lock>();
|
||||
auto const bucket = std::lower_bound(
|
||||
data->buckets.begin(),
|
||||
data->buckets.end(),
|
||||
value,
|
||||
[](Bucket const& bucket, ValueType const& value) { return bucket.upperBound < value; }
|
||||
data->buckets.begin(), data->buckets.end(), value, [](Bucket const& bucket, ValueType const& value) {
|
||||
return bucket.upperBound < value;
|
||||
}
|
||||
);
|
||||
if (bucket != data->buckets.end()) {
|
||||
++bucket->count;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user