Skip to content

NSFS | Improve list objects performance on top of NS FS (PR 2/3) #8422

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

naveenpaul1
Copy link
Contributor

@naveenpaul1 naveenpaul1 commented Sep 30, 2024

Explain the changes

  1. This is Second PR for listing unordered objects.
  2. This PR contains changes in list_object(), TellDir value is passed to next list object result and same value is used to seekdir dir location.
  3. Global flag is added in config for controlling bucket list flow.
    NB : New parameter next_pos added to API list_objects to pass the seek position. I tried to pass this along with next_marker as a object but Ceph test failed when comparing next_marker.

Issues: Fixed #xxx / Gap #xxx

  1. Improve list objects performance on top of NS FS #6615

Testing Instructions:

  1. Run ListObject API after enabling global property ALLOW_NSFS_UNSORTED_OBJECTS_LIST, Result should retun with unsorted list.

closed PR : #7983

  • Doc added/updated
  • Tests added

Summary by CodeRabbit

  • New Features

    • Added support for unsorted object listing in NamespaceFS, including a new configuration flag to enable or disable this mode.
    • Introduced a new class for managing key markers and directory positions to support advanced pagination in unsorted listings.
    • API methods for listing objects and versions now accept an optional parameter to specify listing type.
  • Bug Fixes

    • Ensured that the listing type parameter is properly forwarded in relevant API calls.
  • Tests

    • Added comprehensive unit tests for unsorted object listing, directory reading, and pagination.
    • Centralized dummy SDK creation in test utilities and updated existing tests to use the shared utility.
    • Removed outdated unit tests for legacy directory listing logic.
  • Chores

    • Adjusted debug logging verbosity for directory operations.

@naveenpaul1 naveenpaul1 closed this Oct 9, 2024
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch from 2c43a85 to 4c41484 Compare October 9, 2024 04:17
@naveenpaul1 naveenpaul1 reopened this Oct 9, 2024
@naveenpaul1 naveenpaul1 marked this pull request as draft October 9, 2024 04:35
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch from 63851b5 to 2fdead0 Compare October 9, 2024 05:22
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch 4 times, most recently from 51cec93 to 77fc48b Compare October 16, 2024 12:47
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch from 8034ed2 to 6b417cd Compare October 17, 2024 09:41
@naveenpaul1 naveenpaul1 marked this pull request as ready for review October 17, 2024 10:10
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch 4 times, most recently from b2f5de0 to de2f83b Compare December 3, 2024 07:00
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch from de2f83b to c973335 Compare January 23, 2025 04:39
@naveenpaul1 naveenpaul1 force-pushed the new_nsfs_list_objects_2 branch from c973335 to d8b024e Compare January 23, 2025 06:34
Copy link

This PR had no activity for too long - it will now be labeled stale. Update it to prevent it from getting closed.

Copy link

This PR had no activity for too long - it will now be labeled stale. Update it to prevent it from getting closed.

@github-actions github-actions bot added the Stale label Jul 23, 2025
Copy link

coderabbitai bot commented Jul 23, 2025

Walkthrough

A new unsorted listing mode for NamespaceFS object listings has been introduced, controlled by a configuration flag and an API parameter. This includes a new KeyMarkerFS class for managing directory positions, changes to listing logic and result formatting, and comprehensive new unit tests. Related test utilities and imports were refactored.

Changes

File(s) Change Summary
config.js Added config flag NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED (default: false).
src/api/object_api.js Added optional list_type string parameter to list_objects and list_object_versions schemas.
src/endpoint/s3/ops/s3_get_bucket.js Forwards list_type to list_objects method.
src/native/fs/fs_napi.cpp Changed debug log level in TellDir::OnOK() from DBG0 to DBG1.
src/sdk/keymarker_fs.js Introduced new KeyMarkerFS class for directory marker management.
src/sdk/namespace_fs.js Added support for unsorted listing, integrated KeyMarkerFS, refactored listing and result logic, handled list_type parameter.
src/test/system_tests/test_utils.js Added and exported make_dummy_object_sdk utility function.
src/test/unit_tests/jest_tests/test_list_object.test.js Deleted Jest unit test suite for directory listing/telldir/seekdir.
src/test/unit_tests/jest_tests/test_unsort_list_object.test.js Added comprehensive Jest tests for unsorted listing and pagination.
src/test/unit_tests/test_namespace_fs.js, src/test_unit_tests/test_namespace_fs_mpu.js Refactored to import make_dummy_object_sdk from test_utils, removed local definitions.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant S3_Endpoint
    participant NamespaceFS
    participant KeyMarkerFS

    Client->>API: list_objects({list_type})
    API->>S3_Endpoint: list_objects({list_type})
    S3_Endpoint->>NamespaceFS: _list_objects(params, object_sdk, list_versions)
    NamespaceFS->>KeyMarkerFS: (if list_type == "2") parse marker, manage positions
    NamespaceFS-->>NamespaceFS: Perform sorted or unsorted listing
    NamespaceFS->>NamespaceFS: prepare_result(..., list_type)
    NamespaceFS->>S3_Endpoint: results
    S3_Endpoint->>API: results
    API->>Client: results
Loading

Estimated code review effort

4 (~90 minutes)

Suggested reviewers

  • romayalon
  • liranmauda

Poem

A rabbit hopped through files anew,
Sorting and unsorting, as clever coders do.
With markers and flags, and listings galore,
The tests now check even more!
So here’s a hop and a happy cheer,
For code that brings new listings near!
🐇✨

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.

🔧 ESLint

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-23T11_02_40_266Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🔭 Outside diff range comments (1)
src/sdk/namespace_fs.js (1)

712-777: Refactor to reduce code duplication between insertion functions

The two insertion functions share significant logic. Consider extracting common functionality to reduce duplication and improve maintainability.

+const should_skip_entry = (keymarker, r) => keymarker.key_marker_value === r.key;
+
+const handle_common_prefix = async (r, delimiter, process_dir, keymarker) => {
+    if (!delimiter && r.common_prefix) {
+        if (r.marker_pos && !keymarker.pre_dir.includes(r.pre_dir)) {
+            keymarker.add_previour_dir(r.pre_dir, r.marker_pos);
+        }
+        await process_dir(r.key);
+        return true;
+    }
+    return false;
+};

 const insert_entry_to_results_arr = async r => {
+    if (should_skip_entry(keymarker, r)) return;
+    
     let pos;
     // Since versions are arranged next to latest object in the latest first order,
     // no need to find the sorted last index. Push the ".versions/#VERSION_OBJECT" as
     // they are in order
     if (results.length && r.key < results[results.length - 1].key &&
         !this._is_hidden_version_path(r.key)) {
         pos = _.sortedLastIndexBy(results, r, a => a.key);
     } else {
         pos = results.length;
     }
     if (pos >= limit) {
         is_truncated = true;
         return; // not added
     }
-    if (!delimiter && r.common_prefix) {
-        await process_dir(r.key);
-    } else {
-        if (keymarker.key_marker_value === r.key) {
-            return;
-        }
+    if (!(await handle_common_prefix(r, delimiter, process_dir, keymarker))) {
         if (pos < results.length) {
             results.splice(pos, 0, r);
         } else {
             results.push(r);
         }
         if (results.length > limit) {
             results.length = limit;
             is_truncated = true;
         }
     }
 };
🧹 Nitpick comments (12)
src/sdk/keymarker_fs.js (1)

2-2: Remove redundant 'use strict' directive.

ES modules and CommonJS modules in Node.js are automatically in strict mode. This directive is unnecessary.

-'use strict';
src/test/unit_tests/jest_tests/test_unsort_list_object.test.js (7)

3-3: Remove redundant 'use strict' directive.

As with the previous file, this directive is unnecessary in module context.

-'use strict';

124-124: Fix typo in comment.

-// reak first read after 3 entries.
+// break first read after 3 entries.

158-158: Fix typo in comment.

-// reak first read after 3 entries.
+// break first read after 3 entries.

198-198: Fix typo in comment.

-// Seak first read after 3 entries.
+// Break first read after 500 entries.

223-224: Fix incorrect comment.

The comment mentions 5 items but the test expects 10000.

-//total number of dir and files inside list_dir_root is 5 
+//total number of dir and files inside list_dir_root is 10000
 expect(total_dir_entries).toBe(10000);

490-490: Fix typo in function name.

-async function validat_pagination(r, total_items) {
+async function validate_pagination(r, total_items) {

Remember to update all calls to this function as well.


494-494: Replace magic number with a named constant.

The hardcoded value 1584 should be explained or defined as a constant for clarity.

+const EXPECTED_TOTAL_ITEMS = 1584; // Total number of test objects created
+
 async function validate_pagination(r, total_items) {
     if (r.next_marker) {
         expect(r.is_truncated).toStrictEqual(true);
     } else {
-        expect(total_items).toEqual(1584);
+        expect(total_items).toEqual(EXPECTED_TOTAL_ITEMS);
         expect(r.is_truncated).toStrictEqual(false);
     }
 }
src/sdk/namespace_fs.js (4)

652-663: Simplify keymarker initialization logic

The current implementation checks if key_marker is an object, but this could be more explicit about the expected structure. Consider validating the object structure more thoroughly.

 let keymarker;
-if (typeof(key_marker) === 'object') {
+if (key_marker && typeof key_marker === 'object' && 'marker' in key_marker) {
     keymarker = new KeyMarkerFS(key_marker, true);
 } else {
     keymarker = new KeyMarkerFS({
         marker: key_marker,
         marker_pos: '',
         pre_dir: [],
         pre_dir_pos: [],
     });
 }

846-848: Add clarifying comment for skip_list logic

The purpose of the skip_list flag isn't immediately clear. Add a comment to explain why items need to be skipped when returning to the bucket root.

 // Skip item listing in bucket root path when list flow coming from sub dir to bucket root path,
 // if do not skip items in bucket root path will list two times, 
 // first in normal flow, and second when return back from sub dir.
+// This flag prevents duplicate listings of root directory items that were already
+// processed before descending into subdirectories.
 if (this.bucket_path + '/' === dir_path) {
     skip_list = true;
 }

1049-1061: Consider type safety for list_type comparison

The code compares list_type === '2' as a string, but there's no validation that list_type is actually a string. This could lead to unexpected behavior if a number is passed.

-res.next_marker = list_type === '2' ? {
+res.next_marker = String(list_type) === '2' ? {
     marker: _get_filename(next_version_id_marker),
     marker_pos: r.marker_pos ? r.marker_pos.toString() : '',
     pre_dir: keymarker.pre_dir,
     pre_dir_pos: keymarker.pre_dir_pos,
 } : _get_filename(next_version_id_marker);

826-830: Handle unsorted listing request when feature is disabled

When list_type === '2' is requested but NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED is false, the code silently falls back to sorted listing. Consider logging a warning or throwing an error to make this behavior explicit.

 if (config.NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED && list_type === '2') {
     await insert_unsort_entry_to_results_arr(r);
 } else {
+    if (list_type === '2' && !config.NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED) {
+        dbg.warn('Unsorted listing requested but feature is disabled, falling back to sorted listing');
+    }
     await insert_entry_to_results_arr(r);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d52ffb and d8b024e.

📒 Files selected for processing (11)
  • config.js (1 hunks)
  • src/api/object_api.js (2 hunks)
  • src/endpoint/s3/ops/s3_get_bucket.js (1 hunks)
  • src/native/fs/fs_napi.cpp (1 hunks)
  • src/sdk/keymarker_fs.js (1 hunks)
  • src/sdk/namespace_fs.js (14 hunks)
  • src/test/system_tests/test_utils.js (2 hunks)
  • src/test/unit_tests/jest_tests/test_list_object.test.js (0 hunks)
  • src/test/unit_tests/jest_tests/test_unsort_list_object.test.js (1 hunks)
  • src/test/unit_tests/test_namespace_fs.js (2 hunks)
  • src/test/unit_tests/test_namespace_fs_mpu.js (1 hunks)
🧠 Learnings (1)
src/test/unit_tests/test_namespace_fs.js (1)

Learnt from: naveenpaul1
PR: #9042
File: src/util/cloud_utils.js:183-194
Timestamp: 2025-06-17T12:59:51.543Z
Learning: In the set_noobaa_s3_connection function in src/util/cloud_utils.js, internal NooBaa S3 endpoints (filtered by 'api': 's3', 'kind': 'INTERNAL') will always be non-secure, so tls: false is the correct setting despite the conditional https:// scheme logic.

🧬 Code Graph Analysis (2)
src/test/unit_tests/jest_tests/test_unsort_list_object.test.js (5)
config.js (4)
  • fs (10-10)
  • require (17-17)
  • path (11-11)
  • config (7-7)
src/test/system_tests/test_utils.js (10)
  • fs (4-4)
  • require (11-11)
  • require (12-12)
  • require (16-16)
  • require (18-18)
  • path (6-6)
  • fs_utils (14-14)
  • nb_native (15-15)
  • config (10-10)
  • TMP_PATH (22-22)
src/test/unit_tests/test_namespace_fs_mpu.js (15)
  • fs (6-6)
  • require (20-20)
  • path (8-8)
  • fs_utils (15-15)
  • NamespaceFS (17-17)
  • buffer_utils (19-19)
  • crypto (11-11)
  • config (14-14)
  • upload_bkt (34-34)
  • src_bkt (28-28)
  • ns_tmp_bucket_path (30-30)
  • i (65-65)
  • i (493-493)
  • ns_tmp (37-45)
  • tmp_fs_path (29-29)
src/sdk/namespace_fs.js (10)
  • fs (7-7)
  • require (26-26)
  • require (28-28)
  • require (29-29)
  • path (8-8)
  • nb_native (24-24)
  • buffer_utils (19-19)
  • crypto (15-15)
  • config (14-14)
  • r (213-213)
src/test/unit_tests/test_namespace_fs.js (37)
  • fs (7-7)
  • require (22-22)
  • require (24-24)
  • require (25-25)
  • path (9-9)
  • fs_utils (17-17)
  • nb_native (18-18)
  • NamespaceFS (19-19)
  • buffer_utils (21-21)
  • crypto (11-11)
  • config (15-15)
  • DEFAULT_FS_CONFIG (40-40)
  • upload_bkt (47-47)
  • upload_bkt (717-717)
  • upload_bkt (1363-1363)
  • src_bkt (46-46)
  • src_bkt (716-716)
  • src_bkt (1362-1362)
  • ns_tmp_bucket_path (54-54)
  • ns_tmp_bucket_path (733-733)
  • ns_tmp_bucket_path (1368-1368)
  • i (264-264)
  • dummy_object_sdk (52-52)
  • dummy_object_sdk (731-731)
  • dummy_object_sdk (1234-1234)
  • dummy_object_sdk (1367-1367)
  • ns_tmp (65-73)
  • ns_tmp (734-734)
  • ns_tmp (1369-1369)
  • tmp_fs_path (51-51)
  • tmp_fs_path (727-727)
  • tmp_fs_path (1228-1228)
  • tmp_fs_path (1364-1364)
  • file (1208-1208)
  • key (1457-1457)
  • key (1502-1502)
  • key (1545-1545)
src/sdk/keymarker_fs.js (1)
src/sdk/namespace_fs.js (1)
  • KeyMarkerFS (30-30)
🪛 Biome (1.9.4)
src/test/unit_tests/jest_tests/test_unsort_list_object.test.js

[error] 2-3: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)

src/sdk/keymarker_fs.js

[error] 1-2: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)

💤 Files with no reviewable changes (1)
  • src/test/unit_tests/jest_tests/test_list_object.test.js
🧰 Additional context used
🧠 Learnings (1)
src/test/unit_tests/test_namespace_fs.js (1)

Learnt from: naveenpaul1
PR: #9042
File: src/util/cloud_utils.js:183-194
Timestamp: 2025-06-17T12:59:51.543Z
Learning: In the set_noobaa_s3_connection function in src/util/cloud_utils.js, internal NooBaa S3 endpoints (filtered by 'api': 's3', 'kind': 'INTERNAL') will always be non-secure, so tls: false is the correct setting despite the conditional https:// scheme logic.

🧬 Code Graph Analysis (2)
src/test/unit_tests/jest_tests/test_unsort_list_object.test.js (5)
config.js (4)
  • fs (10-10)
  • require (17-17)
  • path (11-11)
  • config (7-7)
src/test/system_tests/test_utils.js (10)
  • fs (4-4)
  • require (11-11)
  • require (12-12)
  • require (16-16)
  • require (18-18)
  • path (6-6)
  • fs_utils (14-14)
  • nb_native (15-15)
  • config (10-10)
  • TMP_PATH (22-22)
src/test/unit_tests/test_namespace_fs_mpu.js (15)
  • fs (6-6)
  • require (20-20)
  • path (8-8)
  • fs_utils (15-15)
  • NamespaceFS (17-17)
  • buffer_utils (19-19)
  • crypto (11-11)
  • config (14-14)
  • upload_bkt (34-34)
  • src_bkt (28-28)
  • ns_tmp_bucket_path (30-30)
  • i (65-65)
  • i (493-493)
  • ns_tmp (37-45)
  • tmp_fs_path (29-29)
src/sdk/namespace_fs.js (10)
  • fs (7-7)
  • require (26-26)
  • require (28-28)
  • require (29-29)
  • path (8-8)
  • nb_native (24-24)
  • buffer_utils (19-19)
  • crypto (15-15)
  • config (14-14)
  • r (213-213)
src/test/unit_tests/test_namespace_fs.js (37)
  • fs (7-7)
  • require (22-22)
  • require (24-24)
  • require (25-25)
  • path (9-9)
  • fs_utils (17-17)
  • nb_native (18-18)
  • NamespaceFS (19-19)
  • buffer_utils (21-21)
  • crypto (11-11)
  • config (15-15)
  • DEFAULT_FS_CONFIG (40-40)
  • upload_bkt (47-47)
  • upload_bkt (717-717)
  • upload_bkt (1363-1363)
  • src_bkt (46-46)
  • src_bkt (716-716)
  • src_bkt (1362-1362)
  • ns_tmp_bucket_path (54-54)
  • ns_tmp_bucket_path (733-733)
  • ns_tmp_bucket_path (1368-1368)
  • i (264-264)
  • dummy_object_sdk (52-52)
  • dummy_object_sdk (731-731)
  • dummy_object_sdk (1234-1234)
  • dummy_object_sdk (1367-1367)
  • ns_tmp (65-73)
  • ns_tmp (734-734)
  • ns_tmp (1369-1369)
  • tmp_fs_path (51-51)
  • tmp_fs_path (727-727)
  • tmp_fs_path (1228-1228)
  • tmp_fs_path (1364-1364)
  • file (1208-1208)
  • key (1457-1457)
  • key (1502-1502)
  • key (1545-1545)
src/sdk/keymarker_fs.js (1)
src/sdk/namespace_fs.js (1)
  • KeyMarkerFS (30-30)
🪛 Biome (1.9.4)
src/test/unit_tests/jest_tests/test_unsort_list_object.test.js

[error] 2-3: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)

src/sdk/keymarker_fs.js

[error] 1-2: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)

🔇 Additional comments (10)
config.js (1)

846-847: LGTM! Well-placed configuration flag with appropriate defaults.

The new NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED configuration flag is properly placed in the NSFS section and follows the existing naming conventions. The default value of false ensures backward compatibility by keeping the existing sorted behavior as the default.

src/test/system_tests/test_utils.js (2)

494-512: Excellent refactoring! Centralized dummy SDK creation reduces duplication.

The new make_dummy_object_sdk utility function properly centralizes the creation of dummy SDK objects that were previously duplicated across multiple test files. The implementation includes all necessary components:

  • Proper requesting_account structure with NSFS account config
  • AbortController for request cancellation handling
  • throw_if_aborted method for abort signal checking

This promotes consistency and maintainability across the test suite.


781-781: Proper export of the new utility function.

The new utility function is correctly exported for use by other test modules.

src/native/fs/fs_napi.cpp (1)

2108-2108: LGTM! Appropriate debug level adjustment.

Changing from DBG0 to DBG1 reduces the verbosity of this internal directory position logging, which is appropriate for detailed tracing of the new unsorted listing functionality.

src/endpoint/s3/ops/s3_get_bucket.js (1)

44-44: LGTM! Essential parameter forwarding fix.

Adding list_type to the params object ensures the backend receives the listing type parameter, which is required for the new unsorted listing functionality to work correctly.

src/test/unit_tests/test_namespace_fs_mpu.js (1)

20-20: LGTM! Good refactoring to use shared utility.

The change to use the shared make_dummy_object_sdk function from test utilities improves code maintainability by centralizing dummy SDK creation logic and reducing duplication across test files.

Also applies to: 26-26

src/test/unit_tests/test_namespace_fs.js (2)

24-24: Good refactoring to centralize test utilities.

Moving make_dummy_object_sdk to a shared test utility module improves code reusability and maintainability across test files.


76-76: Appropriate configuration for existing tests.

Setting NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED to false ensures existing tests run with the default sorted listing behavior, maintaining test isolation from the new unsorted feature.

src/sdk/namespace_fs.js (2)

30-30: LGTM! Clean import statement

The import of KeyMarkerFS module follows the existing pattern and is appropriately placed with other SDK imports.


3189-3190: LGTM! Improved code formatting

The line break improves readability by keeping the line length manageable.

Comment on lines +726 to +728
list_type: {
type: 'string',
},
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 validation constraints for the list_type parameter.

The list_type parameter lacks validation constraints such as enum values or a description of valid values. This could lead to runtime errors or unexpected behavior if invalid values are passed.

Consider adding enum constraints to define valid list types:

 list_type: {
     type: 'string',
+    enum: ['sorted', 'unsorted'],
+    description: 'Specifies the listing mode: sorted (default) or unsorted'
 },
📝 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
list_type: {
type: 'string',
},
list_type: {
type: 'string',
enum: ['sorted', 'unsorted'],
description: 'Specifies the listing mode: sorted (default) or unsorted'
},
🤖 Prompt for AI Agents
In src/api/object_api.js around lines 726 to 728, the list_type parameter is
missing validation constraints. Add an enum property listing all valid string
values for list_type and include a description explaining what values are
acceptable. This will enforce valid inputs and prevent runtime errors or
unexpected behavior.

Comment on lines +783 to +785
list_type: {
type: 'string',
},
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 validation constraints for the list_type parameter.

Similar to the list_objects method, this parameter needs validation constraints to ensure only valid values are accepted.

Apply the same enum constraints as suggested for the list_objects method:

 list_type: {
     type: 'string',
+    enum: ['sorted', 'unsorted'],
+    description: 'Specifies the listing mode: sorted (default) or unsorted'
 },
📝 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
list_type: {
type: 'string',
},
list_type: {
type: 'string',
enum: ['sorted', 'unsorted'],
description: 'Specifies the listing mode: sorted (default) or unsorted'
},
🤖 Prompt for AI Agents
In src/api/object_api.js around lines 783 to 785, the list_type parameter lacks
validation constraints. Add enum validation constraints to list_type similar to
those used in the list_objects method to restrict accepted values to a
predefined set. This ensures only valid list_type values are accepted and
improves input validation.

Comment on lines +5 to +19
constructor({ marker, marker_pos, pre_dir, pre_dir_pos }, is_unsorted = false) {
this.marker = marker;
this.marker_pos = marker_pos.toString();
this.pre_dir = pre_dir;
this.pre_dir_pos = pre_dir_pos;
this.key_marker_value = marker;
this.current_dir = '';
this.is_unsorted = is_unsorted;
this.last_pre_dir = '';
this.last_pre_dir_position = '';
if (is_unsorted) {
this.current_dir = pre_dir.length > 0 && marker.includes('/') ?
marker.substring(0, marker.lastIndexOf('/') + 1) : '';
}
}
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 parameter validation to prevent runtime errors.

The constructor should validate input parameters, especially marker_pos which could be null/undefined and cause toString() to fail.

 constructor({ marker, marker_pos, pre_dir, pre_dir_pos }, is_unsorted = false) {
+    if (marker_pos === null || marker_pos === undefined) {
+        throw new Error('marker_pos is required');
+    }
     this.marker = marker;
     this.marker_pos = marker_pos.toString();
📝 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
constructor({ marker, marker_pos, pre_dir, pre_dir_pos }, is_unsorted = false) {
this.marker = marker;
this.marker_pos = marker_pos.toString();
this.pre_dir = pre_dir;
this.pre_dir_pos = pre_dir_pos;
this.key_marker_value = marker;
this.current_dir = '';
this.is_unsorted = is_unsorted;
this.last_pre_dir = '';
this.last_pre_dir_position = '';
if (is_unsorted) {
this.current_dir = pre_dir.length > 0 && marker.includes('/') ?
marker.substring(0, marker.lastIndexOf('/') + 1) : '';
}
}
constructor({ marker, marker_pos, pre_dir, pre_dir_pos }, is_unsorted = false) {
if (marker_pos === null || marker_pos === undefined) {
throw new Error('marker_pos is required');
}
this.marker = marker;
this.marker_pos = marker_pos.toString();
this.pre_dir = pre_dir;
this.pre_dir_pos = pre_dir_pos;
this.key_marker_value = marker;
this.current_dir = '';
this.is_unsorted = is_unsorted;
this.last_pre_dir = '';
this.last_pre_dir_position = '';
if (is_unsorted) {
this.current_dir = pre_dir.length > 0 && marker.includes('/') ?
marker.substring(0, marker.lastIndexOf('/') + 1) : '';
}
}
🤖 Prompt for AI Agents
In src/sdk/keymarker_fs.js around lines 5 to 19, the constructor uses
marker_pos.toString() without checking if marker_pos is null or undefined, which
can cause runtime errors. Add validation to ensure marker_pos is defined before
calling toString(), and handle cases where it is null or undefined by assigning
a default string value or throwing a clear error.

Comment on lines +21 to +46
async update_key_marker(marker, marker_pos) {
this.marker = marker;
this.marker_pos = marker_pos;
this.key_marker_value = marker;
}

async get_previour_dir_length() {
return this.pre_dir.length;
}

async get_previour_dir_info() {
return {
pre_dir_path: this.pre_dir.pop(),
pre_dir_position: this.pre_dir_pos.pop(),
};
}

async add_previour_dir(pre_dir, pre_dir_pos) {
this.pre_dir.push(pre_dir);
this.pre_dir_pos.push(pre_dir_pos.toString());
}

async update_last_previour_dir(last_pre_dir, last_pre_dir_position) {
this.last_pre_dir = last_pre_dir;
this.last_pre_dir_position = last_pre_dir_position;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unnecessary async keywords from synchronous methods.

None of these methods perform asynchronous operations. The async keyword is misleading and should be removed.

-async update_key_marker(marker, marker_pos) {
+update_key_marker(marker, marker_pos) {
     this.marker = marker;
     this.marker_pos = marker_pos;
     this.key_marker_value = marker;
 }

Apply the same change to all other methods in this class.

📝 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 update_key_marker(marker, marker_pos) {
this.marker = marker;
this.marker_pos = marker_pos;
this.key_marker_value = marker;
}
async get_previour_dir_length() {
return this.pre_dir.length;
}
async get_previour_dir_info() {
return {
pre_dir_path: this.pre_dir.pop(),
pre_dir_position: this.pre_dir_pos.pop(),
};
}
async add_previour_dir(pre_dir, pre_dir_pos) {
this.pre_dir.push(pre_dir);
this.pre_dir_pos.push(pre_dir_pos.toString());
}
async update_last_previour_dir(last_pre_dir, last_pre_dir_position) {
this.last_pre_dir = last_pre_dir;
this.last_pre_dir_position = last_pre_dir_position;
}
update_key_marker(marker, marker_pos) {
this.marker = marker;
this.marker_pos = marker_pos;
this.key_marker_value = marker;
}
get_previour_dir_length() {
return this.pre_dir.length;
}
get_previour_dir_info() {
return {
pre_dir_path: this.pre_dir.pop(),
pre_dir_position: this.pre_dir_pos.pop(),
};
}
add_previour_dir(pre_dir, pre_dir_pos) {
this.pre_dir.push(pre_dir);
this.pre_dir_pos.push(pre_dir_pos.toString());
}
update_last_previour_dir(last_pre_dir, last_pre_dir_position) {
this.last_pre_dir = last_pre_dir;
this.last_pre_dir_position = last_pre_dir_position;
}
🤖 Prompt for AI Agents
In src/sdk/keymarker_fs.js from lines 21 to 46, several methods are marked as
async but do not perform any asynchronous operations. Remove the async keyword
from all these synchronous methods, including update_key_marker,
get_previour_dir_length, get_previour_dir_info, add_previour_dir, and
update_last_previour_dir. Also, review the rest of the class and remove async
from any other synchronous methods to avoid misleading usage.

Comment on lines +27 to +29
async get_previour_dir_length() {
return this.pre_dir.length;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in method name.

"previour" should be "previous" for consistency and correctness.

-async get_previour_dir_length() {
+async get_previous_dir_length() {
     return this.pre_dir.length;
 }
📝 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 get_previour_dir_length() {
return this.pre_dir.length;
}
async get_previous_dir_length() {
return this.pre_dir.length;
}
🤖 Prompt for AI Agents
In src/sdk/keymarker_fs.js around lines 27 to 29, the method name
get_previour_dir_length contains a typo. Rename the method to
get_previous_dir_length to correct the spelling and maintain consistency.

@@ -593,6 +594,7 @@ class NamespaceFS {
* prefix?: string,
* delimiter?: string,
* key_marker?: string,
* list_type?: string,
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 JSDoc documentation for the new list_type parameter

The new list_type parameter lacks documentation about its purpose and accepted values. Consider adding JSDoc comments to clarify its usage.

 /**
  * @typedef {{
  *  bucket: string,
  *  prefix?: string,
  *  delimiter?: string,
  *  key_marker?: string,
- *  list_type?: string,
+ *  list_type?: string, // '2' for unsorted listing, undefined/other for sorted listing
  *  limit?: number,
  * }} ListParams
  */

Also applies to: 617-617

🤖 Prompt for AI Agents
In src/sdk/namespace_fs.js at lines 597 and 617, the new parameter `list_type`
is missing JSDoc documentation. Add JSDoc comments describing the purpose of
`list_type` and the accepted values it can take to clarify its usage for future
maintainers and users.

const config = require('../../../../config');

const DEFAULT_FS_CONFIG = get_process_fs_context();
config.NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED = true;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Move global config modification into test lifecycle hooks.

Modifying global configuration at the file level can affect other tests running in parallel. This should only be done within beforeAll/afterAll hooks.

-config.NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED = true;

This is already being set in the beforeAll hooks, so this line should be removed.

📝 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
config.NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED = true;
🤖 Prompt for AI Agents
In src/test/unit_tests/jest_tests/test_unsort_list_object.test.js at line 18,
remove the global configuration modification setting
config.NSFS_LIST_OBJECTS_V2_UNSORTED_ENABLED = true from the top-level code and
rely solely on the existing beforeAll and afterAll hooks to set and reset this
configuration to avoid side effects on other tests.

Comment on lines +89 to +91
for (let i = 0; i < total_files; i++) {
create_temp_file(list_dir_root, `test_${i}.json`, {test: test});
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined variable reference.

The variable test is not defined, which will cause a ReferenceError.

 for (let i = 0; i < total_files; i++) {
-    create_temp_file(list_dir_root, `test_${i}.json`, {test: test});
+    create_temp_file(list_dir_root, `test_${i}.json`, {test: 'test'});
 }
📝 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
for (let i = 0; i < total_files; i++) {
create_temp_file(list_dir_root, `test_${i}.json`, {test: test});
}
for (let i = 0; i < total_files; i++) {
create_temp_file(list_dir_root, `test_${i}.json`, {test: 'test'});
}
🤖 Prompt for AI Agents
In src/test/unit_tests/jest_tests/test_unsort_list_object.test.js around lines
89 to 91, the variable `test` used as an argument in create_temp_file is not
defined, causing a ReferenceError. Define the variable `test` with the
appropriate value or replace it with the correct existing variable before using
it in the create_temp_file call to fix the issue.

Comment on lines +146 to +148
} catch (err) {
console.log("Error :", err);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling in tests.

Catching and logging errors without failing the test can hide issues. Consider using Jest's error assertions or re-throwing the error.

 } catch (err) {
-    console.log("Error :", err);
+    throw err; // Let Jest handle the error
 }
📝 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
} catch (err) {
console.log("Error :", err);
}
} catch (err) {
throw err; // Let Jest handle the error
}
🤖 Prompt for AI Agents
In src/test/unit_tests/jest_tests/test_unsort_list_object.test.js around lines
146 to 148, the catch block currently logs errors without failing the test,
which can hide test failures. Modify the catch block to either re-throw the
caught error or use Jest's expect assertions to properly fail the test when an
error occurs, ensuring test failures are visible and handled correctly.


it('list 10000 dir files - telldir and seekdir', async () => {
for (let i = total_files; i < total_files + 9995; i++) {
create_temp_file(list_dir_root, `test_${i}.json`, {test: test});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined variable reference.

Same issue as above - test variable is not defined.

-create_temp_file(list_dir_root, `test_${i}.json`, {test: test});
+create_temp_file(list_dir_root, `test_${i}.json`, {test: 'test'});
📝 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
create_temp_file(list_dir_root, `test_${i}.json`, {test: test});
create_temp_file(list_dir_root, `test_${i}.json`, {test: 'test'});
🤖 Prompt for AI Agents
In src/test/unit_tests/jest_tests/test_unsort_list_object.test.js at line 191,
the variable 'test' used in the call to create_temp_file is undefined. Define or
replace 'test' with the correct variable or value that should be passed as the
third argument to create_temp_file to fix the undefined variable reference.

@github-actions github-actions bot removed the Stale label Jul 24, 2025
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