Skip to content

feat: adapt to eloqstore memory upload and add eloq_store_max_write_concurrency parameters#407

Merged
thweetkomputer merged 4 commits intomainfrom
eloqstore-memory-upload
Feb 12, 2026
Merged

feat: adapt to eloqstore memory upload and add eloq_store_max_write_concurrency parameters#407
thweetkomputer merged 4 commits intomainfrom
eloqstore-memory-upload

Conversation

@thweetkomputer
Copy link
Collaborator

@thweetkomputer thweetkomputer commented Feb 11, 2026

Here are some reminders before you submit the pull request

  • Add tests for the change
  • Document changes
  • Reference the link of issue using fixes eloqdb/tx_service#issue_id
  • Reference the link of RFC if exists
  • Pass ./mtr --suite=mono_main,mono_multi,mono_basic

Summary by CodeRabbit

  • New Features
    • New CLI/config option to cap EloqStore write concurrency.
    • Default max cloud concurrency lowered to 20.
    • Cloud-request thread count can be derived from CPU/core count when not explicitly set.
    • Startup may auto-adjust worker and thread counts when automatic CPU/core configuration is enabled.

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Warning

Rate limit exceeded

@thweetkomputer has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 7 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Adds new eloq_store_max_write_concurrency flag and INI wiring, extends EloqStoreConfig constructor to accept core_number, introduces cloud_request_threads computation (flag → INI → derived from core_number) and core-reservation logic that can reduce core_num and update runtime concurrency, and updates an eloqstore submodule reference and constructor call sites.

Changes

Cohort / File(s) Summary
EloqStore config & flags
store_handler/eloq_data_store_service/eloq_store_config.cpp, store_handler/eloq_data_store_service/eloq_store_config.h
Adds DEFINE_uint32(eloq_store_max_write_concurrency, ...); initializes eloqstore_configs_.max_write_concurrency from flag or INI; removes old max_upload_batch handling; extends constructor to accept core_number; computes cloud_request_threads when cloud_store_path is set (flag → INI → max(1, core_number/4)).
Core config & cloud-thread auto-config
core/include/data_substrate.h, core/src/data_substrate.cpp
Adds core_num_auto_config_ to CoreConfig; declares/uses flags eloq_store_cloud_store_path and eloq_store_cloud_request_threads; when EloqStore enabled, reads cloud_store_path and sets cloud_request_threads from flag/INI/derived value, may reserve CPUs by reducing core_num, updating bthread concurrency and eloq_store_worker_num, and logging adjustments.
Storage init & runtime adjustments
core/src/storage_init.cpp
Passes core_num into EloqStoreConfig constructor; after construction detects changed core_num and updates bthread_concurrency and eloq_store_worker_num via GFLAGS at startup.
EloqStore submodule & main usage
store_handler/eloq_data_store_service/eloqstore, store_handler/eloq_data_store_service/main.cpp
Updates eloqstore submodule reference; updates EloqStoreConfig call sites (adds placeholder core_number arg in main.cpp).

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Startup as "Startup"
participant CoreLoader as "LoadCoreAndNetworkConfig"
participant EloqConfig as "EloqStoreConfig"
participant Runtime as "Runtime (gflags / bthreads)"
Startup->>CoreLoader: begin startup/load config
CoreLoader->>CoreLoader: read flags & INI, detect EloqStore enabled\nread cloud_store_path & cloud_request_threads flag/INI
CoreLoader->>EloqConfig: construct with node_memory_mb, core_number
EloqConfig->>EloqConfig: set max_write_concurrency (flag vs INI)\ncompute cloud_request_threads (flag → INI → max(1, core_number/4))
EloqConfig-->>CoreLoader: return possibly adjusted core_number
CoreLoader->>Runtime: set bthread_concurrency / eloq_store_worker_num if core_num changed
Runtime-->>Startup: continue initialization with updated concurrency

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • liunyl
  • MrGuin

Poem

🐰 A flag hopped in, small and bright,
Cores counted under moonlit night,
Threads took places, INI sang too,
Stores and cores found a number true,
Hop — concurrency tuned anew! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description only contains the repository template checklist without any actual details. All items remain unchecked, indicating none of the required actions have been documented or completed. Fill in the PR description with actual implementation details, specify which tests were added, provide documentation, and reference the related issue/RFC if applicable.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: adding eloq_store_max_write_concurrency parameter and adapting to eloqstore memory upload functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch eloqstore-memory-upload

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@core/src/storage_init.cpp`:
- Around line 292-306: The conditional that compares original_core_num to
core_config_.core_num is dead code because EloqStoreConfig's constructor does
not modify core_config_.core_num; either implement the adjustment logic inside
EloqStoreConfig (e.g., update core_config_.core_num within the
EloqDS::EloqStoreConfig constructor when reserving threads for the cloud) so the
post-construction check can detect changes, or remove the entire block that
checks original_core_num and calls GFLAGS_NAMESPACE::SetCommandLineOption for
"bthread_concurrency" and "eloq_store_worker_num" to avoid confusing dead
branches; refer to EloqStoreConfig, core_config_.core_num, original_core_num,
bthread_concurrency, and eloq_store_worker_num to find the relevant code.

In `@store_handler/eloq_data_store_service/eloq_store_config.cpp`:
- Around line 267-272: The constructor EloqStoreConfig currently accepts
core_number_auto_config and a non-const core_number reference but never uses
them; either remove these parameters from the signature and update
declarations/usages (constructor in header and all call sites) or implement the
auto-config behavior: if core_number_auto_config is true compute the desired
core count (e.g., using hardware_concurrency or INIReader values), set
core_number (the out-parameter) and assign that value to core_config_.core_num
inside the EloqStoreConfig constructor so the caller can observe changes; ensure
the header signature, all call sites, and any related logic that reads
core_config_.core_num are updated consistently.
🧹 Nitpick comments (4)
core/include/data_substrate.h (1)

128-141: Inconsistent naming: trailing underscore on core_num_auto_config_ differs from sibling fields.

All other members of CoreConfig (e.g., core_num, enable_heap_defragment, enable_wal) omit the trailing underscore. Consider renaming to core_num_auto_config for consistency.

store_handler/eloq_data_store_service/eloq_store_config.cpp (1)

609-631: Duplicate cloud_request_threads computation with data_substrate.cpp.

The logic here (lines 609–631) to derive cloud_request_threads from flag → INI → core_number / 4 is nearly identical to the block in core/src/data_substrate.cpp (lines 732–791). The data_substrate version additionally reserves cores by reducing core_num, while this version only sets cloud_request_threads on the config struct.

This duplication means the derivation logic must be kept in sync in two places. Consider consolidating so the thread count is computed once and passed in, or having EloqStoreConfig be the single owner of this logic.

Also note: lines 597–602 already unconditionally set cloud_request_threads (via the standard flag/INI pattern), and then lines 609–631 immediately overwrite it when cloud_store_path is non-empty. The initial assignment on line 597 is wasted work in that case.

store_handler/eloq_data_store_service/main.cpp (1)

33-33: #include <thread> appears unused in this file.

No std::thread or std::thread::hardware_concurrency() usage is visible. If it was added only for the constructor signature change, it's not needed here.

core/src/data_substrate.cpp (1)

729-791: Core reservation logic is safe at boundary conditions but duplicates eloq_store_config.cpp.

The core_num > 1 guard on line 766 correctly prevents reducing core_num to zero, and the std::min on line 770–771 ensures the decrease never exceeds core_num - 1. The boundary behavior for small VCPU counts (1–3) is sound.

However, the cloud_request_threads derivation logic (flag → INI → core_num / 4) is duplicated between here and eloq_store_config.cpp lines 609–631. As noted in that file's review, consider consolidating.

Also note: on line 768, std::max<size_t>(1, cloud_request_threads) is redundant since cloud_request_threads > 0 is already guaranteed by the enclosing if on line 765.

update

eloq_store_max_write_concurrency=4

change parameter

update

fix

fmt

remove unused parameters

fix

fix

fix

fix

update

fix
@thweetkomputer thweetkomputer force-pushed the eloqstore-memory-upload branch from 33e08b4 to a25afaa Compare February 11, 2026 10:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@store_handler/eloq_data_store_service/eloq_store_config.cpp`:
- Around line 267-271: The constructor parameter uint32_t &core_number in
EloqStoreConfig::EloqStoreConfig is a non-const reference but never modified,
which misleads callers (and storage_init logic expects potential write-back);
either change the signature to const uint32_t& or uint32_t (pass-by-value) and
remove the dependent dead-code in storage_init, or add proper write-back inside
EloqStoreConfig::EloqStoreConfig to update the referenced core_number with the
CPU reservation decision made by the constructor so storage_init's later checks
observe the modified value; update callers/tests accordingly to match the chosen
approach.
🧹 Nitpick comments (3)
core/src/data_substrate.cpp (2)

730-787: Cloud thread reservation only applies when core_number is auto-configured.

This entire block lives inside the else branch (line 719) that only executes when core_number is not set via flag or INI. If a user explicitly sets core_number in the config but relies on default cloud_request_threads, no CPU reservation will occur. Is this intentional?

Additionally, the SetCommandLineOption calls on lines 777–782 are redundant — the same flags are unconditionally set to core_config_.core_num later at lines 877–878 and 889–890, and core_config_.core_num already holds the decreased value by then.

♻️ Remove redundant early SetCommandLineOption calls
                     if (decrease > 0)
                     {
                         core_config_.core_num -= decrease;
                         LOG(INFO) << "decrease core_number to "
                                   << core_config_.core_num
                                   << " to reserve cpu for eloqstore "
                                      "threads.";
-                        auto adjusted_core_num =
-                            std::to_string(core_config_.core_num);
-                        GFLAGS_NAMESPACE::SetCommandLineOption(
-                            "bthread_concurrency",
-                            adjusted_core_num.c_str());
-                        GFLAGS_NAMESPACE::SetCommandLineOption(
-                            "eloq_store_worker_num",
-                            adjusted_core_num.c_str());
                     }

Please confirm whether CPU reservation should also apply when core_number is explicitly set (via flag or INI) with cloud store enabled, or if the current auto-config-only behavior is by design.


762-767: reserved_cpu is always equal to cloud_request_threads here.

On line 762, the condition already guarantees cloud_request_threads > 0, so std::max<size_t>(1, cloud_request_threads) on line 764–765 is a no-op. Consider simplifying.

♻️ Simplify
-                    if (cloud_request_threads > 0 && core_config_.core_num > 1)
-                    {
-                        auto reserved_cpu =
-                            std::max<size_t>(1, cloud_request_threads);
-                        auto decrease = std::min<size_t>(
-                            reserved_cpu, core_config_.core_num - 1);
+                    if (cloud_request_threads > 0 && core_config_.core_num > 1)
+                    {
+                        auto decrease = std::min<size_t>(
+                            cloud_request_threads, core_config_.core_num - 1);
store_handler/eloq_data_store_service/eloq_store_config.cpp (1)

608-630: cloud_request_threads is set twice — second block fully overrides the first when cloud path is non-empty.

Lines 596–601 unconditionally set cloud_request_threads (flag → INI → flag-default). Then lines 608–630 completely re-determine it when cloud_store_path is non-empty. The only semantic difference is the fallback: 1 (flag default) vs max(1, core_number / 4).

Consider restructuring so the cloud-path-specific default is applied in a single pass to avoid confusion.

Also, the INI fallback on line 617 is 0 (via GetInteger(..., 0)) whereas the earlier read on line 601 falls back to FLAGS_eloq_store_cloud_request_threads (which is 1). If the INI key exists but holds an unparseable value, this inconsistency would yield different defaults depending on which code path ran last.

♻️ Consolidate cloud_request_threads logic
     eloqstore_configs_.cloud_request_threads =
         !CheckCommandLineFlagIsDefault("eloq_store_cloud_request_threads")
             ? FLAGS_eloq_store_cloud_request_threads
             : config_reader.GetInteger("store",
                                        "eloq_store_cloud_request_threads",
                                        FLAGS_eloq_store_cloud_request_threads);
+    // When cloud store is enabled and no explicit value was provided,
+    // scale cloud_request_threads with core count instead of using flag default.
+    if (!eloqstore_configs_.cloud_store_path.empty() &&
+        CheckCommandLineFlagIsDefault("eloq_store_cloud_request_threads") &&
+        !config_reader.HasValue("store", "eloq_store_cloud_request_threads"))
+    {
+        eloqstore_configs_.cloud_request_threads =
+            std::max<size_t>(1, core_number / 4);
+    }
-    if (!eloqstore_configs_.cloud_store_path.empty())
-    {
-        if (CheckCommandLineFlagIsDefault("eloq_store_cloud_request_threads"))
-        {
-            if (config_reader.HasValue("store",
-                                       "eloq_store_cloud_request_threads"))
-            {
-                eloqstore_configs_.cloud_request_threads =
-                    config_reader.GetInteger(
-                        "store", "eloq_store_cloud_request_threads", 0);
-            }
-            else
-            {
-                eloqstore_configs_.cloud_request_threads =
-                    std::max<size_t>(1, core_number / 4);
-            }
-        }
-        else
-        {
-            eloqstore_configs_.cloud_request_threads =
-                FLAGS_eloq_store_cloud_request_threads;
-        }
-    }

@thweetkomputer thweetkomputer merged commit aa2703c into main Feb 12, 2026
4 checks passed
@thweetkomputer thweetkomputer deleted the eloqstore-memory-upload branch February 12, 2026 02:34
@coderabbitai coderabbitai bot mentioned this pull request Mar 18, 2026
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants