Skip to content

system store - endpoints load from core instead of db #9150

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

alphaprinz
Copy link
Contributor

@alphaprinz alphaprinz commented Jul 20, 2025

Describe the Problem

Reduce db load spikes when all endpoints load from db simultaneously by having only core load from db and endpoints load from core instead.

Explain the Changes

  1. Introduce new RPC that allows endpoints to get system store from core.

Issues: Fixed #xxx / Gap #xxx

Testing Instructions:

  • Doc added/updated
  • Tests added

Summary by CodeRabbit

  • New Features

    • Added support for loading system store data from either a database or a core RPC source, with automatic selection based on environment.
    • Introduced a new API method to retrieve system store data without requiring system-level authentication.
  • Improvements

    • Enhanced system store loading logic for greater flexibility and reliability.
    • Provided a method to access recent in-memory database data for the system store.

Copy link

coderabbitai bot commented Jul 20, 2025

## Walkthrough

A new dual-source loading mechanism was introduced for the system store, allowing data to be loaded either from the database or via core RPC. Supporting API methods and exports were added, including a new `get_system_store` API endpoint and related server-side logic. The system store's initialization and loading logic were updated accordingly.

## Changes

| File(s)                                                                 | Change Summary                                                                                                                      |
|-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
| src/api/system_api.js                                                   | Added `get_system_store` API method with GET method and no system-level authentication required.                                    |
| src/endpoint/endpoint.js                                                | Modified call to `system_store.get_instance()` to include `{source: system_store.SOURCE.CORE}` as an argument for md_server.        |
| src/server/system_services/system_server.js                             | Added and exported async `get_system_store` function returning recent DB data as a buffer keyed by `RPC_BUFFERS`.                   |
| src/server/system_services/system_store.js                              | Enhanced `SystemStore` to support dual-source loading (DB/CORE), added `SOURCE` constant, new methods, and conditional logic.       |
| src/util/postgres_client.js                                             | Added export for `decode_json` function.                                                                                            |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant API as system_api.js
    participant Server as system_server.js
    participant Store as system_store.js
    participant DB

    Client->>API: GET /get_system_store
    API->>Server: get_system_store()
    Server->>Store: recent_db_data()
    Store->>Store: Acquire semaphore lock
    Store->>DB: (If source is DB) Fetch latest data
    Store-->>Server: Return recent DB data
    Server-->>API: Return data buffer
    API-->>Client: Respond with system store data

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested labels

size/S

Suggested reviewers

  • tangledbytes
  • dannyzaken

<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!WARNING]
> There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
> 
> <details>
> <summary>🔧 ESLint</summary>
> 
> > If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.
> 
> npm error Exit handler never called!
> npm error This is an error with npm itself. Please report this error at:
> npm error   <https://github.com/npm/cli/issues>
> npm error A complete log of this run can be found in: /.npm/_logs/2025-07-24T11_57_42_824Z-debug-0.log
> 
> 
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->

<!-- announcements_start -->

> [!NOTE]
> <details open="true">
> <summary>⚡️ Unit Test Generation is now available in beta!</summary>
> 
> Learn more [here](https://docs.coderabbit.ai/finishing-touches/unit-test-generation), or try it out under "Finishing Touches" below.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d880a87430350da5733d3ca0c6aa1fd0f5ee33f6 and 766302a61a550aef4b63b4a02da18ed10d3ec711.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `src/api/system_api.js` (1 hunks)
* `src/endpoint/endpoint.js` (1 hunks)
* `src/server/system_services/system_server.js` (3 hunks)
* `src/server/system_services/system_store.js` (8 hunks)
* `src/util/postgres_client.js` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* src/util/postgres_client.js

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (4)</summary>

* src/server/system_services/system_server.js
* src/api/system_api.js
* src/endpoint/endpoint.js
* src/server/system_services/system_store.js

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)</summary>

* GitHub Check: Build Noobaa Image
* GitHub Check: run-jest-unit-tests
* GitHub Check: run-package-lock-validation

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings
<details>
<summary>🧪 Generate unit tests</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Create PR with unit tests
- [ ] <!-- {"checkboxId": "07f1e7d6-8a8e-4e23-9900-8731c2c87f58", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Post copyable unit tests in a comment

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=noobaa/noobaa-core&utm_content=9150):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai generate unit tests` to generate unit tests for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

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: 6

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24e11b7 and d880a87.

📒 Files selected for processing (5)
  • src/api/system_api.js (1 hunks)
  • src/endpoint/endpoint.js (1 hunks)
  • src/server/system_services/system_server.js (3 hunks)
  • src/server/system_services/system_store.js (8 hunks)
  • src/util/postgres_client.js (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/server/system_services/system_server.js (1)
src/server/system_services/system_store.js (2)
  • require (41-41)
  • require (43-43)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: warp-tests / Warp Tests
  • GitHub Check: ceph-s3-tests / Ceph S3 Tests
  • GitHub Check: run-unit-tests / Unit Tests
🔇 Additional comments (2)
src/util/postgres_client.js (1)

1954-1954: LGTM! Clean export addition for system store RPC support.

This export enables the decode_json function to be used by the system store module for processing JSON data received via RPC from the core system, which aligns perfectly with the PR objectives to reduce database load by centralizing data access.

src/server/system_services/system_store.js (1)

545-565: Review _read_new_data_from_core: adjust error handling and confirm no circular RPC

We’ve confirmed that passing this.data into _read_new_data_from_core is correct, so no change is needed there. However, the method currently has no guard against RPC failures, and it’s worth double-checking that the get_system_store handler doesn’t itself call back into system_store.load() (which would create a circular dependency).

Please address the following:

• Remove the parameter-fix suggestion at line 438—this.data is already the new SystemStoreData instance.
• Add a try/catch around the RPC call to surface failures clearly:

 async _read_new_data_from_core(target) {
     dbg.log3("_read_new_data_from_core begins");
+      try {
         const res = await server_rpc.client.system.get_system_store();
         const ss = JSON.parse(res[RPC_BUFFERS].data.toString());
         dbg.log3("_read_new_data_from_core new system store", ss);
         for (const key of Object.keys(ss)) {
           …  
         }
+      } catch (err) {
+          dbg.error("Failed to read system store from core:", err);
+          throw err;
+      }
 }

• Manually verify that the get_system_store RPC handler (in your core/service code) doesn’t invoke system_store.load() or _read_new_data_from_core, to avoid circular calls.

Comment on lines +464 to 469
get_system_store: {
method: 'GET',
auth: {
system: false
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add reply schema to define the expected response format.

The new get_system_store API method lacks a reply schema, which makes it unclear what data structure this endpoint returns. This could lead to integration issues and runtime errors.

Consider adding a reply schema similar to other methods in this file:

 get_system_store: {
     method: 'GET',
+    reply: {
+        type: 'object',
+        // Define the structure of system store data
+        properties: {
+            // Add expected properties here
+        }
+    },
     auth: {
         system: false
     }
 }

Alternatively, if the response is a binary buffer or serialized data, specify the appropriate type (e.g., type: 'string' for base64-encoded data).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
get_system_store: {
method: 'GET',
auth: {
system: false
}
}
get_system_store: {
method: 'GET',
reply: {
type: 'object',
// Define the structure of system store data
properties: {
// Add expected properties here
}
},
auth: {
system: false
}
}
🤖 Prompt for AI Agents
In src/api/system_api.js around lines 464 to 469, the get_system_store method is
missing a reply schema that defines the expected response format. To fix this,
add a reply schema property to the method specifying the structure of the
returned data, similar to other API methods in this file. If the response is a
JSON object, define its properties and types; if it returns binary or serialized
data, specify the appropriate type such as 'string' for base64-encoded content.

Comment on lines 173 to +174
// this point (and should not kill the process);
system_store.get_instance().load();
system_store.get_instance({source: system_store.SOURCE.CORE}).load();
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider handling the promise rejection to avoid unhandled promise warnings.

The comment states that errors are not relevant, but the .load() promise might still reject and cause unhandled promise warnings. Consider adding a .catch() handler.

-                system_store.get_instance({source: system_store.SOURCE.CORE}).load();
+                system_store.get_instance({source: system_store.SOURCE.CORE}).load().catch(err => {
+                    dbg.warn('Failed to load system store from core:', err);
+                });

Also, verify that this change applies to all endpoint scenarios, not just when LOCAL_MD_SERVER is true.


🏁 Script executed:

#!/bin/bash
# Description: Check if there are other places where endpoints might need to use CORE source
# Look for other system_store.get_instance() calls in endpoint-related files

rg -A 5 'system_store\.get_instance\(' --glob 'src/endpoint/**/*.js'

Length of output: 902


Handle unhandled promise for system_store.load()

The .load() call returns a promise and may reject, triggering unhandled‐promise warnings. Add a .catch() handler to swallow or log errors as intended.

  • File: src/endpoint/endpoint.js
    Lines ~173–174 in the LOCAL_MD_SERVER block

Suggested diff:

-                system_store.get_instance({source: system_store.SOURCE.CORE}).load();
+                system_store.get_instance({source: system_store.SOURCE.CORE})
+                    .load()
+                    .catch(err => {
+                        dbg.warn('Failed to load system store from core:', err);
+                    });

I ran a search for other system_store.get_instance( calls under src/endpoint/ and found only this one use of .load() with CORE—no additional endpoints require the same change.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// this point (and should not kill the process);
system_store.get_instance().load();
system_store.get_instance({source: system_store.SOURCE.CORE}).load();
// this point (and should not kill the process);
system_store.get_instance({source: system_store.SOURCE.CORE})
.load()
.catch(err => {
dbg.warn('Failed to load system store from core:', err);
});
🤖 Prompt for AI Agents
In src/endpoint/endpoint.js around lines 173 to 174, the call to
system_store.get_instance(...).load() returns a promise that may reject, causing
unhandled promise warnings. Fix this by adding a .catch() handler to the load()
call to handle any rejection, either by logging the error or swallowing it as
appropriate to prevent unhandled promise rejections.

Comment on lines +306 to +310
async function get_system_store() {
return {
[RPC_BUFFERS]: {data: Buffer.from(JSON.stringify(await system_store.recent_db_data()))},
};
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Add error handling and consider security implications of exposing system store data.

This function exposes the entire system store data without any visible authorization checks or data filtering. Additionally, it lacks error handling.

Consider the following improvements:

  1. Add error handling:
 async function get_system_store() {
+    try {
         return {
             [RPC_BUFFERS]: {data: Buffer.from(JSON.stringify(await system_store.recent_db_data()))},
         };
+    } catch (err) {
+        dbg.error('Failed to get system store data:', err);
+        throw new RpcError('INTERNAL', 'Failed to retrieve system store data');
+    }
 }
  1. Verify authorization requirements:

  2. Consider implementing data filtering to avoid exposing sensitive information like credentials or keys.

  3. For large datasets, consider implementing pagination or streaming to avoid memory issues with JSON serialization.


🏁 Script executed:

#!/bin/bash
# Description: Check how this RPC method is exposed and what authorization it requires
# Look for the API definition and any auth requirements

# Search for get_system_store in API definitions
rg -A 10 'get_system_store' src/api/

# Check if there are any auth decorators or middleware
ast-grep --pattern 'get_system_store: {
  $$$
}'

Length of output: 509


Enforce authorization and add error handling in get_system_store

The get_system_store RPC is currently exposed via HTTP GET with auth: { system: false } and no error handling or data filtering. This allows unauthenticated clients to fetch the entire store and may crash the server on large payloads.

Please address the following:

  • Require system-level auth
    In src/api/system_api.js, change

    get_system_store: {
        method: 'GET',
        auth: { system: false },
    }

    to

    auth: { system: true }

    or integrate your authorization middleware so only permitted clients can call this RPC.

  • Add error handling
    Wrap the data fetch/serialize in try/catch and return a proper RPC error:

     async function get_system_store() {
  • try {
    return {
    [RPC_BUFFERS]: {
    data: Buffer.from(JSON.stringify(await system_store.recent_db_data())),
    },
    };
  • } catch (err) {
  •  dbg.error('get_system_store failed:', err);
    
  •  throw new RpcError('INTERNAL', 'Unable to retrieve system store data');
    
  • }
    }

- **Filter sensitive data**  
Only include non-sensitive fields in the payload (e.g. omit credentials, tokens, or PII).

- **Handle large datasets**  
Consider implementing pagination or streaming (e.g. chunked responses) to avoid high memory/CPU usage.

<details>
<summary>🤖 Prompt for AI Agents</summary>

In src/server/system_services/system_server.js around lines 306 to 310 and in
src/api/system_api.js where get_system_store is defined, update the auth setting
to require system-level authorization by setting auth: { system: true }. In the
get_system_store function, wrap the data retrieval and serialization in a
try/catch block to handle errors gracefully and return an appropriate RPC error
on failure. Modify the data returned to exclude sensitive information such as
credentials, tokens, or PII by filtering the fields before serialization. To
handle large datasets, implement pagination or chunked responses to limit memory
and CPU usage during data transmission.


</details>

<!-- fingerprinting:phantom:medusa:lion -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +360 to +361
this.source = (process.env.HOSTNAME && process.env.HOSTNAME.indexOf("endpoint") === -1) ? SOURCE.DB : SOURCE.CORE;
dbg.log0("system store source is", this.source);
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Improve the source determination logic for better clarity and maintainability.

The current logic for determining the source relies on checking if HOSTNAME contains "endpoint", which could be fragile and unclear.

Consider using a more explicit approach:

-        this.source = (process.env.HOSTNAME && process.env.HOSTNAME.indexOf("endpoint") === -1) ? SOURCE.DB : SOURCE.CORE;
+        // Explicitly determine source based on process type
+        // Endpoints should load from CORE to reduce DB load, others use DB directly
+        const isEndpointProcess = process.env.HOSTNAME && process.env.HOSTNAME.includes("endpoint");
+        this.source = options.source || (isEndpointProcess ? SOURCE.CORE : SOURCE.DB);

This also respects the options.source parameter that's already being passed in some cases.


🏁 Script executed:

#!/bin/bash
# Description: Verify how HOSTNAME is set for different process types
# Check for HOSTNAME usage patterns

# Search for HOSTNAME environment variable usage
rg 'process\.env\.HOSTNAME' --type js

# Look for how different services set their process names/titles
rg 'process\.title\s*=' --type js

Length of output: 325


🏁 Script executed:

#!/bin/bash
# Search for options.source usage
rg 'options\.source' -n src

# Locate the SystemStore class and its constructor around the source determination logic
rg -n 'class SystemStore' -A20 -B10 src/server/system_services/system_store.js

Length of output: 2118


Clarify and Simplify Source Determination

Extract a clear isEndpoint boolean and use it (or process.title) rather than an inline ternary on HOSTNAME. Optionally add support for a future options.source override.

• File: src/server/system_services/system_store.js (around lines 360–361)
• Replace this block:

-        this.source = (process.env.HOSTNAME && process.env.HOSTNAME.indexOf("endpoint") === -1) ? SOURCE.DB : SOURCE.CORE;
+        // Determine if this is the endpoint process by hostname
+        const hostName = process.env.HOSTNAME || '';
+        const isEndpoint = hostName.includes('endpoint');
+        this.source = isEndpoint ? SOURCE.CORE : SOURCE.DB;

• (Optional) If you want to honor a passed–in override:

 constructor(options = {}) {
   // …
+  if (options.source) {
+      this.source = options.source;
+  } else {
+      const hostName = process.env.HOSTNAME || '';
+      const isEndpoint = hostName.includes('endpoint');
+      this.source = isEndpoint ? SOURCE.CORE : SOURCE.DB;
+  }

• Alternatively, detect via process.title (set in src/endpoint/endpoint.js):

const isEndpoint = process.title === config.ENDPOINT_PROCESS_TITLE;
this.source = isEndpoint ? SOURCE.CORE : SOURCE.DB;

This makes the intent explicit and easier to maintain.

🤖 Prompt for AI Agents
In src/server/system_services/system_store.js around lines 360 to 361, replace
the inline ternary that sets this.source based on process.env.HOSTNAME with a
clearer approach: first define a boolean isEndpoint by checking if the hostname
includes "endpoint" or by comparing process.title to a known endpoint process
title, then set this.source to SOURCE.CORE if isEndpoint is true or SOURCE.DB
otherwise. Optionally, add support for an override via options.source if
applicable. This refactor clarifies intent and improves maintainability.

Comment on lines +475 to +478
//return the latest copy of in-memory data
async recent_db_data() {
return this._load_serial.surround(async () => this.old_db_data);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle the case when recent_db_data is called on a CORE source instance.

This method returns old_db_data which is only populated when the source is DB. For CORE source instances, this will return undefined.

Consider this safer implementation:

     //return the latest copy of in-memory data
     async recent_db_data() {
-        return this._load_serial.surround(async () => this.old_db_data);
+        return this._load_serial.surround(async () => {
+            if (this.source === SOURCE.CORE) {
+                throw new RpcError('BAD_REQUEST', 'recent_db_data is not available for CORE source');
+            }
+            return this.old_db_data || {};
+        });
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//return the latest copy of in-memory data
async recent_db_data() {
return this._load_serial.surround(async () => this.old_db_data);
}
//return the latest copy of in-memory data
async recent_db_data() {
return this._load_serial.surround(async () => {
if (this.source === SOURCE.CORE) {
throw new RpcError(
'BAD_REQUEST',
'recent_db_data is not available for CORE source'
);
}
return this.old_db_data || {};
});
}
🤖 Prompt for AI Agents
In src/server/system_services/system_store.js around lines 475 to 478, the
recent_db_data method returns old_db_data which is undefined for CORE source
instances. Modify the method to check if the instance is a CORE source and
handle that case safely, for example by returning null or an empty object
instead of old_db_data, to avoid returning undefined.

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: 6

🧹 Nitpick comments (2)
src/util/postgres_client.js (1)

1954-1954: Exporting decode_json widens the public API – consider symmetry & documentation

  1. This is the first time an internal helper is exposed from this module. Down-stream code may now rely on the exact traversal semantics (wrapper unwrapping, recursive decode, etc.), making future refactors harder.

  2. encode_json is still internal. External callers that use decode_json almost always need the reverse operation. Exporting only one direction invites accidental misuse or duplicated logic elsewhere.

  3. decode_json silently unwraps SensitiveString, which leaks plain-text secrets to any caller. If that’s intentional, call-sites should at least opt-in explicitly or a comment should warn about it.

Action:

 exports.PostgresClient = PostgresClient;
 exports.instance = PostgresClient.instance;
+// NOTE: exporting both helpers keeps the API symmetrical and explicit.
+exports.encode_json = encode_json;
 exports.decode_json = decode_json;

…and add JSDoc explaining the security implication.

src/server/system_services/system_server.js (1)

306-310: Consider performance implications for large system stores

For systems with many buckets, accounts, or other entities, the system store data could be quite large. Serializing and buffering the entire dataset might impact memory usage and RPC transfer times.

Consider implementing:

  1. Data size limits or pagination
  2. Compression before sending over RPC
  3. Monitoring the size of data being transferred
  4. Caching mechanism to avoid repeated serialization
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24e11b7 and d880a87.

📒 Files selected for processing (5)
  • src/api/system_api.js (1 hunks)
  • src/endpoint/endpoint.js (1 hunks)
  • src/server/system_services/system_server.js (3 hunks)
  • src/server/system_services/system_store.js (8 hunks)
  • src/util/postgres_client.js (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ceph-s3-tests / Ceph S3 Tests
🔇 Additional comments (2)
src/endpoint/endpoint.js (1)

174-174: Approved – SOURCE.CORE is properly defined

Verified in src/server/system_services/system_store.js that the SOURCE enum includes

CORE: 'CORE',

and is exported (exports.SOURCE = SOURCE). No further action needed.

src/server/system_services/system_store.js (1)

360-361: Improve source selection logic robustness

The current logic for determining the source has potential issues:

  1. It assumes endpoints have "endpoint" in their hostname
  2. The logic is inverted - it should check if hostname contains "endpoint" to set source to CORE

The condition should be:

-this.source = (process.env.HOSTNAME && process.env.HOSTNAME.indexOf("endpoint") === -1) ? SOURCE.DB : SOURCE.CORE;
+this.source = (process.env.HOSTNAME && process.env.HOSTNAME.indexOf("endpoint") !== -1) ? SOURCE.CORE : SOURCE.DB;

Additionally, consider making this more configurable:

+const source_override = process.env.SYSTEM_STORE_SOURCE;
+this.source = source_override || ((process.env.HOSTNAME && process.env.HOSTNAME.indexOf("endpoint") !== -1) ? SOURCE.CORE : SOURCE.DB);

Likely an incorrect or invalid review comment.

Comment on lines +464 to 469
get_system_store: {
method: 'GET',
auth: {
system: false
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add reply schema and documentation for the new API method.

The new get_system_store API method is missing essential documentation and schema definition:

  1. Missing reply schema: All other methods in this API define a proper reply schema for validation and documentation purposes.
  2. Missing documentation: The doc field should describe the purpose of this endpoint.
  3. Verify authentication requirements: Confirm that system: false is the correct authentication level for this endpoint.
 get_system_store: {
+    doc: 'Get system store data from core',
     method: 'GET',
+    reply: {
+        type: 'object',
+        // Define the expected structure of system store data
+        additionalProperties: true
+    },
     auth: {
         system: false
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
get_system_store: {
method: 'GET',
auth: {
system: false
}
}
get_system_store: {
doc: 'Get system store data from core',
method: 'GET',
reply: {
type: 'object',
// Define the expected structure of system store data
additionalProperties: true
},
auth: {
system: false
}
}
🤖 Prompt for AI Agents
In src/api/system_api.js around lines 464 to 469, the get_system_store API
method lacks a reply schema and documentation. Add a reply schema that defines
the expected response structure for validation and documentation. Include a doc
field describing the endpoint's purpose clearly. Also, review and confirm if the
auth setting system: false is appropriate for this method's security
requirements, adjusting if necessary.

Comment on lines +306 to +310
async function get_system_store() {
return {
[RPC_BUFFERS]: {data: Buffer.from(JSON.stringify(await system_store.recent_db_data()))},
};
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for potential failures

The function should handle potential errors from recent_db_data() or JSON.stringify() operations to prevent unhandled exceptions.

Consider wrapping the operations in a try-catch block:

 async function get_system_store() {
+    try {
         return {
             [RPC_BUFFERS]: {data: Buffer.from(JSON.stringify(await system_store.recent_db_data()))},
         };
+    } catch (err) {
+        dbg.error('get_system_store: Failed to get system store data', err);
+        throw new RpcError('INTERNAL_ERROR', 'Failed to retrieve system store data');
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function get_system_store() {
return {
[RPC_BUFFERS]: {data: Buffer.from(JSON.stringify(await system_store.recent_db_data()))},
};
}
async function get_system_store() {
try {
return {
[RPC_BUFFERS]: {data: Buffer.from(JSON.stringify(await system_store.recent_db_data()))},
};
} catch (err) {
dbg.error('get_system_store: Failed to get system store data', err);
throw new RpcError('INTERNAL_ERROR', 'Failed to retrieve system store data');
}
}
🤖 Prompt for AI Agents
In src/server/system_services/system_server.js around lines 306 to 310, the
async function get_system_store does not handle errors that may occur during the
call to recent_db_data() or the JSON.stringify operation. To fix this, wrap the
entire operation inside a try-catch block, returning a meaningful error or
fallback value in the catch block to prevent unhandled exceptions and ensure the
function handles failures gracefully.

Comment on lines +475 to +478
//return the latest copy of in-memory data
async recent_db_data() {
return this._load_serial.surround(async () => this.old_db_data);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle undefined old_db_data when source is CORE

When the source is CORE, old_db_data will be undefined, which could cause issues in get_system_store().

 //return the latest copy of in-memory data
 async recent_db_data() {
-    return this._load_serial.surround(async () => this.old_db_data);
+    return this._load_serial.surround(async () => {
+        if (this.source !== SOURCE.DB) {
+            throw new RpcError('BAD_REQUEST', 'recent_db_data is only available when source is DB');
+        }
+        return this.old_db_data || {};
+    });
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//return the latest copy of in-memory data
async recent_db_data() {
return this._load_serial.surround(async () => this.old_db_data);
}
//return the latest copy of in-memory data
async recent_db_data() {
return this._load_serial.surround(async () => {
if (this.source !== SOURCE.DB) {
throw new RpcError('BAD_REQUEST', 'recent_db_data is only available when source is DB');
}
return this.old_db_data || {};
});
}
🤖 Prompt for AI Agents
In src/server/system_services/system_store.js around lines 475 to 478, the
method recent_db_data returns old_db_data which can be undefined when the source
is CORE, potentially causing issues in get_system_store(). Modify recent_db_data
to check if old_db_data is undefined and handle that case appropriately, such as
returning a default value or throwing a clear error, to prevent downstream
errors.

Comment on lines +545 to +565
async _read_new_data_from_core(target) {
dbg.log3("_read_new_data_from_core begins");
const res = await server_rpc.client.system.get_system_store();
const ss = JSON.parse(res[RPC_BUFFERS].data.toString());
dbg.log3("_read_new_data_from_core new system store", ss);
for (const key of Object.keys(ss)) {
const collection = COLLECTIONS_BY_NAME[key];
if (collection) {
target[key] = [];
_.each(ss[key], item => {
//these two lines will transform string values into appropriately typed objects
//(SensitiveString, ObjectId) according to schema
const after = decode_json(collection.schema, item);
db_client.instance().validate(key, after);
target[key].push(after);
});
} else {
target[key] = ss[key];
}
}
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Monitor RPC data transfer and implement operational safeguards

Since endpoints will now fetch system store data via RPC from core, consider implementing:

  1. Metrics to monitor the frequency and size of these RPC calls
  2. Rate limiting to prevent endpoints from overwhelming the core
  3. Circuit breaker pattern for RPC failures
  4. Alerts for unusually large data transfers

Let me verify if there are any existing rate limiting or monitoring mechanisms:


🏁 Script executed:

#!/bin/bash
# Search for rate limiting or monitoring in RPC client code
rg -A 5 "rate.*limit|throttle|circuit.*breaker" --glob "src/rpc/**/*.js"

# Check if there are any metrics collection for RPC calls
rg -A 5 "metrics|monitor|stats.*rpc" --glob "src/rpc/**/*.js"

Length of output: 138


Implement RPC Monitoring, Rate Limiting, and Resilience Patterns

No existing rate-limit, metrics, or circuit-breaker logic was found around your RPC client (verification via rg returned no matches), so let’s add operational safeguards:

• In src/server/system_services/system_store.js (around the _read_new_data_from_core call at lines 545–565):
– Instrument a counter and histogram (e.g. Prometheus) for calls to server_rpc.client.system.get_system_store() (call count, payload size, latency).
– Emit alerts if payload size or latency exceeds thresholds.

• In your RPC client layer (e.g. src/rpc/client/*.js):
– Implement rate limiting or token bucket to cap calls per second.
– Wrap the get_system_store invocation in a circuit-breaker (e.g. with a library like opossum) to fail fast on repeated errors.

• Add configuration knobs for thresholds and integrate with your observability stack (alerts, dashboards).

These changes will help you detect abnormal patterns, protect the core from overload, and degrade gracefully on failures.

🤖 Prompt for AI Agents
In src/server/system_services/system_store.js around lines 545 to 565, add
Prometheus metrics instrumentation for the call to
server_rpc.client.system.get_system_store(), including a counter for call count,
a histogram for payload size and latency, and emit alerts if thresholds are
exceeded. Additionally, in the RPC client layer (e.g., src/rpc/client/*.js),
implement rate limiting (such as a token bucket) to cap calls per second and
wrap the get_system_store call in a circuit breaker (using a library like
opossum) to fail fast on repeated errors. Add configuration options for these
thresholds and integrate the metrics and alerts with the observability stack for
monitoring and graceful degradation.

⚠️ Potential issue

Add comprehensive error handling and improve validation

The method needs error handling for RPC calls and JSON parsing. Also, validation should happen before data transformation.

 async _read_new_data_from_core(target) {
     dbg.log3("_read_new_data_from_core begins");
+    try {
         const res = await server_rpc.client.system.get_system_store();
+        if (!res || !res[RPC_BUFFERS] || !res[RPC_BUFFERS].data) {
+            throw new Error('Invalid response from core system store');
+        }
         const ss = JSON.parse(res[RPC_BUFFERS].data.toString());
         dbg.log3("_read_new_data_from_core new system store", ss);
         for (const key of Object.keys(ss)) {
             const collection = COLLECTIONS_BY_NAME[key];
             if (collection) {
                 target[key] = [];
                 _.each(ss[key], item => {
+                    // Validate before transformation
+                    db_client.instance().validate(key, item, 'warn');
                     //these two lines will transform string values into appropriately typed objects
                     //(SensitiveString, ObjectId) according to schema
                     const after = decode_json(collection.schema, item);
-                    db_client.instance().validate(key, after);
+                    // Validate again after transformation to ensure correctness
+                    db_client.instance().validate(key, after, 'error');
                     target[key].push(after);
                 });
             } else {
                 target[key] = ss[key];
             }
         }
+    } catch (err) {
+        dbg.error('_read_new_data_from_core: Failed to read data from core', err);
+        throw new RpcError('INTERNAL_ERROR', `Failed to load system store from core: ${err.message}`);
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async _read_new_data_from_core(target) {
dbg.log3("_read_new_data_from_core begins");
const res = await server_rpc.client.system.get_system_store();
const ss = JSON.parse(res[RPC_BUFFERS].data.toString());
dbg.log3("_read_new_data_from_core new system store", ss);
for (const key of Object.keys(ss)) {
const collection = COLLECTIONS_BY_NAME[key];
if (collection) {
target[key] = [];
_.each(ss[key], item => {
//these two lines will transform string values into appropriately typed objects
//(SensitiveString, ObjectId) according to schema
const after = decode_json(collection.schema, item);
db_client.instance().validate(key, after);
target[key].push(after);
});
} else {
target[key] = ss[key];
}
}
}
async _read_new_data_from_core(target) {
dbg.log3("_read_new_data_from_core begins");
try {
const res = await server_rpc.client.system.get_system_store();
if (!res || !res[RPC_BUFFERS] || !res[RPC_BUFFERS].data) {
throw new Error('Invalid response from core system store');
}
const ss = JSON.parse(res[RPC_BUFFERS].data.toString());
dbg.log3("_read_new_data_from_core new system store", ss);
for (const key of Object.keys(ss)) {
const collection = COLLECTIONS_BY_NAME[key];
if (collection) {
target[key] = [];
_.each(ss[key], item => {
// Validate before transformation
db_client.instance().validate(key, item, 'warn');
// these two lines will transform string values into appropriately typed objects
// (SensitiveString, ObjectId) according to schema
const after = decode_json(collection.schema, item);
// Validate again after transformation to ensure correctness
db_client.instance().validate(key, after, 'error');
target[key].push(after);
});
} else {
target[key] = ss[key];
}
}
} catch (err) {
dbg.error('_read_new_data_from_core: Failed to read data from core', err);
throw new RpcError('INTERNAL_ERROR', `Failed to load system store from core: ${err.message}`);
}
}
🤖 Prompt for AI Agents
In src/server/system_services/system_store.js around lines 545 to 565, add
try-catch blocks to handle errors from the RPC call and JSON parsing to prevent
crashes. Move the validation step to occur before the decode_json transformation
to ensure data integrity early. Log or handle any errors appropriately within
the catch block to maintain robustness.

@alphaprinz alphaprinz force-pushed the system_store_phase2 branch from d880a87 to 766302a Compare July 24, 2025 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant