Compare commits

..

31 Commits

Author SHA1 Message Date
github-actions[bot]
eaf770ccca style: Update pre-commit hooks (#3087)
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-06-01 11:57:14 +01:00
dependabot[bot]
ffca7f9de0 ci: [DEPENDABOT] bump docker/setup-qemu-action from 4.0.0 to 4.1.0 in /.github/actions/build-docker-image (#3088)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-01 11:44:22 +01:00
Ayaz Salikhov
16c0a64394 chore: Rewrite verify-commits script (#3086) 2026-05-28 11:20:19 +01:00
Ayaz Salikhov
267fe05a8f style: Run shfmt on workflows and actions (#3085) 2026-05-28 11:03:38 +01:00
Ayaz Salikhov
25c0dc6f1c ci: Only push to DockerHub in main repo (#3084) 2026-05-27 14:38:37 +01:00
dependabot[bot]
76043d607f ci: [DEPENDABOT] bump docker/build-push-action from 7.1.0 to 7.2.0 in /.github/actions/build-docker-image (#3083)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:33:12 +01:00
dependabot[bot]
8e7f07d1cf ci: [DEPENDABOT] bump docker/login-action from 4.1.0 to 4.2.0 in /.github/actions/build-docker-image (#3082)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:33:03 +01:00
dependabot[bot]
43c3732116 ci: [DEPENDABOT] bump docker/metadata-action from 6.0.0 to 6.1.0 in /.github/actions/build-docker-image (#3081)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:32:52 +01:00
dependabot[bot]
13f65b6c3c ci: [DEPENDABOT] bump docker/setup-buildx-action from 4.0.0 to 4.1.0 in /.github/actions/build-docker-image (#3080)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:32:40 +01:00
dependabot[bot]
aed2240cbd ci: [DEPENDABOT] bump codecov/codecov-action from 6.0.0 to 6.0.1 (#3079)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:32:32 +01:00
dependabot[bot]
4da9de304e ci: [DEPENDABOT] bump docker/setup-buildx-action from 4.0.0 to 4.1.0 (#3078)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:32:22 +01:00
dependabot[bot]
f189dbf950 ci: [DEPENDABOT] bump docker/login-action from 4.1.0 to 4.2.0 (#3077)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-26 11:32:16 +01:00
Alex Kremer
cc4f204d9e style: More clang-tidy identifier renaming (#3076) 2026-05-19 15:25:47 +01:00
Ayaz Salikhov
f4dcfe20e9 ci: Run actions/configure-pages only in the main repo (#3075) 2026-05-14 18:14:48 +01:00
Ayaz Salikhov
3112a3d214 ci: Fix how workflows behave in forks (#3074) 2026-05-14 17:59:33 +01:00
Alex Kremer
dbc98894ba refactor: Rename static constants (#3073) 2026-05-13 12:09:06 +01:00
Sergey Kuznetsov
d056c72212 test: Fix integration tests (#3072)
Fix 2 issues in integration tests:
- `127.0.0.2` is forwarded to localhost on macos
- Keyspace is always dropped in test's destructor but it may not exist
2026-05-12 13:49:39 +01:00
Sergey Kuznetsov
a1112bf318 chore: Update libxrpl to 3.1.3 (#3070) 2026-05-11 14:13:22 +01:00
Sergey Kuznetsov
e974e1899f fix: Don't cache responses to admin's requests (#3058) 2026-05-05 17:00:59 +01:00
Ayaz Salikhov
a7090f5b19 ci: Print tidy errors (#3068) 2026-05-05 16:30:49 +01:00
Ayaz Salikhov
f2158cd2d9 ci: Make clang-tidy work on individual files in PRs (#3067) 2026-05-05 15:51:25 +01:00
Alex Kremer
e96ef39857 chore: Fix clang-tidy issues after introducing new checks (#3061) 2026-05-05 15:21:54 +01:00
Ayaz Salikhov
5fe7c4407b ci: Use XRPLF/create-issue (#3066) 2026-05-05 14:21:36 +01:00
Ayaz Salikhov
9b20f1871e style: Update pre-commit hooks (#3057) 2026-05-01 15:32:13 +01:00
Alex Kremer
51244feb4a chore: Enable more clang-tidy checks (#3054) 2026-05-01 15:31:45 +01:00
Ayaz Salikhov
d6bae6c12b ci: Rename print-env -> print-build-env (#3056) 2026-05-01 11:07:32 +01:00
Ayaz Salikhov
fe30c87e2c ci: Use print-env from XRLPF/actions (#3053) 2026-04-29 18:28:45 +01:00
Ayaz Salikhov
c88ffa7c92 chore: Use LLVM tools 21 (#3051) 2026-04-29 16:34:21 +01:00
Ayaz Salikhov
32aeda0ce7 chore: Fix clang-tidy 21 issues (#3052) 2026-04-29 16:17:32 +01:00
Ayaz Salikhov
f174b47f49 ci: Build image with LLVM tools 21 (#3049) 2026-04-29 14:25:10 +01:00
Ayaz Salikhov
80cdb3234a ci: Upload clang-tidy git diff (#3050) 2026-04-29 13:28:46 +01:00
458 changed files with 8674 additions and 8227 deletions

View File

@@ -4,6 +4,7 @@ Checks: "-*,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-bool-pointer-implicit-conversion,
bugprone-capturing-this-in-member-variable,
bugprone-casting-through-void,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
@@ -23,6 +24,7 @@ Checks: "-*,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misleading-setter-of-reference,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
@@ -64,6 +66,7 @@ Checks: "-*,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-unchecked-optional-access,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-exception-at-new,
@@ -82,6 +85,7 @@ Checks: "-*,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-rvalue-reference-param-not-moved,
cppcoreguidelines-use-default-member-init,
cppcoreguidelines-use-enum-class,
cppcoreguidelines-virtual-class-destructor,
hicpp-ignored-remove-result,
llvm-namespace-comment,
@@ -105,8 +109,10 @@ Checks: "-*,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-override,
modernize-use-ranges,
modernize-use-scoped-lock,
modernize-use-starts-ends-with,
modernize-use-std-numbers,
modernize-use-using,
@@ -118,6 +124,7 @@ Checks: "-*,
performance-move-constructor-init,
performance-no-automatic-move,
performance-trivially-destructible,
readability-ambiguous-smartptr-reset-call,
readability-avoid-nested-conditional-operator,
readability-avoid-return-with-void-value,
readability-braces-around-statements,
@@ -128,9 +135,9 @@ Checks: "-*,
readability-duplicate-include,
readability-else-after-return,
readability-enum-initial-value,
readability-identifier-naming,
readability-implicit-bool-conversion,
readability-inconsistent-declaration-parameter-name,
readability-identifier-naming,
readability-make-member-function-const,
readability-math-missing-parentheses,
readability-misleading-indentation,
@@ -149,6 +156,11 @@ Checks: "-*,
"
CheckOptions:
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
readability-braces-around-statements.ShortStatementLines: 2
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
readability-identifier-naming.ClassCase: CamelCase
@@ -157,7 +169,7 @@ CheckOptions:
readability-identifier-naming.EnumCase: CamelCase
readability-identifier-naming.EnumConstantCase: CamelCase
readability-identifier-naming.ScopedEnumConstantCase: CamelCase
readability-identifier-naming.GlobalConstantCase: UPPER_CASE
readability-identifier-naming.GlobalConstantCase: CamelCase
readability-identifier-naming.GlobalConstantPrefix: "k"
readability-identifier-naming.GlobalVariableCase: CamelCase
readability-identifier-naming.GlobalVariablePrefix: "g"
@@ -165,27 +177,25 @@ CheckOptions:
readability-identifier-naming.ConstexprMethodCase: camelBack
readability-identifier-naming.ClassMethodCase: camelBack
readability-identifier-naming.ClassMemberCase: camelBack
readability-identifier-naming.ClassConstantCase: UPPER_CASE
readability-identifier-naming.ClassConstantCase: CamelCase
readability-identifier-naming.ClassConstantPrefix: "k"
readability-identifier-naming.StaticConstantCase: UPPER_CASE
readability-identifier-naming.StaticConstantCase: CamelCase
readability-identifier-naming.StaticConstantPrefix: "k"
readability-identifier-naming.StaticVariableCase: UPPER_CASE
readability-identifier-naming.StaticVariablePrefix: "k"
readability-identifier-naming.ConstexprVariableCase: UPPER_CASE
readability-identifier-naming.ConstexprVariablePrefix: "k"
readability-identifier-naming.StaticVariableCase: camelBack
readability-identifier-naming.ConstexprVariableCase: camelBack
readability-identifier-naming.LocalConstantCase: camelBack
readability-identifier-naming.LocalVariableCase: camelBack
readability-identifier-naming.TemplateParameterCase: CamelCase
readability-identifier-naming.ParameterCase: camelBack
readability-identifier-naming.FunctionCase: camelBack
readability-identifier-naming.MemberCase: camelBack
readability-identifier-naming.PrivateMemberCase: camelBack
readability-identifier-naming.PrivateMemberSuffix: _
readability-identifier-naming.ProtectedMemberCase: camelBack
readability-identifier-naming.ProtectedMemberSuffix: _
readability-identifier-naming.PublicMemberCase: camelBack
readability-identifier-naming.PublicMemberSuffix: ""
readability-identifier-naming.FunctionIgnoredRegexp: ".*tag_invoke.*"
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
HeaderFilterRegex: '^.*/(src|tests)/.*\.(h|hpp)$'
WarningsAsErrors: "*"

View File

@@ -26,6 +26,6 @@ runs:
run: |
cd build
cmake \
--build . \
--parallel "${{ steps.nproc.outputs.nproc }}" \
--target ${CMAKE_TARGETS}
--build . \
--parallel "${{ steps.nproc.outputs.nproc }}" \
--target ${CMAKE_TARGETS}

View File

@@ -34,32 +34,32 @@ runs:
steps:
- name: Login to DockerHub
if: ${{ inputs.push_image == 'true' && inputs.dockerhub_repo != '' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_PW }}
- name: Login to GitHub Container Registry
if: ${{ inputs.push_image == 'true' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ env.GITHUB_TOKEN }}
- uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
with:
cache-image: false
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta
with:
images: ${{ inputs.images }}
tags: ${{ inputs.tags }}
- name: Build and push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: ${{ inputs.directory }}
platforms: ${{ inputs.platforms }}

View File

@@ -38,4 +38,4 @@ runs:
CODE_COVERAGE: ${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}
CONAN_PROFILE: ${{ inputs.conan_profile }}
run: |
echo "key=clio-ccache-${RUNNER_OS}-${BUILD_TYPE}${CODE_COVERAGE}-${CONAN_PROFILE}-develop" >> "${GITHUB_OUTPUT}"
echo "key=clio-ccache-${RUNNER_OS}-${BUILD_TYPE}${CODE_COVERAGE}-${CONAN_PROFILE}-develop" >>"${GITHUB_OUTPUT}"

View File

@@ -76,16 +76,16 @@ runs:
FORCE_CLIO_VERSION: ${{ inputs.version }}
run: |
cmake \
-B "${BUILD_DIR}" \
-S . \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
"${SANITIZER_OPTION}" \
-Dtests=ON \
-Dintegration_tests="${INTEGRATION_TESTS}" \
-Dbenchmark="${BENCHMARK}" \
-Dcoverage="${COVERAGE}" \
-Dstatic="${STATIC}" \
-Dtime_trace="${TIME_TRACE}" \
-Dpackage="${PACKAGE}"
-B "${BUILD_DIR}" \
-S . \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
"${SANITIZER_OPTION}" \
-Dtests=ON \
-Dintegration_tests="${INTEGRATION_TESTS}" \
-Dbenchmark="${BENCHMARK}" \
-Dcoverage="${COVERAGE}" \
-Dstatic="${STATIC}" \
-Dtime_trace="${TIME_TRACE}" \
-Dpackage="${PACKAGE}"

View File

@@ -15,13 +15,13 @@ runs:
shell: bash
run: |
gcovr \
-e benchmarks \
-e tests \
-e src/data/cassandra \
-e src/data/CassandraBackend.hpp \
-e 'src/data/BackendFactory.*' \
--xml build/coverage_report.xml \
-j8 --exclude-throw-branches
-e benchmarks \
-e tests \
-e src/data/cassandra \
-e src/data/CassandraBackend.hpp \
-e 'src/data/BackendFactory.*' \
--xml build/coverage_report.xml \
-j8 --exclude-throw-branches
- name: Archive coverage report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1

View File

@@ -30,8 +30,8 @@ runs:
CONAN_PROFILE: "${{ inputs.conan_profile }}"
run: |
conan \
install . \
-of "${BUILD_DIR}" \
-b "${CONAN_BUILD_OPTION}" \
-s "build_type=${BUILD_TYPE}" \
--profile:all "${CONAN_PROFILE}"
install . \
-of "${BUILD_DIR}" \
-b "${CONAN_BUILD_OPTION}" \
-s "build_type=${BUILD_TYPE}" \
--profile:all "${CONAN_PROFILE}"

View File

@@ -1,46 +0,0 @@
name: Create an issue
description: Create an issue
inputs:
title:
description: Issue title
required: true
body:
description: Issue body
required: true
labels:
description: Comma-separated list of labels
required: true
default: "bug"
assignees:
description: Comma-separated list of assignees
required: true
default: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
outputs:
created_issue_id:
description: Created issue id
value: ${{ steps.create_issue.outputs.created_issue }}
runs:
using: composite
steps:
- name: Create an issue
id: create_issue
shell: bash
env:
ISSUE_BODY: ${{ inputs.body }}
ISSUE_ASSIGNEES: ${{ inputs.assignees }}
ISSUE_LABELS: ${{ inputs.labels }}
ISSUE_TITLE: ${{ inputs.title }}
run: |
echo -e "${ISSUE_BODY}" > issue.md
gh issue create \
--assignee "${ISSUE_ASSIGNEES}" \
--label "${ISSUE_LABELS}" \
--title "${ISSUE_TITLE}" \
--body-file ./issue.md \
> create_issue.log
created_issue="$(sed 's|.*/||' create_issue.log)"
echo "created_issue=$created_issue" >> $GITHUB_OUTPUT
rm create_issue.log issue.md

View File

@@ -13,4 +13,4 @@ runs:
id: find_common_ancestor
shell: bash
run: |
echo "commit=\"$(git merge-base --fork-point origin/develop)\"" >> $GITHUB_OUTPUT
echo "commit=\"$(git merge-base --fork-point origin/develop)\"" >>$GITHUB_OUTPUT

View File

@@ -78,19 +78,6 @@ updates:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/create-issue/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
reviewers:
- XRPLF/clio-dev-team
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/git-common-ancestor/
schedule:

View File

@@ -14,9 +14,9 @@ on:
type: boolean
description: Whether to strip clio binary
default: true
publish_image:
push_image:
type: boolean
description: Whether to publish docker image
description: Whether to push docker image
required: true
workflow_dispatch:
@@ -43,7 +43,7 @@ defaults:
shell: bash
jobs:
build_and_publish_image:
build_and_push_image:
name: Build and publish image
runs-on: ubuntu-latest
@@ -65,8 +65,8 @@ jobs:
run: |
wget "${BINARY_URL}" -P ./docker/clio/artifact/
if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${BINARY_SHA256}" ]; then
echo "Binary sha256 sum doesn't match"
exit 1
echo "Binary sha256 sum doesn't match"
exit 1
fi
- name: Unpack binary
run: |
@@ -74,9 +74,9 @@ jobs:
cd docker/clio/artifact
artifact=$(find . -type f)
if [[ $artifact == *.zip ]]; then
unzip $artifact
unzip $artifact
elif [[ $artifact == *.tar.gz ]]; then
tar -xvf $artifact
tar -xvf $artifact
fi
chmod +x ./clio_server
mv ./clio_server ../
@@ -90,7 +90,7 @@ jobs:
- name: Set GHCR_REPO
id: set-ghcr-repo
run: |
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> ${GITHUB_OUTPUT}
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >>${GITHUB_OUTPUT}
- name: Build Docker image
uses: ./.github/actions/build-docker-image
@@ -102,7 +102,7 @@ jobs:
images: |
ghcr.io/${{ steps.set-ghcr-repo.outputs.GHCR_REPO }}/clio
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio' || '' }}
push_image: ${{ inputs.publish_image }}
push_image: ${{ inputs.push_image }}
directory: docker/clio
tags: ${{ inputs.tags }}
platforms: linux/amd64

View File

@@ -15,7 +15,6 @@ on:
- ".github/actions/**"
- "!.github/actions/build-docker-image/**"
- "!.github/actions/create-issue/**"
- CMakeLists.txt
- conanfile.py

View File

@@ -33,6 +33,9 @@ jobs:
with:
enable_ccache: false
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Update libXRPL version requirement
run: |
sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.conan_ref }}'|g" conanfile.py
@@ -95,14 +98,12 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Create an issue
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
labels: "compatibility,bug"
title: "Proposed libXRPL check failed"
body: >
Clio build or tests failed against `libXRPL ${{ github.event.client_payload.conan_ref }}`.
PR: ${{ github.event.client_payload.pr_url }}
Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
labels: "compatibility,bug"
assignees: "godexsoft,kuznetsss,mathbunnyru"

View File

@@ -7,4 +7,4 @@ on:
jobs:
check_title:
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@a5d8dd35be543365e90a11358447130c8763871d
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81

View File

@@ -1,16 +1,22 @@
name: Clang-tidy check
name: Run clang-tidy on files
on:
push:
branches: [develop]
schedule:
- cron: "0 9 * * 1-5"
workflow_dispatch:
pull_request:
branches: [develop]
paths:
- .github/workflows/clang-tidy.yml
- CMakeLists.txt
- conanfile.py
- conan.lock
- "cmake/**"
- "src/**"
- "tests/**"
- "benchmarks/**"
- .clang_tidy
concurrency:
@@ -19,19 +25,34 @@ concurrency:
cancel-in-progress: true
env:
BUILD_DIR: build
BUILD_TYPE: Debug # Debug so that ASSERTS and such participate in clang-tidy check
OUTPUT_FILE: clang-tidy-output.txt
DIFF_FILE: clang-tidy-git-diff.txt
ISSUE_FILE: clang-tidy-issue.md
CONAN_PROFILE: clang
LLVM_TOOLS_VERSION: 20
LLVM_TOOLS_VERSION: 21
defaults:
run:
shell: bash
jobs:
clang_tidy:
if: github.event_name != 'push' || contains(github.event.head_commit.message, 'clang-tidy auto fixes')
determine-files:
if: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@224f3c48d3014d082a1129237b8291ff0b0a331f
run-clang-tidy:
name: Run clang tidy
needs: [determine-files]
if: ${{ always() && !cancelled() && (github.event_name != 'pull_request' || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
image: ghcr.io/xrplf/clio-ci:f174b47f4909ae41b80406d836ab52adc39eacc6
permissions:
contents: write
@@ -40,37 +61,54 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
enable_ccache: false
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Run conan
uses: ./.github/actions/conan
with:
build_dir: ${{ env.BUILD_DIR }}
conan_profile: ${{ env.CONAN_PROFILE }}
build_type: ${{ env.BUILD_TYPE }}
- name: Run CMake
uses: ./.github/actions/cmake
with:
build_dir: ${{ env.BUILD_DIR }}
conan_profile: ${{ env.CONAN_PROFILE }}
build_type: ${{ env.BUILD_TYPE }}
- name: Get number of processors
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
- name: Run clang-tidy (several times)
- name: Run clang tidy
continue-on-error: true
id: clang_tidy
id: run_clang_tidy
env:
TARGETS: ${{ (needs.determine-files.outputs.clang_tidy_config_changed != 'true' && github.event_name == 'pull_request') && needs.determine-files.outputs.cpp_changed_files || 'benchmarks src tests' }}
run: |
# We run clang-tidy several times, because some fixes may enable new fixes in subsequent runs.
CLANG_TIDY_COMMAND="run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j ${{ steps.nproc.outputs.nproc }} -fix -quiet"
${CLANG_TIDY_COMMAND} ||
${CLANG_TIDY_COMMAND} ||
${CLANG_TIDY_COMMAND}
set -o pipefail
run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
- name: Print errors
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
sed '/error\||/!d' "${OUTPUT_FILE}"
- name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
path: ${{ env.OUTPUT_FILE }}
archive: false
retention-days: 30
- name: Check for changes
id: files_changed
@@ -78,24 +116,76 @@ jobs:
run: |
git diff --exit-code
- name: Fix local includes and clang-format style
- name: Fix style
if: ${{ steps.files_changed.outcome != 'success' }}
run: |
pre-commit run --all-files fix-local-includes || true
pre-commit run --all-files clang-format || true
pre-commit run --all-files || true
- name: Create an issue
if: ${{ (steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success') && github.event_name != 'pull_request' }}
id: create_issue
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
- name: Generate git diff
if: ${{ steps.files_changed.outcome != 'success' }}
run: |
git diff | tee "${DIFF_FILE}"
- name: Upload clang-tidy diff output
if: ${{ github.event.repository.visibility == 'public' && steps.files_changed.outcome != 'success' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
title: "Clang-tidy found bugs in code 🐛"
body: >
Clang-tidy found issues in the code:
path: ${{ env.DIFF_FILE }}
archive: false
retention-days: 30
List of the issues found: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
- name: Write issue header
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >"${ISSUE_FILE}" <<EOF
## Clang-tidy Check Failed
### Clang-tidy Output:
\`\`\`
EOF
- name: Append clang-tidy output to issue body (filter for errors and warnings)
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
if [ -f "${OUTPUT_FILE}" ]; then
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >filtered-output.txt || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp "${OUTPUT_FILE}" filtered-output.txt
fi
# Truncate if too large
head -c 60000 filtered-output.txt >>"${ISSUE_FILE}"
if [ "$(wc -c <filtered-output.txt)" -gt 60000 ]; then
echo "" >>"${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >>"${ISSUE_FILE}"
fi
rm filtered-output.txt
else
echo "No output file found" >>"${ISSUE_FILE}"
fi
- name: Append issue footer
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >>"${ISSUE_FILE}" <<EOF
\`\`\`
---
*This issue was automatically created by the clang-tidy workflow.*
EOF
- name: Create issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Clang-tidy check failed"
body_file: ${{ env.ISSUE_FILE }}
labels: "bug"
assignees: "godexsoft,mathbunnyru"
- uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
@@ -118,9 +208,14 @@ jobs:
branch-suffix: timestamp
delete-branch: true
title: "style: clang-tidy auto fixes"
body: "Fixes #${{ steps.create_issue.outputs.created_issue_id }}. Please review and commit clang-tidy fixes."
reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
body: >
Fixes #${{ steps.create_issue.outputs.issue_number }}.
Please review and commit clang-tidy fixes.
reviewers: "godexsoft,kuznetsss,mathbunnyru"
- name: Fail the job
if: ${{ steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success' }}
run: exit 1
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
echo "Clang-tidy check failed!"
exit 1

View File

@@ -31,6 +31,9 @@ jobs:
with:
enable_ccache: false
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Create build directory
run: mkdir build_docs
@@ -43,6 +46,7 @@ jobs:
run: cmake --build . --target docs
- name: Setup Pages
if: ${{ github.repository == 'XRPLF/clio' && github.event_name == 'push' }}
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Upload artifact
@@ -52,6 +56,7 @@ jobs:
name: docs-develop
deploy:
if: ${{ github.repository == 'XRPLF/clio' && github.event_name == 'push' }}
needs: build
permissions:
pages: write

View File

@@ -37,7 +37,7 @@ jobs:
- name: Get current date
id: get_date
run: |
echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
echo "date=$(date +'%Y%m%d')" >>$GITHUB_OUTPUT
build-and-test:
name: Build and Test
@@ -157,7 +157,7 @@ jobs:
type=raw,value=${{ github.sha }}
artifact_name: clio_server_Linux_Release_gcc
strip_binary: true
publish_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
create_issue_on_failure:
needs: [build-and-test, nightly_release, build_and_publish_docker_image]
@@ -172,12 +172,9 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Create an issue
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Nightly release failed 🌙"
body: >
Nightly release failed:
Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
body: ""
labels: "bug"
assignees: "godexsoft,kuznetsss,mathbunnyru"

View File

@@ -12,11 +12,11 @@ on:
jobs:
auto-update:
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@a249154199805d6809359fe99fa8ba09dd804e3d
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@5e942d61bf32f7557a7c159cfac4712a687b3e3a
with:
sign_commit: true
committer: "Clio CI <skuznetsov@ripple.com>"
reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
reviewers: "godexsoft,kuznetsss,mathbunnyru"
secrets:
GPG_PRIVATE_KEY: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}

View File

@@ -8,7 +8,7 @@ on:
jobs:
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@9307df762265e15c745ddcdb38a581c989f7f349
uses: XRPLF/actions/.github/workflows/pre-commit.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:14342e087ceb8b593027198bf9ef06a43833c696" }'

View File

@@ -99,6 +99,9 @@ jobs:
with:
enable_ccache: ${{ inputs.download_ccache }}
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Setup conan on macOS
if: ${{ runner.os == 'macOS' }}
run: ./.github/scripts/conan/init.sh
@@ -146,7 +149,7 @@ jobs:
if: ${{ inputs.analyze_build_time }}
run: |
ClangBuildAnalyzer --all build/ build_time_report.bin
ClangBuildAnalyzer --analyze build_time_report.bin > build_time_report.txt
ClangBuildAnalyzer --analyze build_time_report.bin >build_time_report.txt
cat build_time_report.txt
- name: Upload build time analyze report
@@ -224,13 +227,13 @@ jobs:
set -e
EXPECTED_VERSION="clio-${INPUT_VERSION}"
if [[ "${BUILD_TYPE}" == "Debug" ]]; then
EXPECTED_VERSION="${EXPECTED_VERSION}+DEBUG"
EXPECTED_VERSION="${EXPECTED_VERSION}+DEBUG"
fi
actual_version=$(./build/clio_server --version | head -n 1)
if [[ "${actual_version}" != "${EXPECTED_VERSION}" ]]; then
echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
exit 1
echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
exit 1
fi
# `codecov/codecov-action` will rerun `gcov` if it's available and build directory is present

View File

@@ -81,9 +81,9 @@ jobs:
env:
RELEASE_HEADER: ${{ inputs.header }}
run: |
echo "# Release notes" > "${RUNNER_TEMP}/release_notes.md"
echo "" >> "${RUNNER_TEMP}/release_notes.md"
printf '%s\n' "${RELEASE_HEADER}" >> "${RUNNER_TEMP}/release_notes.md"
echo "# Release notes" >"${RUNNER_TEMP}/release_notes.md"
echo "" >>"${RUNNER_TEMP}/release_notes.md"
printf '%s\n' "${RELEASE_HEADER}" >>"${RUNNER_TEMP}/release_notes.md"
- name: Generate changelog
if: ${{ inputs.generate_changelog }}
@@ -91,7 +91,7 @@ jobs:
LAST_TAG="$(gh release view --json tagName -q .tagName --repo XRPLF/clio)"
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|-rc" >> "${RUNNER_TEMP}/release_notes.md"
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc" >>"${RUNNER_TEMP}/release_notes.md"
- name: Upload release notes
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -106,10 +106,10 @@ jobs:
run: |
RELEASES_TO_DELETE=$(gh release list --limit 50 --repo "${GH_REPO}" | grep -E "${DELETE_PATTERN}" | awk -F'\t' '{print $3}' || true)
if [ -n "$RELEASES_TO_DELETE" ]; then
for RELEASE in $RELEASES_TO_DELETE; do
echo "Deleting release: $RELEASE"
gh release delete "$RELEASE" --repo "${GH_REPO}" --yes --cleanup-tag
done
for RELEASE in $RELEASES_TO_DELETE; do
echo "Deleting release: $RELEASE"
gh release delete "$RELEASE" --repo "${GH_REPO}" --yes --cleanup-tag
done
fi
- name: Publish release
@@ -121,9 +121,9 @@ jobs:
DRAFT_OPTION: ${{ inputs.draft && '--draft' || '' }}
run: |
gh release create "${RELEASE_VERSION}" \
${PRERELEASE_OPTION} \
--title "${RELEASE_TITLE}" \
--target "${GITHUB_SHA}" \
${DRAFT_OPTION} \
--notes-file "${RUNNER_TEMP}/release_notes.md" \
./release_artifacts/clio_*
${PRERELEASE_OPTION} \
--title "${RELEASE_TITLE}" \
--target "${GITHUB_SHA}" \
${DRAFT_OPTION} \
--notes-file "${RUNNER_TEMP}/release_notes.md" \
./release_artifacts/clio_*

View File

@@ -68,16 +68,12 @@ jobs:
- name: Create an issue
if: ${{ steps.run_clio_tests.outcome == 'failure' && endsWith(inputs.conan_profile, 'san') }}
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
labels: "bug"
title: "[${{ inputs.conan_profile }}] reported issues"
body: >
Clio tests failed one or more sanitizer checks when built with `${{ inputs.conan_profile }}`.
Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
body: "Clio tests failed one or more sanitizer checks when built with `${{ inputs.conan_profile }}`."
labels: "bug"
assignees: "godexsoft,kuznetsss,mathbunnyru"
- name: Fail the job if clio_tests failed
if: ${{ steps.run_clio_tests.outcome == 'failure' }}
@@ -116,22 +112,22 @@ jobs:
timeout-minutes: 1
run: |
docker run \
--detach \
--name scylladb \
--health-cmd "cqlsh -e 'describe cluster'" \
--health-interval 10s \
--health-timeout 5s \
--health-retries 5 \
--publish 9042:9042 \
--memory 16G \
scylladb/scylla
--detach \
--name scylladb \
--health-cmd "cqlsh -e 'describe cluster'" \
--health-interval 10s \
--health-timeout 5s \
--health-retries 5 \
--publish 9042:9042 \
--memory 16G \
scylladb/scylla
- name: Wait for scylladb container to be healthy (macOS)
if: ${{ runner.os == 'macOS' }}
timeout-minutes: 1
run: |
until [ "$(docker inspect -f '{{.State.Health.Status}}' scylladb)" == "healthy" ]; do
sleep 1
sleep 1
done
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1

View File

@@ -27,8 +27,8 @@ jobs:
path: build
- name: Upload coverage report
if: ${{ hashFiles('build/coverage_report.xml') != '' }}
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
if: ${{ github.repository == 'XRPLF/clio' && hashFiles('build/coverage_report.xml') != '' }}
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
files: build/coverage_report.xml
fail_ci_if_error: true

View File

@@ -14,7 +14,6 @@ on:
- ".github/actions/**"
- "!.github/actions/build-docker-image/**"
- "!.github/actions/create-issue/**"
- CMakeLists.txt
- conanfile.py

View File

@@ -48,7 +48,7 @@ jobs:
- name: Set GHCR_REPO
id: set-ghcr-repo
run: |
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> ${GITHUB_OUTPUT}
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >>${GITHUB_OUTPUT}
gcc-amd64:
name: Build and push GCC docker image (amd64)
@@ -74,7 +74,7 @@ jobs:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/compilers/gcc
tags: |
type=raw,value=amd64-latest
@@ -112,7 +112,7 @@ jobs:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/compilers/gcc
tags: |
type=raw,value=arm64-latest
@@ -141,19 +141,19 @@ jobs:
files: "docker/compilers/gcc/**"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PW }}
@@ -162,19 +162,19 @@ jobs:
if: ${{ github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
run: |
push_image() {
image=$1
image=$1
docker buildx imagetools create \
-t $image:latest \
-t $image:${{ env.GCC_MAJOR_VERSION }} \
-t $image:${{ env.GCC_VERSION }} \
-t $image:${{ github.sha }} \
$image:arm64-latest \
$image:amd64-latest
docker buildx imagetools create \
-t $image:latest \
-t $image:${{ env.GCC_MAJOR_VERSION }} \
-t $image:${{ env.GCC_VERSION }} \
-t $image:${{ github.sha }} \
$image:arm64-latest \
$image:amd64-latest
}
push_image ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
if [[ ${{ github.repository_owner }} == 'XRPLF' ]]; then
push_image rippleci/clio_clang
if [[ ${{ github.repository }} == 'XRPLF/clio' ]]; then
push_image rippleci/clio_clang
fi
clang:
@@ -201,7 +201,7 @@ jobs:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-clang
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/compilers/clang
tags: |
type=raw,value=latest
@@ -234,7 +234,7 @@ jobs:
with:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/tools
tags: |
type=raw,value=amd64-latest
@@ -265,7 +265,7 @@ jobs:
with:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/tools
tags: |
type=raw,value=arm64-latest
@@ -290,11 +290,11 @@ jobs:
files: "docker/tools/**"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -305,10 +305,10 @@ jobs:
run: |
image=${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
docker buildx imagetools create \
-t $image:latest \
-t $image:${{ github.sha }} \
$image:arm64-latest \
$image:amd64-latest
-t $image:latest \
-t $image:${{ github.sha }} \
$image:arm64-latest \
$image:amd64-latest
pre-commit:
name: Build and push pre-commit docker image
@@ -323,7 +323,7 @@ jobs:
with:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-pre-commit
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/pre-commit
tags: |
type=raw,value=latest
@@ -348,7 +348,7 @@ jobs:
images: |
${{ needs.repo.outputs.GHCR_REPO }}/clio-ci
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_ci' || '' }}
push_image: ${{ github.event_name != 'pull_request' }}
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
directory: docker/ci
tags: |
type=raw,value=latest

View File

@@ -56,7 +56,7 @@ jobs:
- name: Calculate conan matrix
id: set-matrix
run: .github/scripts/conan/generate_matrix.py >> "${GITHUB_OUTPUT}"
run: .github/scripts/conan/generate_matrix.py >>"${GITHUB_OUTPUT}"
upload-conan-deps:
name: Build ${{ matrix.compiler }}${{ matrix.sanitizer_ext }} ${{ matrix.build_type }}
@@ -82,6 +82,9 @@ jobs:
with:
enable_ccache: false
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Setup conan on macOS
if: ${{ runner.os == 'macOS' }}
run: ./.github/scripts/conan/init.sh
@@ -98,12 +101,12 @@ jobs:
force_conan_source_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
build_type: ${{ matrix.build_type }}
- name: Login to Conan
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
- name: Log into Conan remote
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} xrplf ${{ secrets.CONAN_USERNAME }}
- name: Upload Conan packages
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
env:
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
run: conan upload "*" -r=xrplf --confirm ${FORCE_OPTION}

View File

@@ -29,7 +29,7 @@ repos:
# Autoformat: YAML, JSON, Markdown, etc.
- repo: https://github.com/rbubley/mirrors-prettier
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3
hooks:
- id: prettier
@@ -40,7 +40,7 @@ repos:
exclude: LICENSE.md
- repo: https://github.com/hadolint/hadolint
rev: 4e697ba704fd23b2409b947a319c19c3ee54d24f # frozen: v2.14.0
rev: 57e1618d78fd469a92c1e584e8c9313024656623 # frozen: v2.14.0
hooks:
- id: hadolint-docker
# hadolint-docker is a special hook that runs hadolint in a Docker container
@@ -59,15 +59,15 @@ repos:
]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: fa505ab9c3e0fedafe1709fd7ac2b5f8996c670d # frozen: 26.3.1
rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
hooks:
- id: black
- repo: https://github.com/scop/pre-commit-shfmt
rev: e26a818fd47b4f33cefa99035d1265b0849f4b47 # frozen: v3.13.0-1
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
hooks:
- id: shfmt
args: ["-i", "4", "--write"]
args: [--write, --indent=4, --case-indent=true]
# Running some C++ hooks before clang-format
# to ensure that the style is consistent.
@@ -94,14 +94,14 @@ repos:
language: script
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: 07a0f7667439f60724899f6ae288e4a4f572e0e1 # frozen: v22.1.2
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
hooks:
- id: clang-format
args: [--style=file]
types: [c++]
- repo: https://github.com/BlankSpruce/gersemi
rev: 79ddf2c9f3a84d766fce4e39fb2f83eac62b34f7 # frozen: 0.26.1
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: e98930bdc210d3387007f9252d8c1694ea7e410f # frozen: 0.27.7
hooks:
- id: gersemi

View File

@@ -26,7 +26,7 @@ using namespace util::config;
namespace {
auto const kCONFIG = ClioConfigDefinition{
auto const kConfig = ClioConfigDefinition{
{"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"log.channels.[].channel", Array{ConfigValue{ConfigType::String}}},
@@ -48,10 +48,10 @@ auto const kCONFIG = ClioConfigDefinition{
void
init()
{
static std::once_flag kONCE;
std::call_once(kONCE, [] {
PrometheusService::init(kCONFIG);
(void)util::LogService::init(kCONFIG);
static std::once_flag kOnce;
std::call_once(kOnce, [] {
PrometheusService::init(kConfig);
(void)util::LogService::init(kConfig);
});
}

View File

@@ -169,11 +169,11 @@ public:
static auto
generateData()
{
constexpr auto kTOTAL = 10'000;
constexpr auto kTotal = 10'000;
std::vector<uint64_t> data;
data.reserve(kTOTAL);
data.reserve(kTotal);
util::MTRandomGenerator randomGenerator;
for (auto i = 0; i < kTOTAL; ++i)
for (auto i = 0; i < kTotal; ++i)
data.push_back(randomGenerator.uniform(1, 100'000'000));
return data;

View File

@@ -21,7 +21,7 @@
using namespace util;
static constexpr auto kLOG_FORMAT = "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v";
static constexpr auto kLogFormat = "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v";
struct BenchmarkLoggingInitializer {
[[nodiscard]] static std::shared_ptr<spdlog::sinks::sink>
@@ -32,7 +32,7 @@ struct BenchmarkLoggingInitializer {
.logDir = logDir,
.rotation = LogService::RotationParams{.sizeMB = sizeMB, .maxFiles = maxFiles},
},
kLOG_FORMAT
kLogFormat
);
}
@@ -71,9 +71,9 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
state.PauseTiming();
std::filesystem::create_directories(logDir);
static constexpr size_t kQUEUE_SIZE = 8192;
static constexpr size_t kTHREAD_COUNT = 1;
spdlog::init_thread_pool(kQUEUE_SIZE, kTHREAD_COUNT);
static constexpr size_t kQueueSize = 8192;
static constexpr size_t kThreadCount = 1;
spdlog::init_thread_pool(kQueueSize, kThreadCount);
auto fileSink = BenchmarkLoggingInitializer::createFileSink(logDir, 5, 25);

View File

@@ -10,36 +10,36 @@ CLIO_BIN="$CLIO_PREFIX/bin/${CLIO_EXECUTABLE}"
CLIO_CONFIG="$CLIO_PREFIX/etc/config.json"
case "$1" in
configure)
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
# Users who should not have a home directory should have their home directory set to /nonexistent
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
useradd \
--system \
--home-dir /nonexistent \
--no-create-home \
--shell /usr/sbin/nologin \
--comment "system user for ${CLIO_EXECUTABLE}" \
--user-group \
${USER_NAME}
fi
configure)
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
# Users who should not have a home directory should have their home directory set to /nonexistent
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
useradd \
--system \
--home-dir /nonexistent \
--no-create-home \
--shell /usr/sbin/nologin \
--comment "system user for ${CLIO_EXECUTABLE}" \
--user-group \
${USER_NAME}
fi
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
if [ -f "$CLIO_CONFIG" ]; then
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
fi
if [ -f "$CLIO_CONFIG" ]; then
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
fi
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
;;
abort-upgrade | abort-remove | abort-deconfigure) ;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
;;
abort-upgrade | abort-remove | abort-deconfigure) ;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

View File

@@ -1,17 +1,17 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"xrpl/3.1.0#3d408ab8c8020014fa7dd52bc7cc7ea8%1769706825.165",
"xrpl/3.1.3#eabc6838b4553671bdde4b3aa1f8e3e6%1778495466.414",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
"spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1768312128.781",
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
"rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456",
"openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
"minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592",
@@ -25,18 +25,18 @@
"doctest/2.4.11#a4211dfc329a16ba9f280f9574025659%1756234220.819",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"cassandra-cpp-driver/2.17.0#bd3934138689482102c265d01288a316%1764175359.611",
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1%1764175359.61",
"benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
"abseil/20230802.1#90ba607d4ee8fb5fb157c3db540671fc%1764175359.429"
],
"build_requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456",
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937",
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
"b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355"
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"cmake/3.31.11#f325c933f618a1fcebc1e1c0babfd1ba%1774439246.719",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447"
],
"python_requires": [],
"overrides": {
@@ -51,10 +51,10 @@
"lz4/1.9.4": [
"lz4/1.10.0"
],
"boost/1.90.0": [
"boost/[>=1.83.0 <1.91.0]": [
"boost/1.83.0"
],
"sqlite3/3.44.2": [
"sqlite3/[>=3.44 <4]": [
"sqlite3/3.49.1"
]
},

View File

@@ -19,7 +19,7 @@ class ClioConan(ConanFile):
"openssl/1.1.1w",
"protobuf/3.21.12",
"spdlog/1.17.0",
"xrpl/3.1.0",
"xrpl/3.1.3",
"zlib/1.3.1",
]

View File

@@ -61,7 +61,7 @@ RUN pip install -q --no-cache-dir \
pre-commit
# Install LLVM tools
ARG LLVM_TOOLS_VERSION=20
ARG LLVM_TOOLS_VERSION=21
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
&& wget --progress=dot:giga -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -

View File

@@ -14,6 +14,7 @@ The image is based on Ubuntu 20.04 and contains:
- GDB 17.1
- gh 2.83.2
- git-cliff 2.11.0
- LLVM Tools 21
- mold 2.40.4
- Ninja 1.13.2
- Python 3.8

View File

@@ -41,26 +41,26 @@ EOF
}
case $1 in
-h | --help)
print_help
;;
-h | --help)
print_help
;;
-t | --terminal)
open_terminal
;;
-t | --terminal)
open_terminal
;;
-s | --stop)
stop_container
;;
-s | --stop)
stop_container
;;
-*)
echo "Unknown option: $1"
print_help
;;
-*)
echo "Unknown option: $1"
print_help
;;
*)
run "$@"
;;
*)
run "$@"
;;
esac
popd >/dev/null

View File

@@ -1,51 +1,56 @@
#!/bin/bash
# git for-each-ref refs/tags # see which tags are annotated and which are lightweight. Annotated tags are "tag" objects.
# # Set these so your commits and tags are always signed
# git config commit.gpgsign true
# git config tag.gpgsign true
# Annotated tags have object type "tag"; lightweight tags have type "commit".
# To inspect tags: git for-each-ref refs/tags
#
# To always sign commits and tags, configure:
# git config --global commit.gpgsign true
# git config --global tag.gpgsign true
verify_commit_signed() {
if git verify-commit HEAD &>/dev/null; then
:
# echo "HEAD commit seems signed..."
echo "HEAD commit is signed."
else
echo "HEAD commit isn't signed!"
echo "HEAD commit is not signed!"
exit 1
fi
}
verify_tag() {
if git describe --exact-match --tags HEAD &>/dev/null; then
: # You might be ok to push
# echo "Tag is annotated."
return 0
verify_tag_annotated() {
local version="$1"
# git cat-file -t returns "tag" for annotated tags, "commit" for lightweight.
if [[ "$(git cat-file -t "$version")" == "tag" ]]; then
echo "Tag '$version' is annotated."
else
echo "Tag for [$version] not an annotated tag."
echo "Tag '$version' is not annotated!"
echo "Re-create it with: git tag -a -s -m \"$version\" \"$version\""
exit 1
fi
}
verify_tag_signed() {
local version="$1"
if git verify-tag "$version" &>/dev/null; then
: # ok, I guess we'll let you push
# echo "Tag appears signed"
return 0
echo "Tag '$version' is signed."
else
echo "$version tag isn't signed"
echo "Sign it with [git tag -ams\"$version\" $version]"
echo "Tag '$version' is not signed!"
echo "Sign it with: git tag -a -s -m \"$version\" \"$version\""
exit 1
fi
}
# Check some things if we're pushing a branch called "release/"
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep ^refs\/heads\/release\/ &>/dev/null; then
version=$(git tag --points-at HEAD)
echo "Looks like you're trying to push a $version release..."
echo "Making sure you've signed and tagged it."
if verify_commit_signed && verify_tag && verify_tag_signed; then
: # Ok, I guess you can push
else
# Enforce signing and annotated tags when pushing to a release branch.
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep -q "^refs/heads/release/"; then
# git describe --exact-match guarantees a single tag; git tag --points-at HEAD
# can return multiple newline-separated values, which breaks downstream commands.
version=$(git describe --exact-match --tags HEAD 2>/dev/null)
if [[ -z "$version" ]]; then
echo "No tag found at HEAD — cannot push an untagged release commit!"
exit 1
fi
echo "Looks like you're trying to push a '$version' release..."
echo "Verifying the commit is signed and the tag is annotated and signed."
verify_commit_signed
verify_tag_annotated "$version"
verify_tag_signed "$version"
fi

View File

@@ -28,7 +28,7 @@ CliArgs::parse(int argc, char const* argv[])
description.add_options()
("help,h", "Print help message and exit")
("version,v", "Print version and exit")
("conf,c", po::value<std::string>()->default_value(kDEFAULT_CONFIG_PATH), "Configuration file")
("conf,c", po::value<std::string>()->default_value(kDefaultConfigPath), "Configuration file")
("ng-web-server,w", "Use ng-web-server")
("migrate", po::value<std::string>(), "Start migration helper")
("verify", "Checks the validity of config values")

View File

@@ -16,7 +16,7 @@ public:
/**
* @brief Default configuration path.
*/
static constexpr char kDEFAULT_CONFIG_PATH[] = "/etc/opt/clio/config.json";
static constexpr char kDefaultConfigPath[] = "/etc/opt/clio/config.json";
/**
* @brief An action parsed from the command line.

View File

@@ -28,7 +28,7 @@ parseConfig(std::string_view configPath)
}
auto const errors = getClioConfig().parse(json.value());
if (errors.has_value()) {
for (auto const& err : errors.value()) {
for (auto const& err : *errors) {
std::cerr << "Issues found in provided config '" << configPath << "':\n";
std::cerr << err.error << std::endl;
}

View File

@@ -83,7 +83,7 @@ MetricsHandler::operator()(
ASSERT(onTaskComplete.has_value(), "Coroutine group can't be full");
bool const postSuccessful = workQueue_.get().postCoro(
[this, &request, &response, &onTaskComplete = onTaskComplete.value(), &connectionMetadata](
[this, &request, &response, &onTaskComplete = *onTaskComplete, &connectionMetadata]( // NOLINT(bugprone-unchecked-optional-access)
boost::asio::yield_context
) mutable {
auto const maybeHttpRequest = request.asHttpRequest();
@@ -94,7 +94,7 @@ MetricsHandler::operator()(
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
);
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
response = web::ng::Response{std::move(maybeResponse).value(), request};
response = web::ng::Response{*std::move(maybeResponse), request};
// notify the coroutine group that the foreign task is done
onTaskComplete();
},
@@ -114,7 +114,7 @@ MetricsHandler::operator()(
coroutineGroup.asyncWait(yield);
ASSERT(response.has_value(), "Woke up coroutine without setting response");
return std::move(response).value();
return *std::move(response); // NOLINT(bugprone-unchecked-optional-access)
}
web::ng::Response
@@ -125,7 +125,7 @@ HealthCheckHandler::operator()(
boost::asio::yield_context
)
{
static constexpr auto kHEALTH_CHECK_HTML = R"html(
static constexpr auto kHealthCheckHtml = R"html(
<!DOCTYPE html>
<html>
<head><title>Test page for Clio</title></head>
@@ -133,7 +133,7 @@ HealthCheckHandler::operator()(
</html>
)html";
return web::ng::Response{boost::beast::http::status::ok, kHEALTH_CHECK_HTML, request};
return web::ng::Response{boost::beast::http::status::ok, kHealthCheckHtml, request};
}
web::ng::Response
@@ -144,7 +144,7 @@ CacheStateHandler::operator()(
boost::asio::yield_context
)
{
static constexpr auto kCACHE_CHECK_LOADED_HTML = R"html(
static constexpr auto kCacheCheckLoadedHtml = R"html(
<!DOCTYPE html>
<html>
<head><title>Cache state</title></head>
@@ -152,7 +152,7 @@ CacheStateHandler::operator()(
</html>
)html";
static constexpr auto kCACHE_CHECK_NOT_LOADED_HTML = R"html(
static constexpr auto kCacheCheckNotLoadedHtml = R"html(
<!DOCTYPE html>
<html>
<head><title>Cache state</title></head>
@@ -161,10 +161,10 @@ CacheStateHandler::operator()(
)html";
if (cache_.get().isFull())
return web::ng::Response{boost::beast::http::status::ok, kCACHE_CHECK_LOADED_HTML, request};
return web::ng::Response{boost::beast::http::status::ok, kCacheCheckLoadedHtml, request};
return web::ng::Response{
boost::beast::http::status::service_unavailable, kCACHE_CHECK_NOT_LOADED_HTML, request
boost::beast::http::status::service_unavailable, kCacheCheckNotLoadedHtml, request
};
}

View File

@@ -22,12 +22,11 @@ namespace cluster {
namespace {
struct JsonFields {
static constexpr std::string_view const kUPDATE_TIME = "update_time";
static constexpr std::string_view const kDB_ROLE = "db_role";
static constexpr std::string_view const kETL_STARTED = "etl_started";
static constexpr std::string_view const kCACHE_IS_FULL = "cache_is_full";
static constexpr std::string_view const kCACHE_IS_CURRENTLY_LOADING =
"cache_is_currently_loading";
static constexpr std::string_view const kUpdateTime = "update_time";
static constexpr std::string_view const kDbRole = "db_role";
static constexpr std::string_view const kEtlStarted = "etl_started";
static constexpr std::string_view const kCacheIsFull = "cache_is_full";
static constexpr std::string_view const kCacheIsCurrentlyLoading = "cache_is_currently_loading";
};
} // namespace
@@ -67,11 +66,11 @@ void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, ClioNode const& node)
{
jv = {
{JsonFields::kUPDATE_TIME, util::systemTpToUtcStr(node.updateTime, ClioNode::kTIME_FORMAT)},
{JsonFields::kDB_ROLE, static_cast<int64_t>(node.dbRole)},
{JsonFields::kETL_STARTED, node.etlStarted},
{JsonFields::kCACHE_IS_FULL, node.cacheIsFull},
{JsonFields::kCACHE_IS_CURRENTLY_LOADING, node.cacheIsCurrentlyLoading}
{JsonFields::kUpdateTime, util::systemTpToUtcStr(node.updateTime, ClioNode::kTimeFormat)},
{JsonFields::kDbRole, static_cast<int64_t>(node.dbRole)},
{JsonFields::kEtlStarted, node.etlStarted},
{JsonFields::kCacheIsFull, node.cacheIsFull},
{JsonFields::kCacheIsCurrentlyLoading, node.cacheIsCurrentlyLoading}
};
}
@@ -79,16 +78,16 @@ ClioNode
tag_invoke(boost::json::value_to_tag<ClioNode>, boost::json::value const& jv)
{
auto const& obj = jv.as_object();
auto const& updateTimeStr = obj.at(JsonFields::kUPDATE_TIME).as_string();
auto const& updateTimeStr = obj.at(JsonFields::kUpdateTime).as_string();
auto const updateTime =
util::systemTpFromUtcStr(std::string(updateTimeStr), ClioNode::kTIME_FORMAT);
util::systemTpFromUtcStr(std::string(updateTimeStr), ClioNode::kTimeFormat);
if (!updateTime.has_value()) {
throw std::runtime_error("Failed to parse update time");
}
// Each field has a default value for backward compatibility
auto dbRole = ClioNode::DbRole::Fallback;
if (auto const* v = obj.if_contains(JsonFields::kDB_ROLE)) {
if (auto const* v = obj.if_contains(JsonFields::kDbRole)) {
auto const dbRoleValue = v->as_int64();
if (dbRoleValue > static_cast<int64_t>(ClioNode::DbRole::Max))
throw std::runtime_error("Invalid db_role value");
@@ -96,19 +95,18 @@ tag_invoke(boost::json::value_to_tag<ClioNode>, boost::json::value const& jv)
}
auto const etlStarted =
obj.contains(JsonFields::kETL_STARTED) ? obj.at(JsonFields::kETL_STARTED).as_bool() : true;
auto const cacheIsFull = obj.contains(JsonFields::kCACHE_IS_FULL)
? obj.at(JsonFields::kCACHE_IS_FULL).as_bool()
: true;
auto const cacheIsCurrentlyLoading = obj.contains(JsonFields::kCACHE_IS_CURRENTLY_LOADING)
? obj.at(JsonFields::kCACHE_IS_CURRENTLY_LOADING).as_bool()
obj.contains(JsonFields::kEtlStarted) ? obj.at(JsonFields::kEtlStarted).as_bool() : true;
auto const cacheIsFull =
obj.contains(JsonFields::kCacheIsFull) ? obj.at(JsonFields::kCacheIsFull).as_bool() : true;
auto const cacheIsCurrentlyLoading = obj.contains(JsonFields::kCacheIsCurrentlyLoading)
? obj.at(JsonFields::kCacheIsCurrentlyLoading).as_bool()
: false;
return ClioNode{
// Json data doesn't contain uuid so leaving it empty here. It will be filled outside of
// this parsing
.uuid = std::make_shared<boost::uuids::uuid>(),
.updateTime = updateTime.value(),
.updateTime = *updateTime,
.dbRole = dbRole,
.etlStarted = etlStarted,
.cacheIsFull = cacheIsFull,

View File

@@ -19,7 +19,7 @@ struct ClioNode {
/**
* @brief The format of the time to store in the database.
*/
static constexpr char const* kTIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ";
static constexpr char const* kTimeFormat = "%Y-%m-%dT%H:%M:%SZ";
/**
* @brief Database role of a node in the cluster.

View File

@@ -36,8 +36,8 @@ class ClusterCommunicationService : public ClusterCommunicationServiceTag {
CacheLoaderDecider cacheLoaderDecider_;
public:
static constexpr std::chrono::milliseconds kDEFAULT_READ_INTERVAL{1000};
static constexpr std::chrono::milliseconds kDEFAULT_WRITE_INTERVAL{1000};
static constexpr std::chrono::milliseconds kDefaultReadInterval{1000};
static constexpr std::chrono::milliseconds kDefaultWriteInterval{1000};
/**
* @brief Construct a new Cluster Communication Service object.
@@ -52,8 +52,8 @@ public:
std::shared_ptr<data::BackendInterface> backend,
std::unique_ptr<etl::WriterStateInterface> writerState,
std::unique_ptr<data::LedgerCacheLoadingStateInterface> cacheLoadingState,
std::chrono::steady_clock::duration readInterval = kDEFAULT_READ_INTERVAL,
std::chrono::steady_clock::duration writeInterval = kDEFAULT_WRITE_INTERVAL
std::chrono::steady_clock::duration readInterval = kDefaultReadInterval,
std::chrono::steady_clock::duration writeInterval = kDefaultWriteInterval
);
~ClusterCommunicationService() override;

View File

@@ -63,7 +63,7 @@ namespace cluster {
*/
class WriterDecider {
public:
static constexpr std::chrono::steady_clock::duration kRECOVERY_TIME = std::chrono::hours{1};
static constexpr std::chrono::steady_clock::duration kRecoveryTime = std::chrono::hours{1};
private:
/** @brief Thread pool for spawning asynchronous tasks */
@@ -90,12 +90,12 @@ public:
* @param ctx Thread pool for executing asynchronous operations
* @param writerState Writer state interface for controlling write operations
* @param recoveryTime How long to wait in Fallback before attempting recovery
* (defaults to `kRECOVERY_TIME`; pass a short duration in tests)
* (defaults to `kRecoveryTime`; pass a short duration in tests)
*/
WriterDecider(
boost::asio::thread_pool& ctx,
std::unique_ptr<etl::WriterStateInterface> writerState,
std::chrono::steady_clock::duration recoveryTime = kRECOVERY_TIME
std::chrono::steady_clock::duration recoveryTime = kRecoveryTime
);
/**

View File

@@ -33,8 +33,8 @@ namespace {
std::unordered_set<std::string>&
supportedAmendments()
{
static std::unordered_set<std::string> kAMENDMENTS = {};
return kAMENDMENTS;
static std::unordered_set<std::string> kAmendments = {};
return kAmendments;
}
bool

View File

@@ -159,6 +159,7 @@ struct Amendments {
REGISTER(fix1523);
REGISTER(fix1528);
REGISTER(fixBatchInnerSigs);
REGISTER(fixCleanup3_1_3);
// NOLINTEND(readability-identifier-naming)
/** @endcond */
};

View File

@@ -17,7 +17,7 @@ namespace data {
namespace {
std::vector<std::int64_t> const kHISTOGRAM_BUCKETS{1, 2, 5, 10, 20, 50, 100, 200, 500, 700, 1000};
std::vector<std::int64_t> const kHistogramBuckets{1, 2, 5, 10, 20, 50, 100, 200, 500, 700, 1000};
std::int64_t
durationInMillisecondsSince(std::chrono::steady_clock::time_point const startTime)
@@ -60,7 +60,7 @@ BackendCounters::BackendCounters()
PrometheusService::histogramInt(
"backend_duration_milliseconds_histogram",
Labels({Label{"operation", "read"}}),
kHISTOGRAM_BUCKETS,
kHistogramBuckets,
"The duration of backend read operations including retries"
)
)
@@ -68,7 +68,7 @@ BackendCounters::BackendCounters()
PrometheusService::histogramInt(
"backend_duration_milliseconds_histogram",
Labels({Label{"operation", "write"}}),
kHISTOGRAM_BUCKETS,
kHistogramBuckets,
"The duration of backend write operations including retries"
)
)

View File

@@ -130,7 +130,7 @@ public:
*
* @return The report
*/
boost::json::object
[[nodiscard]] boost::json::object
report() const;
private:
@@ -152,7 +152,7 @@ private:
void
registerError(std::uint64_t count);
boost::json::object
[[nodiscard]] boost::json::object
report() const;
private:

View File

@@ -188,7 +188,7 @@ BackendInterface::fetchBookOffers(
auto mid2 = std::chrono::system_clock::now();
numSucc++;
succMillis += getMillis(mid2 - mid1);
if (!offerDir || offerDir->key >= bookEnd) {
if (not offerDir.has_value() || offerDir->key >= bookEnd) {
LOG(log_.trace()) << "offerDir.has_value() " << offerDir.has_value() << " breaking";
break;
}
@@ -208,8 +208,10 @@ BackendInterface::fetchBookOffers(
auto nextKey = ripple::keylet::page(uTipIndex, next);
auto nextDir = fetchLedgerObject(nextKey.key, ledgerSequence, yield);
ASSERT(nextDir.has_value(), "Next dir must exist");
// NOLINTBEGIN(bugprone-unchecked-optional-access)
offerDir->blob = *nextDir;
offerDir->key = nextKey.key;
// NOLINTEND(bugprone-unchecked-optional-access)
}
auto mid3 = std::chrono::system_clock::now();
pageMillis += getMillis(mid3 - mid2);
@@ -309,9 +311,10 @@ BackendInterface::fetchLedgerPage(
ripple::uint256 const& curCursor = [&]() {
if (!keys.empty())
return keys.back();
return (cursor ? *cursor : kFIRST_KEY);
return (cursor ? *cursor : kFirstKey);
}();
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
std::uint32_t const seq = outOfOrder ? range_->maxSequence : ledgerSequence;
auto succ = fetchSuccessorKey(curCursor, seq, yield);

View File

@@ -42,14 +42,14 @@ public:
/**
* @return The error message as a C string
*/
char const*
[[nodiscard]] char const*
what() const throw() override
{
return "Database read timed out. Please retry the request";
}
};
static constexpr std::size_t kDEFAULT_WAIT_BETWEEN_RETRY = 500;
static constexpr std::size_t kDefaultWaitBetweenRetry = 500;
/**
* @brief A helper function that catches DatabaseTimeout exceptions and retries indefinitely.
*
@@ -60,7 +60,7 @@ static constexpr std::size_t kDEFAULT_WAIT_BETWEEN_RETRY = 500;
*/
template <typename FnType>
auto
retryOnTimeout(FnType func, size_t waitMs = kDEFAULT_WAIT_BETWEEN_RETRY)
retryOnTimeout(FnType func, size_t waitMs = kDefaultWaitBetweenRetry)
{
static util::Logger const log{"Backend"}; // NOLINT(readability-identifier-naming)

View File

@@ -99,7 +99,7 @@ public:
return true;
}
NFTsAndCursor
[[nodiscard]] NFTsAndCursor
fetchNFTsByIssuer(
ripple::AccountID const& issuer,
std::optional<std::uint32_t> const& taxon,
@@ -190,7 +190,7 @@ public:
return ret;
}
std::vector<ripple::uint256>
[[nodiscard]] std::vector<ripple::uint256>
fetchAccountRoots(
std::uint32_t number,
std::uint32_t pageSize,

View File

@@ -209,13 +209,13 @@ template <typename T>
inline bool
isDirNode(T const& object)
{
static constexpr auto kMIN_SIZE_REQUIRED = 3;
if (std::size(object) < kMIN_SIZE_REQUIRED)
static constexpr auto kMinSizeRequired = 3;
if (std::size(object) < kMinSizeRequired)
return false;
static constexpr short kDIR_NODE_SPACE_KEY = 0x0064;
static constexpr short kDirNodeSpaceKey = 0x0064;
short const spaceKey = (object.data()[1] << 8) | object.data()[2];
return spaceKey == kDIR_NODE_SPACE_KEY;
return spaceKey == kDirNodeSpaceKey;
}
/**
@@ -246,12 +246,12 @@ template <typename T>
inline ripple::uint256
getBookBase(T const& key)
{
static constexpr size_t kEY_SIZE = 24;
static constexpr size_t kEySize = 24;
ASSERT(key.size() == ripple::uint256::size(), "Invalid key size {}", key.size());
ripple::uint256 ret;
for (size_t i = 0; i < kEY_SIZE; ++i)
for (size_t i = 0; i < kEySize; ++i)
ret.data()[i] = key.data()[i];
return ret;
@@ -270,4 +270,4 @@ uint256ToString(ripple::uint256 const& input)
}
/** @brief The ripple epoch start timestamp. Midnight on 1st January 2000. */
static constexpr std::uint32_t kRIPPLE_EPOCH_START = 946684800;
static constexpr std::uint32_t kRippleEpochStart = 946684800;

View File

@@ -102,7 +102,7 @@ public:
return true;
}
NFTsAndCursor
[[nodiscard]] NFTsAndCursor
fetchNFTsByIssuer(
ripple::AccountID const& issuer,
std::optional<std::uint32_t> const& taxon,
@@ -162,7 +162,7 @@ public:
* @param yield The coroutine context.
* @return A vector of ripple::uint256 representing the account root hashes.
*/
std::vector<ripple::uint256>
[[nodiscard]] std::vector<ripple::uint256>
fetchAccountRoots(
[[maybe_unused]] std::uint32_t number,
[[maybe_unused]] std::uint32_t pageSize,
@@ -175,7 +175,7 @@ public:
}
private:
std::vector<ripple::uint256>
[[nodiscard]] std::vector<ripple::uint256>
fetchNFTIDsByTaxon(
ripple::AccountID const& issuer,
std::uint32_t const taxon,
@@ -198,7 +198,7 @@ private:
return nftIDs;
}
std::vector<ripple::uint256>
[[nodiscard]] std::vector<ripple::uint256>
fetchNFTIDsWithoutTaxon(
ripple::AccountID const& issuer,
std::uint32_t const limit,
@@ -242,7 +242,7 @@ private:
* @brief Takes a list of NFT IDs, fetches their full data, and assembles the final result with
* a cursor.
*/
NFTsAndCursor
[[nodiscard]] NFTsAndCursor
populateNFTsAndCreateCursor(
std::vector<ripple::uint256> const& nftIDs,
std::uint32_t const ledgerSequence,

View File

@@ -55,7 +55,7 @@ public:
* @param seq The sequence to fetch for
* @return If found in cache, will return the cached Blob; otherwise nullopt is returned
*/
virtual std::optional<Blob>
[[nodiscard]] virtual std::optional<Blob>
get(ripple::uint256 const& key, uint32_t seq) const = 0;
/**
@@ -65,7 +65,7 @@ public:
* @param seq The sequence to fetch for
* @return If found in deleted cache, will return the cached Blob; otherwise nullopt is returned
*/
virtual std::optional<Blob>
[[nodiscard]] virtual std::optional<Blob>
getDeleted(ripple::uint256 const& key, uint32_t seq) const = 0;
/**
@@ -77,7 +77,7 @@ public:
* @param seq The sequence to fetch for
* @return If found in cache, will return the cached successor; otherwise nullopt is returned
*/
virtual std::optional<LedgerObject>
[[nodiscard]] virtual std::optional<LedgerObject>
getSuccessor(ripple::uint256 const& key, uint32_t seq) const = 0;
/**
@@ -89,7 +89,7 @@ public:
* @param seq The sequence to fetch for
* @return If found in cache, will return the cached predcessor; otherwise nullopt is returned
*/
virtual std::optional<LedgerObject>
[[nodiscard]] virtual std::optional<LedgerObject>
getPredecessor(ripple::uint256 const& key, uint32_t seq) const = 0;
/**
@@ -101,7 +101,7 @@ public:
/**
* @return true if the cache is disabled; false otherwise
*/
virtual bool
[[nodiscard]] virtual bool
isDisabled() const = 0;
/**
@@ -117,33 +117,33 @@ public:
/**
* @return The latest ledger sequence for which cache is available.
*/
virtual uint32_t
[[nodiscard]] virtual uint32_t
latestLedgerSequence() const = 0;
/**
* @return true if the cache has all data for the most recent ledger; false otherwise
*/
virtual bool
[[nodiscard]] virtual bool
isFull() const = 0;
/**
* @return The total size of the cache.
*/
virtual size_t
[[nodiscard]] virtual size_t
size() const = 0;
/**
* @return A number representing the success rate of hitting an object in the cache versus
* missing it.
*/
virtual float
[[nodiscard]] virtual float
getObjectHitRate() const = 0;
/**
* @return A number representing the success rate of hitting a successor in the cache versus
* missing it.
*/
virtual float
[[nodiscard]] virtual float
getSuccessorHitRate() const = 0;
/**

View File

@@ -312,13 +312,13 @@ struct AmendmentKey {
operator<=>(AmendmentKey const& other) const = default;
};
constexpr ripple::uint256 kFIRST_KEY{
constexpr ripple::uint256 kFirstKey{
"0000000000000000000000000000000000000000000000000000000000000000"
};
constexpr ripple::uint256 kLAST_KEY{
constexpr ripple::uint256 kLastKey{
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
};
constexpr ripple::uint256 kHI192{
constexpr ripple::uint256 kHi192{
"0000000000000000000000000000000000000000000000001111111111111111"
};

View File

@@ -564,7 +564,7 @@ public:
<< ", key = " << ripple::to_string(key);
if (auto const res = executor_.read(yield, schema_->selectObject, key, sequence); res) {
if (auto const result = res->template get<Blob, std::uint32_t>(); result) {
auto [_, seq] = result.value();
auto [_, seq] = *result;
return seq;
}
LOG(log_.debug()) << "Could not fetch ledger object sequence - no rows";
@@ -603,7 +603,7 @@ public:
if (auto const res = executor_.read(yield, schema_->selectSuccessor, key, ledgerSequence);
res) {
if (auto const result = res->template get<ripple::uint256>(); result) {
if (*result == kLAST_KEY)
if (*result == kLastKey)
return std::nullopt;
return result;
}
@@ -923,14 +923,15 @@ public:
record.tokenID
));
statements.push_back(schema_->insertNFTURI.bind(
record.tokenID, record.ledgerSequence, record.uri.value()
record.tokenID, record.ledgerSequence, *record.uri
));
}
} else {
// only uri changed, we update the uri table only
statements.push_back(schema_->insertNFTURI.bind(
record.tokenID, record.ledgerSequence, record.uri.value()
));
statements.push_back(
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
schema_->insertNFTURI.bind(record.tokenID, record.ledgerSequence, *record.uri)
);
}
}
@@ -1002,7 +1003,7 @@ protected:
return false;
}
if (not maybeSuccess.value()) {
if (not *maybeSuccess) {
LOG(log_.warn()) << "Update failed. Checking if DB state is what we expect";
// error may indicate that another writer wrote something.

View File

@@ -65,7 +65,7 @@ public:
/**
* @return The final error message as a std::string
*/
std::string
[[nodiscard]] std::string
message() const
{
return message_;
@@ -74,7 +74,7 @@ public:
/**
* @return The error code
*/
uint32_t
[[nodiscard]] uint32_t
code() const
{
return code_;
@@ -83,7 +83,7 @@ public:
/**
* @return true if the wrapped error is considered a timeout; false otherwise
*/
bool
[[nodiscard]] bool
isTimeout() const
{
return code_ == CASS_ERROR_LIB_NO_HOSTS_AVAILABLE or
@@ -94,7 +94,7 @@ public:
/**
* @return true if the wrapped error is an invalid query; false otherwise
*/
bool
[[nodiscard]] bool
isInvalidQuery() const
{
return code_ == CASS_ERROR_SERVER_INVALID_QUERY;

View File

@@ -114,7 +114,7 @@ public:
*
* @return Possibly an error
*/
[[maybe_unused]] MaybeErrorType
[[nodiscard]] [[maybe_unused]] MaybeErrorType
disconnect() const;
/**
@@ -162,7 +162,7 @@ public:
* @return The result or an error
*/
template <typename... Args>
[[maybe_unused]] ResultOrErrorType
[[nodiscard]] [[maybe_unused]] ResultOrErrorType
execute(std::string_view query, Args&&... args) const
{
return asyncExecute<Args...>(query, std::forward<Args>(args)...).get();
@@ -189,7 +189,7 @@ public:
* @param statements The statements to execute
* @return Possibly an error
*/
[[maybe_unused]] MaybeErrorType
[[nodiscard]] [[maybe_unused]] MaybeErrorType
executeEach(std::vector<StatementType> const& statements) const;
/**
@@ -250,7 +250,7 @@ public:
* @param statement The statement to execute
* @return The result or an error
*/
[[maybe_unused]] ResultOrErrorType
[[nodiscard]] [[maybe_unused]] ResultOrErrorType
execute(StatementType const& statement) const;
/**
@@ -270,7 +270,7 @@ public:
* @param statements The statements to execute
* @return Possibly an error
*/
[[maybe_unused]] MaybeErrorType
[[nodiscard]] [[maybe_unused]] MaybeErrorType
execute(std::vector<StatementType> const& statements) const;
/**

View File

@@ -90,13 +90,13 @@ SettingsProvider::parseSettings() const
if (config_.getValueView("connect_timeout").hasValue()) {
auto const connectTimeoutSecond = config_.get<uint32_t>("connect_timeout");
settings.connectionTimeout =
std::chrono::milliseconds{connectTimeoutSecond * util::kMILLISECONDS_PER_SECOND};
std::chrono::milliseconds{connectTimeoutSecond * util::kMillisecondsPerSecond};
}
if (config_.getValueView("request_timeout").hasValue()) {
auto const requestTimeoutSecond = config_.get<uint32_t>("request_timeout");
settings.requestTimeout =
std::chrono::milliseconds{requestTimeoutSecond * util::kMILLISECONDS_PER_SECOND};
std::chrono::milliseconds{requestTimeoutSecond * util::kMillisecondsPerSecond};
}
settings.certificate = parseOptionalCertificate();

View File

@@ -12,7 +12,7 @@
#include <vector>
namespace {
constexpr auto kBATCH_DELETER = [](CassBatch* ptr) { cass_batch_free(ptr); };
constexpr auto kBatchDeleter = [](CassBatch* ptr) { cass_batch_free(ptr); };
} // namespace
namespace data::cassandra::impl {
@@ -29,7 +29,7 @@ namespace data::cassandra::impl {
* https://docs.datastax.com/en/developer/cpp-driver-dse/1.10/features/basics/batches/index.html
*/
Batch::Batch(std::vector<Statement> const& statements)
: ManagedObject{cass_batch_new(CASS_BATCH_TYPE_UNLOGGED), kBATCH_DELETER}
: ManagedObject{cass_batch_new(CASS_BATCH_TYPE_UNLOGGED), kBatchDeleter}
{
cass_batch_set_is_idempotent(*this, cass_true);

View File

@@ -14,13 +14,13 @@
namespace {
constexpr auto kCLUSTER_DELETER = [](CassCluster* ptr) { cass_cluster_free(ptr); };
constexpr auto kClusterDeleter = [](CassCluster* ptr) { cass_cluster_free(ptr); };
}; // namespace
namespace data::cassandra::impl {
Cluster::Cluster(Settings const& settings) : ManagedObject{cass_cluster_new(), kCLUSTER_DELETER}
Cluster::Cluster(Settings const& settings) : ManagedObject{cass_cluster_new(), kClusterDeleter}
{
using std::to_string;
@@ -123,8 +123,8 @@ Cluster::setupContactPoints(Settings::ContactPoints const& points)
}
if (points.port) {
auto const rc = cass_cluster_set_port(*this, points.port.value());
throwErrorIfNeeded(rc, "port", to_string(points.port.value()));
auto const rc = cass_cluster_set_port(*this, *points.port);
throwErrorIfNeeded(rc, "port", to_string(*points.port));
}
}
@@ -158,10 +158,8 @@ Cluster::setupCredentials(Settings const& settings)
if (not settings.username || not settings.password)
return;
LOG(log_.debug()) << "Set credentials; username: " << settings.username.value();
cass_cluster_set_credentials(
*this, settings.username.value().c_str(), settings.password.value().c_str()
);
LOG(log_.debug()) << "Set credentials; username: " << *settings.username;
cass_cluster_set_credentials(*this, settings.username->c_str(), settings.password->c_str());
}
} // namespace data::cassandra::impl

View File

@@ -35,11 +35,11 @@ providerFromString(std::string const& provider)
* @brief Bundles all cassandra settings in one place.
*/
struct Settings {
static constexpr std::size_t kDEFAULT_CONNECTION_TIMEOUT = 10000;
static constexpr uint32_t kDEFAULT_MAX_WRITE_REQUESTS_OUTSTANDING = 10'000;
static constexpr uint32_t kDEFAULT_MAX_READ_REQUESTS_OUTSTANDING = 100'000;
static constexpr std::size_t kDEFAULT_BATCH_SIZE = 20;
static constexpr Provider kDEFAULT_PROVIDER = Provider::Cassandra;
static constexpr std::size_t kDefaultConnectionTimeout = 10000;
static constexpr uint32_t kDefaultMaxWriteRequestsOutstanding = 10'000;
static constexpr uint32_t kDefaultMaxReadRequestsOutstanding = 100'000;
static constexpr std::size_t kDefaultBatchSize = 20;
static constexpr Provider kDefaultProvider = Provider::Cassandra;
/**
* @brief Represents the configuration of contact points for cassandra.
@@ -61,7 +61,7 @@ struct Settings {
/** @brief Connect timeout specified in milliseconds */
std::chrono::milliseconds connectionTimeout =
std::chrono::milliseconds{kDEFAULT_CONNECTION_TIMEOUT};
std::chrono::milliseconds{kDefaultConnectionTimeout};
/** @brief Request timeout specified in milliseconds */
std::chrono::milliseconds requestTimeout = std::chrono::milliseconds{0}; // no timeout at all
@@ -73,19 +73,19 @@ struct Settings {
uint32_t threads = std::thread::hardware_concurrency();
/** @brief The maximum number of outstanding write requests at any given moment */
uint32_t maxWriteRequestsOutstanding = kDEFAULT_MAX_WRITE_REQUESTS_OUTSTANDING;
uint32_t maxWriteRequestsOutstanding = kDefaultMaxWriteRequestsOutstanding;
/** @brief The maximum number of outstanding read requests at any given moment */
uint32_t maxReadRequestsOutstanding = kDEFAULT_MAX_READ_REQUESTS_OUTSTANDING;
uint32_t maxReadRequestsOutstanding = kDefaultMaxReadRequestsOutstanding;
/** @brief The number of connection per host to always have active */
uint32_t coreConnectionsPerHost = 3u;
/** @brief Size of batches when writing */
std::size_t writeBatchSize = kDEFAULT_BATCH_SIZE;
std::size_t writeBatchSize = kDefaultBatchSize;
/** @brief Provider to know if we are using scylladb or keyspace */
Provider provider = kDEFAULT_PROVIDER;
Provider provider = kDefaultProvider;
/** @brief Size of the IO queue */
std::optional<uint32_t> queueSizeIO =

View File

@@ -14,7 +14,7 @@
namespace data::cassandra::impl {
class Collection : public ManagedObject<CassCollection> {
static constexpr auto kDELETER = [](CassCollection* ptr) { cass_collection_free(ptr); };
static constexpr auto kDeleter = [](CassCollection* ptr) { cass_collection_free(ptr); };
static void
throwErrorIfNeeded(CassError const rc, std::string_view const label)
@@ -30,7 +30,7 @@ public:
template <typename Type>
explicit Collection(std::vector<Type> const& value)
: ManagedObject{cass_collection_new(CASS_COLLECTION_TYPE_LIST, value.size()), kDELETER}
: ManagedObject{cass_collection_new(CASS_COLLECTION_TYPE_LIST, value.size()), kDeleter}
{
bind(value);
}

View File

@@ -525,13 +525,13 @@ private:
{
// mutex lock required to prevent race condition around spurious
// wakeup
std::lock_guard const lck(throttleMutex_);
std::scoped_lock const lck(throttleMutex_);
throttleCv_.notify_one();
}
if (cur == 0) {
// mutex lock required to prevent race condition around spurious
// wakeup
std::lock_guard const lck(syncMutex_);
std::scoped_lock const lck(syncMutex_);
syncCv_.notify_one();
}
}

View File

@@ -13,12 +13,12 @@
#include <utility>
namespace {
constexpr auto kFUTURE_DELETER = [](CassFuture* ptr) { cass_future_free(ptr); };
constexpr auto kFutureDeleter = [](CassFuture* ptr) { cass_future_free(ptr); };
} // namespace
namespace data::cassandra::impl {
/* implicit */ Future::Future(CassFuture* ptr) : ManagedObject{ptr, kFUTURE_DELETER}
/* implicit */ Future::Future(CassFuture* ptr) : ManagedObject{ptr, kFutureDeleter}
{
}

View File

@@ -13,10 +13,10 @@ namespace data::cassandra::impl {
struct Future : public ManagedObject<CassFuture> {
/* implicit */ Future(CassFuture* ptr);
MaybeError
[[nodiscard]] MaybeError
await() const;
ResultOrError
[[nodiscard]] ResultOrError
get() const;
};

View File

@@ -7,13 +7,13 @@
#include <cstddef>
namespace {
constexpr auto kRESULT_DELETER = [](CassResult const* ptr) { cass_result_free(ptr); };
constexpr auto kRESULT_ITERATOR_DELETER = [](CassIterator* ptr) { cass_iterator_free(ptr); };
constexpr auto kResultDeleter = [](CassResult const* ptr) { cass_result_free(ptr); };
constexpr auto kResultIteratorDeleter = [](CassIterator* ptr) { cass_iterator_free(ptr); };
} // namespace
namespace data::cassandra::impl {
/* implicit */ Result::Result(CassResult const* ptr) : ManagedObject{ptr, kRESULT_DELETER}
/* implicit */ Result::Result(CassResult const* ptr) : ManagedObject{ptr, kResultDeleter}
{
}
@@ -30,7 +30,7 @@ Result::hasRows() const
}
/* implicit */ ResultIterator::ResultIterator(CassIterator* ptr)
: ManagedObject{ptr, kRESULT_ITERATOR_DELETER}, hasMore_{cass_iterator_next(ptr) != 0u}
: ManagedObject{ptr, kResultIteratorDeleter}, hasMore_{cass_iterator_next(ptr) != 0u}
{
}

View File

@@ -108,7 +108,7 @@ struct Result : public ManagedObject<CassResult const> {
hasRows() const;
template <typename... RowTypes>
std::optional<std::tuple<RowTypes...>>
[[nodiscard]] std::optional<std::tuple<RowTypes...>>
get() const
requires(std::tuple_size<std::tuple<RowTypes...>>{} > 1)
{
@@ -126,7 +126,7 @@ struct Result : public ManagedObject<CassResult const> {
}
template <typename RowType>
std::optional<RowType>
[[nodiscard]] std::optional<RowType>
get() const
{
// row managed internally by cassandra driver, hence no ManagedObject.
@@ -153,7 +153,7 @@ public:
hasMore() const;
template <typename... RowTypes>
std::tuple<RowTypes...>
[[nodiscard]] std::tuple<RowTypes...>
extractCurrentRow() const
{
// note: row is invalidated on each iteration.

View File

@@ -7,10 +7,10 @@
namespace data::cassandra::impl {
class Session : public ManagedObject<CassSession> {
static constexpr auto kDELETER = [](CassSession* ptr) { cass_session_free(ptr); };
static constexpr auto kDeleter = [](CassSession* ptr) { cass_session_free(ptr); };
public:
Session() : ManagedObject{cass_session_new(), kDELETER}
Session() : ManagedObject{cass_session_new(), kDeleter}
{
}
};

View File

@@ -8,13 +8,13 @@
#include <string>
namespace {
constexpr auto kCONTEXT_DELETER = [](CassSsl* ptr) { cass_ssl_free(ptr); };
constexpr auto kContextDeleter = [](CassSsl* ptr) { cass_ssl_free(ptr); };
} // namespace
namespace data::cassandra::impl {
SslContext::SslContext(std::string const& certificate)
: ManagedObject{cass_ssl_new(), kCONTEXT_DELETER}
: ManagedObject{cass_ssl_new(), kContextDeleter}
{
cass_ssl_set_verify_flags(*this, CASS_SSL_VERIFY_NONE);
if (auto const rc = cass_ssl_add_trusted_cert(*this, certificate.c_str()); rc != CASS_OK) {

View File

@@ -26,7 +26,7 @@
namespace data::cassandra::impl {
class Statement : public ManagedObject<CassStatement> {
static constexpr auto kDELETER = [](CassStatement* ptr) { cass_statement_free(ptr); };
static constexpr auto kDeleter = [](CassStatement* ptr) { cass_statement_free(ptr); };
public:
/**
@@ -37,7 +37,7 @@ public:
*/
template <typename... Args>
explicit Statement(std::string_view query, Args&&... args)
: ManagedObject{cass_statement_new_n(query.data(), query.size(), sizeof...(args)), kDELETER}
: ManagedObject{cass_statement_new_n(query.data(), query.size(), sizeof...(args)), kDeleter}
{
// TODO: figure out how to set consistency level in config
// NOTE: Keyspace doesn't support QUORUM at write level
@@ -46,7 +46,7 @@ public:
bind<Args...>(std::forward<Args>(args)...);
}
/* implicit */ Statement(CassStatement* ptr) : ManagedObject{ptr, kDELETER}
/* implicit */ Statement(CassStatement* ptr) : ManagedObject{ptr, kDeleter}
{
// cass_statement_set_consistency(*this, CASS_CONSISTENCY_LOCAL_QUORUM);
cass_statement_set_is_idempotent(*this, cass_true);
@@ -157,10 +157,10 @@ public:
* This is used to produce Statement objects that can be executed.
*/
class PreparedStatement : public ManagedObject<CassPrepared const> {
static constexpr auto kDELETER = [](CassPrepared const* ptr) { cass_prepared_free(ptr); };
static constexpr auto kDeleter = [](CassPrepared const* ptr) { cass_prepared_free(ptr); };
public:
/* implicit */ PreparedStatement(CassPrepared const* ptr) : ManagedObject{ptr, kDELETER}
/* implicit */ PreparedStatement(CassPrepared const* ptr) : ManagedObject{ptr, kDeleter}
{
}
@@ -171,7 +171,7 @@ public:
* @return A bound and ready to execute Statement object
*/
template <typename... Args>
Statement
[[nodiscard]] Statement
bind(Args&&... args) const
{
Statement statement = cass_prepared_bind(*this);

View File

@@ -5,18 +5,18 @@
#include <cassandra.h>
namespace {
constexpr auto kTUPLE_DELETER = [](CassTuple* ptr) { cass_tuple_free(ptr); };
constexpr auto kTUPLE_ITERATOR_DELETER = [](CassIterator* ptr) { cass_iterator_free(ptr); };
constexpr auto kTupleDeleter = [](CassTuple* ptr) { cass_tuple_free(ptr); };
constexpr auto kTupleIteratorDeleter = [](CassIterator* ptr) { cass_iterator_free(ptr); };
} // namespace
namespace data::cassandra::impl {
/* implicit */ Tuple::Tuple(CassTuple* ptr) : ManagedObject{ptr, kTUPLE_DELETER}
/* implicit */ Tuple::Tuple(CassTuple* ptr) : ManagedObject{ptr, kTupleDeleter}
{
}
/* implicit */ TupleIterator::TupleIterator(CassIterator* ptr)
: ManagedObject{ptr, kTUPLE_ITERATOR_DELETER}
: ManagedObject{ptr, kTupleIteratorDeleter}
{
}

View File

@@ -18,14 +18,14 @@
namespace data::cassandra::impl {
class Tuple : public ManagedObject<CassTuple> {
static constexpr auto kDELETER = [](CassTuple* ptr) { cass_tuple_free(ptr); };
static constexpr auto kDeleter = [](CassTuple* ptr) { cass_tuple_free(ptr); };
public:
/* implicit */ Tuple(CassTuple* ptr);
template <typename... Types>
explicit Tuple(std::tuple<Types...>&& value)
: ManagedObject{cass_tuple_new(std::tuple_size<std::tuple<Types...>>{}), kDELETER}
: ManagedObject{cass_tuple_new(std::tuple_size<std::tuple<Types...>>{}), kDeleter}
{
std::apply(std::bind_front(&Tuple::bind<Types...>, this), std::move(value));
}
@@ -93,7 +93,7 @@ public:
private:
template <typename Type>
Type
[[nodiscard]] Type
extractNext() const
{
using std::to_string;

View File

@@ -19,7 +19,7 @@ namespace data::impl {
using Hash = ripple::uint256;
using Separator = std::array<char, 16>;
static constexpr Separator kSEPARATOR = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static constexpr Separator kSeparator = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
namespace {
@@ -78,7 +78,7 @@ LedgerCacheFile::write(DataView dataView)
.deletedSize = dataView.deleted.size()
};
file.write(header);
file.write(kSEPARATOR);
file.write(kSeparator);
for (auto const& [k, v] : dataView.map) {
file.write(k.data(), decltype(k)::bytes);
@@ -86,7 +86,7 @@ LedgerCacheFile::write(DataView dataView)
file.write(v.blob.size());
file.writeRaw(reinterpret_cast<char const*>(v.blob.data()), v.blob.size());
}
file.write(kSEPARATOR);
file.write(kSeparator);
for (auto const& [k, v] : dataView.deleted) {
file.write(k.data(), decltype(k)::bytes);
@@ -94,7 +94,7 @@ LedgerCacheFile::write(DataView dataView)
file.write(v.blob.size());
file.writeRaw(reinterpret_cast<char const*>(v.blob.data()), v.blob.size());
}
file.write(kSEPARATOR);
file.write(kSeparator);
auto const hash = file.hash();
file.write(hash.data(), decltype(hash)::bytes);
@@ -129,9 +129,9 @@ LedgerCacheFile::read(uint32_t minLatestSequence)
if (not file.read(header)) {
return std::unexpected{"Error reading cache header"};
}
if (header.version != kVERSION) {
if (header.version != kVersion) {
return std::unexpected{fmt::format(
"Cache has wrong version: expected {} found {}", kVERSION, header.version
"Cache has wrong version: expected {} found {}", kVersion, header.version
)};
}
if (header.latestSeq < minLatestSequence) {

View File

@@ -17,14 +17,14 @@ namespace data::impl {
class LedgerCacheFile {
public:
struct Header {
uint32_t version = kVERSION;
uint32_t version = kVersion;
uint32_t latestSeq{};
uint64_t mapSize{};
uint64_t deletedSize{};
};
private:
static constexpr uint32_t kVERSION = 1;
static constexpr uint32_t kVersion = 1;
std::string path_;

View File

@@ -47,8 +47,7 @@ makeCacheLoaderSettings(util::config::ClioConfigDefinition const& config)
if (auto filePath = cache.maybeValue<std::string>("file.path"); filePath.has_value()) {
settings.cacheFileSettings = CacheLoaderSettings::CacheFileSettings{
.path = std::move(filePath).value(),
.maxAge = cache.get<uint32_t>("file.max_sequence_age")
.path = *std::move(filePath), .maxAge = cache.get<uint32_t>("file.max_sequence_age")
};
}

View File

@@ -417,6 +417,7 @@ ETLService::attemptTakeoverWriter()
auto rng = backend_->hardFetchLedgerRangeNoThrow();
ASSERT(rng.has_value(), "Ledger range can't be null");
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
if (backend_->cache().latestLedgerSequence() != rng->maxSequence) {
LOG(log_.info()) << "Wanted to take over the ETL writer seat but LedgerCache is outdated";
// Give ETL time to update LedgerCache. This method will be called because
@@ -426,7 +427,7 @@ ETLService::attemptTakeoverWriter()
state_->isWriting = true; // switch to writer
LOG(log_.info()) << "Taking over the ETL writer seat";
startLoading(rng->maxSequence + 1);
startLoading(rng->maxSequence + 1); // NOLINT(bugprone-unchecked-optional-access)
}
void

View File

@@ -32,7 +32,7 @@ struct LedgerPublisherInterface {
*
* @return A std::chrono::time_point representing the time of the last publish
*/
virtual std::chrono::time_point<std::chrono::system_clock>
[[nodiscard]] virtual std::chrono::time_point<std::chrono::system_clock>
getLastPublish() const = 0;
/**
@@ -40,7 +40,7 @@ struct LedgerPublisherInterface {
*
* @return The number of seconds since the last ledger close as std::uint32_t
*/
virtual std::uint32_t
[[nodiscard]] virtual std::uint32_t
lastCloseAgeSeconds() const = 0;
/**
@@ -48,7 +48,7 @@ struct LedgerPublisherInterface {
*
* @return The number of seconds since the last publish as std::uint32_t
*/
virtual std::uint32_t
[[nodiscard]] virtual std::uint32_t
lastPublishAgeSeconds() const = 0;
};

View File

@@ -275,10 +275,11 @@ LoadBalancer::forwardToRippled(
return std::unexpected{rpc::ClioError::RpcCommandIsMissing};
auto const cmd = boost::json::value_to<std::string>(request.at("command"));
if (forwardingCache_) {
if (shouldUseCache(isAdmin)) {
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
if (auto cachedResponse = forwardingCache_->get(cmd); cachedResponse) {
forwardingCounters_.cacheHit.get() += 1;
return std::move(cachedResponse).value();
return *std::move(cachedResponse);
}
}
forwardingCounters_.cacheMiss.get() += 1;
@@ -288,7 +289,7 @@ LoadBalancer::forwardToRippled(
auto numAttempts = 0u;
auto xUserValue = isAdmin ? kADMIN_FORWARDING_X_USER_VALUE : kUSER_FORWARDING_X_USER_VALUE;
auto xUserValue = isAdmin ? kAdminForwardingXUserValue : kUserForwardingXUserValue;
std::optional<boost::json::object> response;
rpc::ClioError error = rpc::ClioError::EtlConnectionError;
@@ -310,9 +311,9 @@ LoadBalancer::forwardToRippled(
}
if (response) {
if (forwardingCache_ and not response->contains("error"))
forwardingCache_->put(cmd, *response);
return std::move(response).value();
if (shouldUseCache(isAdmin) and not response->contains("error"))
forwardingCache_->put(cmd, *response); // NOLINT(bugprone-unchecked-optional-access)
return *std::move(response);
}
return std::unexpected{error};
@@ -415,4 +416,10 @@ LoadBalancer::chooseForwardingSource()
}
}
bool
LoadBalancer::shouldUseCache(bool isAdmin) const
{
return forwardingCache_.has_value() and not isAdmin;
}
} // namespace etl

View File

@@ -63,7 +63,7 @@ public:
using OptionalGetLedgerResponseType = std::optional<GetLedgerResponseType>;
private:
static constexpr std::uint32_t kDEFAULT_DOWNLOAD_RANGES = 16;
static constexpr std::uint32_t kDefaultDownloadRanges = 16;
util::Logger log_{"ETL"};
// Forwarding cache must be destroyed after sources because sources have a callback to
@@ -75,7 +75,7 @@ private:
std::vector<SourcePtr> sources_;
std::optional<ETLState> etlState_;
std::uint32_t downloadRanges_ = kDEFAULT_DOWNLOAD_RANGES; /*< The number of markers to use when
std::uint32_t downloadRanges_ = kDefaultDownloadRanges; /*< The number of markers to use when
downloading initial ledger */
struct ForwardingCounters {
@@ -95,12 +95,12 @@ public:
/**
* @brief Value for the X-User header when forwarding admin requests
*/
static constexpr std::string_view kADMIN_FORWARDING_X_USER_VALUE = "clio_admin";
static constexpr std::string_view kAdminForwardingXUserValue = "clio_admin";
/**
* @brief Value for the X-User header when forwarding user requests
*/
static constexpr std::string_view kUSER_FORWARDING_X_USER_VALUE = "clio_user";
static constexpr std::string_view kUserForwardingXUserValue = "clio_user";
/**
* @brief Create an instance of the load balancer.
@@ -254,6 +254,9 @@ private:
*/
void
chooseForwardingSource();
bool
shouldUseCache(bool isAdmin) const;
};
} // namespace etl

View File

@@ -31,7 +31,7 @@ namespace etl::model {
template <ripple::TxType... Types>
requires(util::hasNoDuplicates(Types...))
struct Spec {
static constexpr bool kSPEC_TAG = true;
static constexpr bool kSpecTag = true;
/**
* @brief Checks if the transaction type was requested.

View File

@@ -16,7 +16,7 @@ namespace etl {
*/
class MonitorInterface {
public:
static constexpr auto kDEFAULT_REPEAT_INTERVAL = std::chrono::seconds{1};
static constexpr auto kDefaultRepeatInterval = std::chrono::seconds{1};
using NewSequenceSignalType = boost::signals2::signal<void(uint32_t)>;
using DbStalledSignalType = boost::signals2::signal<void()>;
@@ -61,7 +61,7 @@ public:
* @param repeatInterval The interval between attempts to check the database for new ledgers
*/
virtual void
run(std::chrono::steady_clock::duration repeatInterval = kDEFAULT_REPEAT_INTERVAL) = 0;
run(std::chrono::steady_clock::duration repeatInterval = kDefaultRepeatInterval) = 0;
/**
* @brief Stops the monitor service

View File

@@ -18,7 +18,7 @@ struct MonitorProviderInterface {
/**
* @brief The time Monitor should wait before reporting absence of updates to the database
*/
static constexpr auto kDEFAULT_DB_STALLED_REPORT_DELAY = std::chrono::seconds{10};
static constexpr auto kDefaultDbStalledReportDelay = std::chrono::seconds{10};
virtual ~MonitorProviderInterface() = default;
@@ -38,7 +38,7 @@ struct MonitorProviderInterface {
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<NetworkValidatedLedgersInterface> validatedLedgers,
uint32_t startSequence,
std::chrono::steady_clock::duration dbStalledReportDelay = kDEFAULT_DB_STALLED_REPORT_DELAY
std::chrono::steady_clock::duration dbStalledReportDelay = kDefaultDbStalledReportDelay
) = 0;
};

View File

@@ -18,7 +18,7 @@ NetworkValidatedLedgers::makeValidatedLedgers()
void
NetworkValidatedLedgers::push(uint32_t idx)
{
std::lock_guard const lck(mtx_);
std::scoped_lock const lck(mtx_);
if (!latest_ || idx > *latest_)
latest_ = idx;

View File

@@ -171,14 +171,14 @@ public:
*/
WriterState(std::shared_ptr<SystemState> state, data::LedgerCacheInterface const& cache);
bool
[[nodiscard]] bool
isReadOnly() const override;
/**
* @brief Check if the ETL process is currently writing to the database.
* @return true if the process is writing, false otherwise
*/
bool
[[nodiscard]] bool
isWriting() const override;
/**
@@ -213,11 +213,11 @@ public:
*
* @return true if the cluster has switched to fallback mode, false otherwise
*/
bool
[[nodiscard]] bool
isFallback() const override;
/** @copydoc WriterStateInterface::isFallbackRecovery */
bool
[[nodiscard]] bool
isFallbackRecovery() const override;
/** @copydoc WriterStateInterface::setFallbackRecovery */
@@ -225,11 +225,11 @@ public:
setFallbackRecovery(bool newValue) override;
/** @copydoc WriterStateInterface::isEtlStarted */
bool
[[nodiscard]] bool
isEtlStarted() const override;
/** @copydoc WriterStateInterface::isCacheFull */
bool
[[nodiscard]] bool
isCacheFull() const override;
/**
@@ -239,7 +239,7 @@ public:
*
* @return A unique pointer to the cloned writer state.
*/
std::unique_ptr<WriterStateInterface>
[[nodiscard]] std::unique_ptr<WriterStateInterface>
clone() const override;
};

View File

@@ -11,15 +11,14 @@
namespace etl::impl {
AmendmentBlockHandler::ActionType const AmendmentBlockHandler::kDEFAULT_AMENDMENT_BLOCK_ACTION =
[]() {
static util::Logger const log{"ETL"}; // NOLINT(readability-identifier-naming)
LOG(
log.fatal()
) << "Can't process new ledgers: The current ETL source is not compatible with the version "
"of "
<< "the libxrpl Clio is currently using. Please upgrade Clio to a newer version.";
};
AmendmentBlockHandler::ActionType const AmendmentBlockHandler::kDefaultAmendmentBlockAction = []() {
static util::Logger const log{"ETL"}; // NOLINT(readability-identifier-naming)
LOG(
log.fatal()
) << "Can't process new ledgers: The current ETL source is not compatible with the version "
"of "
<< "the libxrpl Clio is currently using. Please upgrade Clio to a newer version.";
};
AmendmentBlockHandler::AmendmentBlockHandler(
util::async::AnyExecutionContext ctx,

View File

@@ -28,13 +28,13 @@ private:
ActionType action_;
public:
static ActionType const kDEFAULT_AMENDMENT_BLOCK_ACTION;
static ActionType const kDefaultAmendmentBlockAction;
AmendmentBlockHandler(
util::async::AnyExecutionContext ctx,
SystemState& state,
std::chrono::steady_clock::duration interval = std::chrono::seconds{1},
ActionType action = kDEFAULT_AMENDMENT_BLOCK_ACTION
ActionType action = kDefaultAmendmentBlockAction
);
~AmendmentBlockHandler() override;

View File

@@ -104,7 +104,7 @@ private:
return; // queue is empty
}
auto [start, end] = cursor.value();
auto [start, end] = *cursor;
LOG(log_.debug()) << "Starting a cursor: " << ripple::strHex(start);
while (not token.isStopRequested() and not cache_.get().isDisabled()) {
@@ -136,7 +136,7 @@ private:
break; // pick up the next cursor if available
}
start = std::move(res.cursor).value();
start = *std::move(res.cursor);
}
}
});

View File

@@ -43,10 +43,10 @@ public:
}();
rg::sort(accountRoots);
std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
std::vector<ripple::uint256> cursors{data::kFirstKey};
rg::copy(accountRoots.begin(), accountRoots.end(), std::back_inserter(cursors));
rg::sort(cursors);
cursors.push_back(data::kLAST_KEY);
cursors.push_back(data::kLastKey);
std::vector<CursorPair> pairs;
pairs.reserve(cursors.size());

View File

@@ -46,6 +46,7 @@ public:
std::set<ripple::uint256> liveCursors;
std::set<ripple::uint256> deletedCursors;
auto i = 0;
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
while (liveCursors.size() < numCursors_ and seq - i >= range->minSequence) {
auto diffs = fetchDiff(i++);
rg::copy(
@@ -66,13 +67,13 @@ public:
);
}
std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
std::vector<ripple::uint256> cursors{data::kFirstKey};
rg::copy(
liveCursors | vs::take(std::min(liveCursors.size(), numCursors_)),
std::back_inserter(cursors)
);
rg::sort(cursors);
cursors.push_back(data::kLAST_KEY);
cursors.push_back(data::kLastKey);
std::vector<CursorPair> pairs;
pairs.reserve(cursors.size());

View File

@@ -57,14 +57,14 @@ public:
rg::unique(diffs, [](auto const& a, auto const& b) { return a.key == b.key; });
diffs.erase(removalCursor, last);
std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
std::vector<ripple::uint256> cursors{data::kFirstKey};
rg::copy(
diffs //
| vs::filter([](auto const& obj) { return not obj.blob.empty(); }) //
| vs::transform([](auto const& obj) { return obj.key; }),
std::back_inserter(cursors)
);
cursors.push_back(data::kLAST_KEY); // last pair should cover the remaining range
cursors.push_back(data::kLastKey); // last pair should cover the remaining range
std::vector<CursorPair> pairs;
pairs.reserve(cursors.size());

View File

@@ -94,6 +94,8 @@ extractObj(PBObjType obj)
{
auto const key = ripple::uint256::fromVoidChecked(obj.key());
ASSERT(key.has_value(), "Failed to deserialize key from void");
if (!key)
return {};
auto const valueOr = [](std::string const& maybe, std::string fallback) -> std::string {
if (maybe.empty())
@@ -106,8 +108,8 @@ extractObj(PBObjType obj)
.keyRaw = std::move(*obj.mutable_key()),
.data = {obj.mutable_data()->begin(), obj.mutable_data()->end()},
.dataRaw = std::move(*obj.mutable_data()),
.successor = valueOr(obj.successor(), uint256ToString(data::kFIRST_KEY)),
.predecessor = valueOr(obj.predecessor(), uint256ToString(data::kLAST_KEY)),
.successor = valueOr(obj.successor(), uint256ToString(data::kFirstKey)),
.predecessor = valueOr(obj.predecessor(), uint256ToString(data::kLastKey)),
.type = extractModType(obj.mod_type()),
};
}

View File

@@ -20,14 +20,14 @@ class ForwardingSource {
util::requests::WsConnectionBuilder connectionBuilder_;
std::chrono::steady_clock::duration forwardingTimeout_;
static constexpr std::chrono::seconds kCONNECTION_TIMEOUT{3};
static constexpr std::chrono::seconds kConnectionTimeout{3};
public:
ForwardingSource(
std::string ip,
std::string wsPort,
std::chrono::steady_clock::duration forwardingTimeout,
std::chrono::steady_clock::duration connTimeout = ForwardingSource::kCONNECTION_TIMEOUT
std::chrono::steady_clock::duration connTimeout = ForwardingSource::kConnectionTimeout
);
/**
@@ -39,7 +39,7 @@ public:
* @param yield The coroutine context
* @return Response on success or error on failure
*/
std::expected<boost::json::object, rpc::ClioError>
[[nodiscard]] std::expected<boost::json::object, rpc::ClioError>
forwardToRippled(
boost::json::object const& request,
std::optional<std::string> const& forwardToRippledClientIp,

View File

@@ -58,13 +58,12 @@ GrpcSource::GrpcSource(
try {
grpc::ChannelArguments chArgs;
chArgs.SetMaxReceiveMessageSize(-1);
chArgs.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, kKEEPALIVE_PING_INTERVAL_MS);
chArgs.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, kKEEPALIVE_TIMEOUT_MS);
chArgs.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, kKeepalivePingIntervalMs);
chArgs.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, kKeepaliveTimeoutMs);
chArgs.SetInt(
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS,
static_cast<int>(kKEEPALIVE_PERMIT_WITHOUT_CALLS)
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, static_cast<int>(kKeepalivePermitWithoutCalls)
);
chArgs.SetInt(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, kMAX_PINGS_WITHOUT_DATA);
chArgs.SetInt(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, kMaxPingsWithoutData);
stub_ = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
grpc::CreateCustomChannel(

View File

@@ -24,18 +24,18 @@ class GrpcSource {
std::unique_ptr<std::atomic_bool> initialLoadShouldStop_;
std::chrono::system_clock::duration deadline_;
static constexpr auto kKEEPALIVE_PING_INTERVAL_MS = 10000;
static constexpr auto kKEEPALIVE_TIMEOUT_MS = 5000;
static constexpr auto kKEEPALIVE_PERMIT_WITHOUT_CALLS =
true; // Allow keepalive pings when no calls
static constexpr auto kMAX_PINGS_WITHOUT_DATA = 0; // No limit
static constexpr auto kDEADLINE = std::chrono::seconds(30);
static constexpr auto kKeepalivePingIntervalMs = 10000;
static constexpr auto kKeepaliveTimeoutMs = 5000;
static constexpr auto kKeepalivePermitWithoutCalls =
true; // Allow keepalive pings when no calls
static constexpr auto kMaxPingsWithoutData = 0; // No limit
static constexpr auto kDeadline = std::chrono::seconds(30);
public:
GrpcSource(
std::string const& ip,
std::string const& grpcPort,
std::chrono::system_clock::duration deadline = kDEADLINE
std::chrono::system_clock::duration deadline = kDeadline
);
/**

View File

@@ -139,6 +139,8 @@ public:
"Ledger must exist in database. Ledger sequence = {}",
ledgerSequence
);
if (!lgr)
return false;
publish(*lgr);
return true;
@@ -165,8 +167,8 @@ public:
// if the ledger closed over MAX_LEDGER_AGE_SECONDS ago, assume we are still catching up
// and don't publish
static constexpr std::uint32_t kMAX_LEDGER_AGE_SECONDS = 600;
if (age < kMAX_LEDGER_AGE_SECONDS) {
static constexpr std::uint32_t kMaxLedgerAgeSeconds = 600;
if (age < kMaxLedgerAgeSeconds) {
std::optional<ripple::Fees> fees =
data::synchronousAndRetryOnTimeout([&](auto yield) {
return backend_->fetchFees(lgrInfo.seq, yield);
@@ -244,9 +246,9 @@ public:
std::chrono::system_clock::now().time_since_epoch()
)
.count();
if (now < (kRIPPLE_EPOCH_START + closeTime))
if (now < (kRippleEpochStart + closeTime))
return 0;
return now - (kRIPPLE_EPOCH_START + closeTime);
return now - (kRippleEpochStart + closeTime);
}
/**

View File

@@ -83,8 +83,8 @@ Loader::onInitialLoadGotMoreObjects(
std::optional<std::string> lastKey
)
{
static constexpr std::size_t kLOG_STRIDE = 1000u;
static auto kINITIAL_LOAD_START_TIME = std::chrono::steady_clock::now();
static constexpr std::size_t kLogStride = 1000u;
static auto kInitialLoadStartTime = std::chrono::steady_clock::now();
try {
LOG(log_.trace()) << "On initial load: got more objects for seq " << seq
@@ -99,12 +99,12 @@ Loader::onInitialLoadGotMoreObjects(
initialLoadWrittenObjects_ += data.size();
++initialLoadWrites_;
if (initialLoadWrites_ % kLOG_STRIDE == 0u && initialLoadWrites_ != 0u) {
if (initialLoadWrites_ % kLogStride == 0u && initialLoadWrites_ != 0u) {
auto elapsedSinceStart = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - kINITIAL_LOAD_START_TIME
std::chrono::steady_clock::now() - kInitialLoadStartTime
);
auto elapsedSeconds =
elapsedSinceStart.count() / static_cast<double>(util::kMILLISECONDS_PER_SECOND);
elapsedSinceStart.count() / static_cast<double>(util::kMillisecondsPerSecond);
auto objectsPerSecond = elapsedSeconds > 0.0
? static_cast<double>(initialLoadWrittenObjects_) / elapsedSeconds
: 0.0;

View File

@@ -51,6 +51,8 @@ Monitor::notifySequenceLoaded(uint32_t seq)
lck->lastSeenMaxSeqInDb = std::max(seq, lck->lastSeenMaxSeqInDb);
lck->lastDbCheckTime = std::chrono::steady_clock::now();
}
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
repeatedTask_->invoke(); // force-invoke doWork immediately
};
@@ -110,6 +112,8 @@ Monitor::onNextSequence(uint32_t seq)
{
ASSERT(repeatedTask_.has_value(), "Ledger subscription without repeated task is a logic error");
LOG(log_.debug()) << "Notified about new sequence on the network: " << seq;
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
repeatedTask_->invoke(); // force-invoke immediately
}

View File

@@ -57,7 +57,7 @@ concept HasInitialObjectHook = requires(T p) {
};
template <typename T>
concept ContainsSpec = std::decay_t<T>::spec::kSPEC_TAG;
concept ContainsSpec = std::decay_t<T>::spec::kSpecTag;
template <typename T>
concept ContainsValidHook =

Some files were not shown because too many files have changed in this diff Show More