Skip to content
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

Add support for deserializing and decoding v0.1.0 IR streams, but without log-level parsing and filtering. #30

Merged
merged 43 commits into from
Nov 9, 2024

Conversation

junhaoliao
Copy link
Collaborator

@junhaoliao junhaoliao commented Nov 7, 2024

Description

  1. Add StructuredIrStreamReader which supports reading v0.1.0 IR streams without log level filtering.

Validation performed

  1. Extracted and placed sample file at project root: test-irv2.clp.zip

  2. Built the js assets with task and ran below sample code at project root:

    import ModuleInit from "./cmake-build-debug/ClpFfiJs-node.js"
    import fs from "node:fs"
    
    const main = async () => {
        const file = fs.readFileSync("./test-irv2.clp.zst")
    
        console.time("perf")
        const Module = await ModuleInit()
        try {
            // const decoder = new Module.ClpStreamReader(new Uint8Array(file))
            const decoder = new Module.ClpStreamReader(new Uint8Array(file), {timestampKey: "timestamp"})
            console.log("type:", decoder.getIrStreamType() === Module.IrStreamType.STRUCTURED,
                decoder.getIrStreamType() === Module.IrStreamType.UNSTRUCTURED)
            const numEvents = decoder.deserializeStream()
            console.log(numEvents)
            const results = decoder.decodeRange(0, numEvents, false)
            console.log(results)
    
            decoder.filterLogEvents([0]) // Expect error printed
    
            const filteredLogEventMap = decoder.getFilteredLogEventMap() // Expect error printed
            console.log(filteredLogEventMap) // Expect: null
        } catch (e) {
            console.error("Exception caught:", e.stack)
        }
        console.timeEnd("perf")
    }
    
    void main()
  3. Observed below in the console:

    [2024-11-07 03:19:49.407] [info] [StreamReader.cpp:162] StreamReader::create: got buffer of length=391
    [2024-11-07 03:19:49.425] [info] [StreamReader.cpp:112] IR version is 0.1.0
    type: true false
    1000
    [
      [
        '{"@timestamp":1730965799000,"application":{"nestedNodeKey":"nestedNodeVal"},"application_hashes":["3bbb624d",123,null,{"arrayNodeKey":"arrayNodeVal"},true],"count":-123.1,"is_contained":false,"log.level":1,"message":"hello","process.thread.name":"main","service":null}',
        0n,
        0,
        1
      ],
      [
        '{"@timestamp":1730965799000,"application":{"nestedNodeKey":"nestedNodeVal"},"application_hashes":["3bbb624d",123,null,{"arrayNodeKey":"arrayNodeVal"},true],"count":-123.1,"is_contained":false,"log.level":1,"message":"hello","process.thread.name":"main","service":null}',
        0n,
        0,
        2
      ],
      ...
      ... 900 more items
    ]
    [2024-11-07 03:19:49.696] [error] [StructuredIrStreamReader.cpp:85] Log level filtering is not yet supported in this reader.
    [2024-11-07 03:19:49.696] [error] [StructuredIrStreamReader.cpp:77] Log level filtering is not yet supported in this reader.
    null
    perf: 343.331ms
  4. Sanitize-tested Zstd-compressed CLP IR stream files with older versions:

    1. test-0.0.1.clp.zst : Downloaded from https://yscope.s3.us-east-2.amazonaws.com/sample-logs/yarn-ubuntu-resourcemanager-ip-172-31-17-135.log.1.clp.zst : succeeded.
    2. test-0.0.2.clp.zst : test-0.0.2.clp.zip : succeeded.
    3. An empty file: failed.
    4. A beta version file that is never supported on CLP OSS: failed.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced the StructuredIrStreamReader class for improved handling of structured IR streams.
    • Added flexible configuration options for the StreamReader class.
    • Enhanced error handling for stream deserialization.
    • New method get_reader in StreamReaderDataContext for accessing the reader interface.
    • Added a method to retrieve the IR stream type in the UnstructuredIrStreamReader class.
  • Bug Fixes

    • Improved validation logic for IR stream versions.
  • Chores

    • Updated submodule to the latest commit for enhanced functionality and stability.

These changes collectively enhance the project's capability to manage and process structured data streams effectively.

Copy link

coderabbitai bot commented Nov 7, 2024

Walkthrough

The pull request introduces significant changes to the CMakeLists.txt file, enhancing the build configuration for the clp-ffi-js project by adding new source files and defining build options for Emscripten. Modifications to the StreamReader class include updates to its method signatures and error handling, while new classes StructuredIrStreamReader and IrUnitHandler are implemented to manage structured IR streams. Additionally, a submodule update reflects changes in external dependencies, ensuring the project remains aligned with its required components.

Changes

File Path Change Summary
CMakeLists.txt Added new source files and updated build configuration for Emscripten, including version checks and compile options.
src/clp_ffi_js/ir/StreamReader.cpp Updated create method to accept ReaderOptions, improved version validation, and refined error handling.
src/clp_ffi_js/ir/StreamReader.hpp Removed unnecessary headers, updated create method signature to include ReaderOptions.
src/clp_ffi_js/ir/StreamReaderDataContext.hpp Added get_reader method to provide access to the ReaderInterface.
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp Implemented StructuredIrStreamReader class for structured IR stream handling with error handling and deserialization methods.
src/clp_ffi_js/ir/StructuredIrStreamReader.hpp Introduced IrUnitHandler and StructuredIrStreamReader classes with methods for managing IR units and stream deserialization.
src/submodules/clp Updated submodule commit reference to reflect the latest changes in the submodule repository.
src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp Added get_ir_stream_type method to return Unstructured stream type in UnstructuredIrStreamReader.

Possibly related PRs


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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

@junhaoliao junhaoliao changed the title Add StructuredIrStreamReader. Add StructuredIrStreamReader without log level filtering. Nov 7, 2024
@junhaoliao junhaoliao changed the title Add StructuredIrStreamReader without log level filtering. Add StructuredIrStreamReader which supports reading v0.1.0 IR stream without log level filtering. Nov 7, 2024
@junhaoliao junhaoliao changed the title Add StructuredIrStreamReader which supports reading v0.1.0 IR stream without log level filtering. Add StructuredIrStreamReader which supports reading v0.1.0 IR streams without log level filtering. Nov 7, 2024
@junhaoliao
Copy link
Collaborator Author

@coderabbitai review

Copy link

coderabbitai bot commented Nov 7, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Outside diff range and nitpick comments (8)
src/clp_ffi_js/ir/StreamReaderDataContext.hpp (1)

47-50: LGTM! Consider enhancing the documentation.

The implementation is correct and follows the class's patterns. Consider adding more details to the documentation about the lifetime of the returned reference and its intended usage.

     /**
-     * @return A reference to the reader.
+     * @return A reference to the underlying reader. The reference remains valid
+     *         as long as this context object exists.
      */
src/clp_ffi_js/ir/StreamReader.hpp (2)

14-14: Please document the ReaderOptions type.

Consider adding JSDoc comments to describe the available options and their impact on the reader's behaviour, particularly regarding log level filtering support.

+/**
+ * Options for configuring the stream reader's behaviour.
+ * @typedef {Object} ReaderOptions
+ * @property {boolean} enableLogLevelFiltering - Whether to enable log level filtering
+ */
 EMSCRIPTEN_DECLARE_VAL_TYPE(ReaderOptions);

35-37: Update method documentation to include the reader_options parameter.

The documentation block above needs to be updated to describe the new parameter.

     /**
      * Creates a `StreamReader` to read from the given array.
      *
      * @param data_array An array containing a Zstandard-compressed IR stream.
+     * @param reader_options Configuration options for the reader instance.
      * @return The created instance.
      * @throw ClpFfiJsException if any error occurs.
      */
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (5)

76-79: Consider throwing an exception for unsupported functionality

Currently, the get_filtered_log_event_map method logs an error and returns null when log level filtering is not supported. To provide clearer feedback to the caller, consider throwing a ClpFfiJsException to indicate that this functionality is not implemented.


93-94: Make buffer reservation size configurable

The constant cDefaultNumReservedLogEvents is set to reserve space for 500,000 log events. Depending on the typical size of the IR streams, it may be beneficial to make this value configurable or dynamically adjust it based on the stream's size to optimize memory usage.


139-141: Handle invalid indices in decode_range method

Currently, the method returns null if the provided indices are invalid. It would be more appropriate to throw an exception, such as a std::out_of_range or a custom exception, to clearly indicate the misuse of the function and aid in debugging.


157-167: Optimize extraction of log level information

The extraction of the log level involves multiple checks and could be streamlined. Consider simplifying the logic to enhance readability and performance. For example, you might use a helper function or employ structured bindings if the compiler supports C++17 or higher.


190-197: Initialize member variables using an initializer list

For improved readability and performance, consider initializing m_stream_reader_data_context and m_deserialized_log_events directly in the constructor's member initializer list rather than within the constructor body.

Apply this diff to adjust the constructor:

- StructuredIrStreamReader::StructuredIrStreamReader(
-         StreamReaderDataContext<StructuredIrDeserializer>&& stream_reader_data_context,
-         std::shared_ptr<std::vector<clp::ffi::KeyValuePairLogEvent>> deserialized_log_events
- )
-         : m_stream_reader_data_context{std::make_unique<
-                   StreamReaderDataContext<StructuredIrDeserializer>>(
-                   std::move(stream_reader_data_context)
-           )},
-           m_deserialized_log_events{std::move(deserialized_log_events)} {}
+ StructuredIrStreamReader::StructuredIrStreamReader(
+         StreamReaderDataContext<StructuredIrDeserializer>&& stream_reader_data_context,
+         std::shared_ptr<std::vector<clp::ffi::KeyValuePairLogEvent>> deserialized_log_events
+ )
+         : m_stream_reader_data_context{std::make_unique<
+                   StreamReaderDataContext<StructuredIrDeserializer>>(
+                   std::move(stream_reader_data_context)
+           )},
+           m_deserialized_log_events{std::move(deserialized_log_events)} {
+     // Empty constructor body
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 805c392 and 8a1e9a6.

📒 Files selected for processing (7)
  • CMakeLists.txt (1 hunks)
  • src/clp_ffi_js/ir/StreamReader.cpp (5 hunks)
  • src/clp_ffi_js/ir/StreamReader.hpp (2 hunks)
  • src/clp_ffi_js/ir/StreamReaderDataContext.hpp (1 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1 hunks)
  • src/submodules/clp (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/submodules/clp
🧰 Additional context used
📓 Learnings (1)
src/clp_ffi_js/ir/StreamReader.cpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
🔇 Additional comments (10)
src/clp_ffi_js/ir/StreamReaderDataContext.hpp (1)

47-50: Verify the usage of get_reader() method.

Let's ensure this new method is being used appropriately in the StructuredIrStreamReader implementation.

✅ Verification successful

Let me analyze the usage of get_reader() further by checking its implementation context.


The get_reader() method is properly implemented and used

The method is used correctly within StructuredIrStreamReader.cpp where it's called to obtain the reader reference for deserializing IR units. The usage is consistent with its intended purpose as shown by:

  • It's used in conjunction with the deserializer to process IR units
  • The return value is properly captured as a reference
  • The context shows appropriate error handling and processing flow
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of get_reader() to verify proper implementation

# Search for direct method calls
echo "Searching for get_reader() usage:"
rg -p "get_reader\(\)" --type cpp

# Search for StructuredIrStreamReader implementation to verify integration
echo -e "\nChecking StructuredIrStreamReader implementation:"
fd -e cpp -e hpp "StructuredIrStreamReader" --exec rg -p "StreamReaderDataContext"

Length of output: 1110


Script:

#!/bin/bash
# Check the implementation of StructuredIrStreamReader where get_reader() is used
echo "Checking the context of get_reader() usage:"
rg -p -B 5 -A 5 "get_reader\(\)" src/clp_ffi_js/ir/StructuredIrStreamReader.cpp

# Check the full class definition of StreamReaderDataContext
echo -e "\nChecking StreamReaderDataContext class definition:"
ast-grep --pattern 'template <typename DeserializerT>
class StreamReaderDataContext {
  $$$
}'

Length of output: 872

src/clp_ffi_js/ir/StreamReader.hpp (1)

35-37: Verify version compatibility handling.

Since this interface will be used by the new StructuredIrStreamReader for v0.1.0 IR streams, consider adding version validation in the create() method.

Consider adding a version compatibility check in the factory method or documenting version support in the class documentation.

CMakeLists.txt (2)

86-88: 💡 Codebase verification

Missing test coverage for Stream Reader implementations

The verification reveals that while there are three reader implementations:

  • src/clp_ffi_js/ir/StreamReader.cpp
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp
  • src/clp_ffi_js/ir/UnstructuredIrStreamReader.cpp

There are no corresponding test files in the codebase. This is concerning as these components handle critical IR stream processing functionality.

  • Add unit tests for StructuredIrStreamReader to verify v0.1.0 IR stream handling
  • Add unit tests for UnstructuredIrStreamReader to ensure proper stream processing
  • Consider adding integration tests to verify the interaction between different reader implementations
🔗 Analysis chain

Source files organization looks good, but verify test coverage.

The addition of StructuredIrStreamReader.cpp and UnstructuredIrStreamReader.cpp alongside the existing StreamReader.cpp follows a logical organization pattern. However, ensure that corresponding test files are also added to maintain test coverage.

Let's verify the test coverage:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for corresponding test files for the new source files
# Expected: Test files should exist for the new reader implementations

echo "Checking for test files..."
fd -g "*test*.cpp" -g "*Test*.cpp" | grep -i "structured.*reader"

Length of output: 228


Script:

#!/bin/bash
# Let's try a different approach to find test files
echo "Searching for test files related to readers..."
rg -l "test|Test" --type cpp | grep -i "reader"

# Also search for the actual implementation files to compare
echo -e "\nSearching for reader implementation files..."
fd ".*Reader\.cpp$" 

Length of output: 408


Script:

#!/bin/bash
# Let's check the test directory structure and content
echo "Checking test directory structure..."
fd "test" -t d

echo -e "\nChecking for any test files in the repository..."
fd -e cpp -e h ".*[tT]est.*"

# Let's also check if there are tests in the same directory as the readers
echo -e "\nChecking for test files in the ir directory..."
ls src/clp_ffi_js/ir/*[tT]est*

Length of output: 460

⛔ Skipped due to learnings
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/IrStreamReader.cpp:58-59
Timestamp: 2024-11-04T19:35:32.602Z
Learning: In the `IrStreamReader::filter_log_events` method in `src/clp_ffi_js/ir/IrStreamReader.cpp`, the wrapper code is typed with TypeScript, ensuring that non-array inputs for `log_level_filter` would fail static checks, so additional runtime error handling is unnecessary.

92-95: Verify dependency graph for new core components.

The addition of core CLP components (ir_unit_deserialization_methods.cpp, utils.cpp, KeyValuePairLogEvent.cpp, SchemaTree.cpp) suggests new dependencies. These components appear to support the structured IR stream reading functionality.

Let's verify the dependency relationships:

src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (3)

65-67: Correct use of [[maybe_unused]] attribute

The parameters utc_offset_old and utc_offset_new are properly marked with [[maybe_unused]], indicating they are intentionally unused in this function.


82-83: Verify the management of m_current_node_id

Manually incrementing m_current_node_id may lead to inconsistencies if node IDs are managed elsewhere. Please ensure that this approach aligns with the SchemaTree node ID assignment strategy or consider retrieving the node ID directly from schema_tree_node_locator.


134-192: Well-structured class design and resource management

The StructuredIrStreamReader class is well-designed, adhering to RAII principles with appropriate use of constructors and deleted copy and move assignment operators. The resource management appears sound.

src/clp_ffi_js/ir/StreamReader.cpp (3)

120-122: Emscripten type registration updated correctly

The ReaderOptions type is registered appropriately with Emscripten bindings, allowing it to be used effectively in the interface.


198-203: Appropriate exception handling for unsupported versions

Throwing ClpFfiJsException for unsupported IR stream versions provides clear feedback to the user about the inability to create a reader.


149-150: ⚠️ Potential issue

Update method signature and adjust all invocations

The StreamReader::create method now includes the ReaderOptions parameter. Please ensure that all calls to this method are updated to include the new parameter to maintain consistency and prevent compilation issues.

Run the following script to identify any calls to StreamReader::create that might be missing the ReaderOptions parameter:

src/clp_ffi_js/ir/StructuredIrStreamReader.hpp Outdated Show resolved Hide resolved
Comment on lines +172 to +189
if (clp::ffi::ir_stream::IRProtocolErrorCode::Supported == version_validation_result) {
zstd_decompressor->seek_from_begin(0);
return std::make_unique<StructuredIrStreamReader>(StructuredIrStreamReader::create(
std::move(zstd_decompressor),
std::move(data_buffer),
reader_options
));
}
if (clp::ffi::ir_stream::IRProtocolErrorCode::BackwardCompatible
== version_validation_result)
{
zstd_decompressor->seek_from_begin(pos);
return std::make_unique<UnstructuredIrStreamReader>(UnstructuredIrStreamReader::create(
std::move(zstd_decompressor),
std::move(data_buffer)
));
}
} catch (ZstdDecompressor::OperationFailed const& e) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure consistent use of ReaderOptions

While StructuredIrStreamReader::create is called with reader_options, the UnstructuredIrStreamReader::create is called without it. If ReaderOptions are applicable to both reader types, consider passing reader_options to UnstructuredIrStreamReader::create as well for consistency.

std::format("Unable to create reader for IR stream with version {}.", version)
};
}
auto const version_validation_result{clp::ffi::ir_stream::validate_protocol_version(version)};
Copy link

@coderabbitai coderabbitai bot Nov 7, 2024

Choose a reason for hiding this comment

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

💡 Codebase verification

Function validate_protocol_version appears to be missing from the codebase

The function clp::ffi::ir_stream::validate_protocol_version is being called in StreamReader.cpp, but after thorough searching through the codebase:

  • No function definition was found
  • No header file contains the declaration
  • Only usage appears in StreamReader.cpp

This confirms the original concern that this function is not yet available in the CLP-core library.

🔗 Analysis chain

Verify the existence of validate_protocol_version function

Please confirm that the function clp::ffi::ir_stream::validate_protocol_version is available in the CLP-core library. According to previous learnings, this utility function was not planned to be added soon.

Run the following script to check for the definition of validate_protocol_version:


Let me search for more specific information about this function's definition.


Let me try one more search with different parameters to find any related header files or function definitions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for the definition of `validate_protocol_version` in the codebase.

rg 'validate_protocol_version'

Length of output: 164


Script:

#!/bin/bash
# Search for the function definition using ast-grep
ast-grep --pattern 'validate_protocol_version'

# Also check header files that might contain the declaration
rg -t hpp -t h 'validate_protocol_version'

# Look for any namespace definitions related to ir_stream
rg 'namespace.*ir_stream'

Length of output: 283


Script:

#!/bin/bash
# Search for header files with .h extension
fd -e h -x rg -l "validate_protocol_version" {} \;

# Search for any ir_stream related files
fd -t f -x rg -l "namespace.*ir_stream|ir_stream" {} \;

# Look for the function definition in cpp files
fd -e cpp -x rg -B 2 -A 5 "validate_protocol_version" {} \;

Length of output: 784

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is imported from a CLP upstream library.

Copy link

Choose a reason for hiding this comment

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

@junhaoliao, thank you for the clarification. I understand that validate_protocol_version is imported from the CLP upstream library.


✏️ Learnings added
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StreamReader.cpp:179-179
Timestamp: 2024-11-07T08:38:39.605Z
Learning: The function `clp::ffi::ir_stream::validate_protocol_version` used in `src/clp_ffi_js/ir/StreamReader.cpp` is imported from the CLP upstream library and may not be present in the local codebase.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines 82 to 86
if (log_level_filter.isNull()) {
return;
}
SPDLOG_ERROR(cLogLevelFilteringNotSupportedPrompt);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance error handling in filter_log_events method

Instead of logging an error when log level filtering is unsupported, you might throw a ClpFfiJsException. This approach would more effectively notify the caller that the operation is not available, allowing for better error management in the application.

Comment on lines +107 to +110
if (std::errc::result_out_of_range == error) {
SPDLOG_ERROR("File contains an incomplete IR stream");
break;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Throw exception for incomplete IR streams

When encountering an incomplete IR stream, the code logs an error and exits the loop. Consider throwing a ClpFfiJsException to inform the caller about the incomplete stream explicitly. This change would improve error propagation and allow for more robust error handling upstream.

Comment on lines 176 to 183
EM_ASM(
{ Emval.toValue($0).push([UTF8ToString($1), $2, $3, $4]); },
results.as_handle(),
json.value().dump().c_str(),
log_level,
timestamp,
log_event_idx + 1
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid using EM_ASM for data aggregation

Using EM_ASM macros can introduce complexity and potential maintenance issues. Consider using emscripten::val functions to manipulate JavaScript arrays directly from C++. This approach would lead to cleaner code and better type safety.

Apply this diff to refactor the code:

- EM_ASM(
-         { Emval.toValue($0).push([UTF8ToString($1), $2, $3, $4]); },
-         results.as_handle(),
-         json.value().dump().c_str(),
-         log_level,
-         timestamp,
-         log_event_idx + 1
- );
+ auto js_array = emscripten::val::array();
+ js_array.call<void>("push", json.value().dump(), log_level, timestamp, log_event_idx + 1);
+ results.call<void>("push", js_array);

Committable suggestion skipped: line range outside the PR's diff.

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

🧹 Outside diff range and nitpick comments (7)
src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp (1)

59-62: Implementation looks good, but documentation would be helpful, eh?

The implementation correctly provides backward compatibility for IR protocol error handling. However, adding documentation would make the intent clearer.

Consider adding documentation like this:

+    /**
+     * Returns the IR protocol error code for this reader.
+     * @return BackwardCompatible to indicate support for older IR stream versions
+     */
     [[nodiscard]] auto get_ir_protocol_error_code(
     ) const -> clp::ffi::ir_stream::IRProtocolErrorCode override {
         return clp::ffi::ir_stream::IRProtocolErrorCode::BackwardCompatible;
     }
src/clp_ffi_js/ir/StreamReader.hpp (2)

15-15: Add documentation for ReaderOptions type.

Please add JSDoc or similar documentation to describe the purpose and structure of the ReaderOptions type, similar to how other TS types are documented in the codebase.


54-55: Add documentation for get_ir_protocol_error_code method.

The new pure virtual method requires documentation to:

  • Describe its purpose and return value meanings
  • Specify when it should be called in the error handling flow
  • Document any exceptional conditions

Additionally, consider adding error code constants or enums to make the error handling more explicit.

src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1)

64-71: Consider implementing UTC offset change handling

The method handle_utc_offset_change currently logs a warning indicating that UTC offset changes are not handled. If UTC offset changes are expected in the IR streams, implementing proper handling would ensure accurate processing of time-sensitive data.

Would you like assistance in implementing the logic for handling UTC offset changes?

src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (2)

144-146: Remove unused variable message to clean up the code

The variable message is declared and reserved but never used. Removing it will simplify the code and eliminate any unnecessary memory allocation.

Apply this diff to remove the unused variable:

-    std::string message;
-    constexpr size_t cDefaultReservedMessageLength{512};
-    message.reserve(cDefaultReservedMessageLength);

93-94: Consider making the reserved log events count configurable

The default reservation of 500,000 log events might not be optimal for all use cases. Allowing this value to be configurable can help manage memory usage more effectively for different stream sizes.

Apply this diff to introduce configurability:

-    constexpr size_t cDefaultNumReservedLogEvents{500'000};
+    size_t num_reserved_log_events = reader_options.contains("numReservedLogEvents")
+                                         ? reader_options["numReservedLogEvents"].as<size_t>()
+                                         : 500'000;
-    m_deserialized_log_events->reserve(cDefaultNumReservedLogEvents);
+    m_deserialized_log_events->reserve(num_reserved_log_events);
src/clp_ffi_js/ir/StreamReader.cpp (1)

182-199: Usage of reader_options with UnstructuredIrStreamReader

reader_options are passed to StructuredIrStreamReader::create but not to UnstructuredIrStreamReader::create. If UnstructuredIrStreamReader does not utilize reader_options, this is acceptable. However, for consistency and future extensibility, consider passing reader_options to UnstructuredIrStreamReader::create as well.

Apply this diff if applicable:

-                std::move(data_buffer)
+                std::move(data_buffer),
+                reader_options
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8a1e9a6 and dc652ad.

📒 Files selected for processing (5)
  • src/clp_ffi_js/ir/StreamReader.cpp (6 hunks)
  • src/clp_ffi_js/ir/StreamReader.hpp (3 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1 hunks)
  • src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp (1 hunks)
🧰 Additional context used
📓 Learnings (3)
src/clp_ffi_js/ir/StreamReader.cpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
src/clp_ffi_js/ir/StreamReader.hpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/IrStreamReader.cpp:58-59
Timestamp: 2024-11-04T19:35:32.602Z
Learning: In the `IrStreamReader::filter_log_events` method in `src/clp_ffi_js/ir/IrStreamReader.cpp`, the wrapper code is typed with TypeScript, ensuring that non-array inputs for `log_level_filter` would fail static checks, so additional runtime error handling is unnecessary.
🔇 Additional comments (7)
src/clp_ffi_js/ir/StreamReader.hpp (2)

7-7: LGTM! Header changes improve modularity.

The addition of decoding_methods.hpp is appropriate for the new IR protocol error code functionality, and removing unused headers helps reduce compilation overhead.


36-38: Verify all callers are updated for the new create() signature.

The addition of the reader_options parameter is a breaking change.

✅ Verification successful

Let me generate additional scripts to verify the actual usage of StreamReader::create from JavaScript code since we only see the C++ side so far.


Let me try one more search with a different approach to find JavaScript files and their usage patterns.


Based on the search results, I can now provide a final response:

Breaking change in StreamReader::create is properly handled

The addition of the ReaderOptions parameter to StreamReader::create is correctly propagated through the inheritance hierarchy:

  • StreamReader::create is the factory method exposed to JavaScript through Emscripten bindings
  • Both derived classes (StructuredIrStreamReader and UnstructuredIrStreamReader) handle the change:
    • StructuredIrStreamReader::create accepts and uses the reader_options parameter
    • UnstructuredIrStreamReader::create maintains its original signature since it doesn't need the options

The JavaScript interface is properly maintained through the Emscripten bindings which register the ReaderOptions type as "{logLevelKey: string, timestampKey: string} | null".

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to StreamReader::create to ensure they're updated
# with the new ReaderOptions parameter

# Search for create() calls in both C++ and JS files
rg -t cpp -t js "StreamReader::create|StreamReader\.create" -A 2

Length of output: 2015


Script:

#!/bin/bash
# Search for JavaScript code that calls StreamReader.create
rg -t js "new StreamReader|StreamReader\.create" -A 3

# Also check for any test files that might use StreamReader
fd -e test.js -e spec.js -X rg "StreamReader" -A 3

Length of output: 255


Script:

#!/bin/bash
# Find all JavaScript files first
fd -e js -e mjs -e jsx -e ts -e tsx | xargs rg "StreamReader" -A 3

# Also look for binding registration to see how StreamReader is exposed to JS
rg "EMSCRIPTEN_BINDINGS|class_<StreamReader>" -A 5

Length of output: 26037

src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1)

47-48: Ensure reader_options contains valid logLevelKey and timestampKey

Accessing reader_options["logLevelKey"].as<std::string>() without verifying the existence and type of the key may lead to exceptions. It's prudent to validate that these keys are present and contain string values before using them.

Run the following script to check the initialization of reader_options:

src/clp_ffi_js/ir/StreamReader.cpp (4)

120-122: Registration of ReaderOptions Type is Correct

The ReaderOptions type is correctly registered with Emscripten, accurately reflecting the TypeScript type {logLevelKey: string, timestampKey: string} | null. This ensures proper type checking and usage in JavaScript.


125-130: Emscripten Binding for IRProtocolErrorCode Enum is Accurate

The enumeration IRProtocolErrorCode is properly bound to JavaScript using Emscripten. All enum values—SUPPORTED, BACKWARD_COMPATIBLE, UNSUPPORTED, and INVALID—are correctly registered, allowing JavaScript code to utilize these constants effectively.


140-143: Exposed Method getIrProtocolErrorCode Matches Naming Conventions

The addition of getIrProtocolErrorCode to the Emscripten bindings exposes the corresponding C++ method to JavaScript. The method name is consistent with the project's naming conventions and provides necessary functionality to the JavaScript interface.


208-213: Exception Handling Enhances Error Reporting

The thrown ClpFfiJsException provides a clear and informative message when unable to create a reader for the IR stream with an unsupported version. This improves error reporting and aids in debugging.

Comment on lines +186 to +189
explicit StructuredIrStreamReader(
StreamReaderDataContext<StructuredIrDeserializer>&& stream_reader_data_context,
std::shared_ptr<std::vector<clp::ffi::KeyValuePairLogEvent>> deserialized_log_events
);
Copy link

@coderabbitai coderabbitai bot Nov 7, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Resolve mismatch between constructor parameter and member variable types

The constructor accepts stream_reader_data_context as an rvalue reference to StreamReaderDataContext<StructuredIrDeserializer>, but the member variable m_stream_reader_data_context is a std::unique_ptr<StreamReaderDataContext<StructuredIrDeserializer>>. This mismatch may lead to incorrect ownership semantics or compilation errors.

Apply this diff to correct the issue:

 explicit StructuredIrStreamReader(
-        StreamReaderDataContext<StructuredIrDeserializer>&& stream_reader_data_context,
+        std::unique_ptr<StreamReaderDataContext<StructuredIrDeserializer>>&& stream_reader_data_context,
         std::shared_ptr<std::vector<clp::ffi::KeyValuePairLogEvent>> deserialized_log_events
 );

Then, initialize m_stream_reader_data_context by moving the unique pointer:

m_stream_reader_data_context{std::move(stream_reader_data_context)}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The moved value is already wrapped by a make_unique pointer in the constructor.

Copy link

Choose a reason for hiding this comment

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

@junhaoliao, thank you for the clarification. Since the stream_reader_data_context is already wrapped by a std::make_unique pointer in the constructor, the ownership semantics are correctly handled.


✏️ Learnings added
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StructuredIrStreamReader.hpp:187-190
Timestamp: 2024-11-07T08:35:20.081Z
Learning: In the `StructuredIrStreamReader` constructor of `src/clp_ffi_js/ir/StructuredIrStreamReader.hpp`, the `stream_reader_data_context` parameter is already wrapped in a `std::make_unique`, ensuring it matches the member variable `m_stream_reader_data_context` of type `std::unique_ptr<StreamReaderDataContext<StructuredIrDeserializer>>`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines 160 to 167
auto const& log_level_pair{id_value_pairs.at(m_level_node_id.value())};
log_level = log_level_pair.has_value()
? static_cast<LogLevel>(
log_level_pair.value()
.get_immutable_view<clp::ffi::value_int_t>()
)
: log_level;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent potential exceptions when accessing id_value_pairs with missing keys

Using id_value_pairs.at() can throw an std::out_of_range exception if the key is not found. To ensure robustness, consider checking if the key exists before accessing it.

Apply this diff to safely access the map:

At lines 160-167:

-    auto const& log_level_pair{id_value_pairs.at(m_level_node_id.value())};
-    log_level = log_level_pair.has_value()
-                    ? static_cast<LogLevel>(
-                              log_level_pair.value()
-                                      .get_immutable_view<clp::ffi::value_int_t>()
-                      )
-                    : log_level;
+    auto log_level_it = id_value_pairs.find(m_level_node_id.value());
+    if (log_level_it != id_value_pairs.end()) {
+        auto const& log_level_pair = log_level_it->second;
+        if (log_level_pair.has_value()) {
+            log_level = static_cast<LogLevel>(
+                log_level_pair.value().get_immutable_view<clp::ffi::value_int_t>()
+            );
+        }
+    }

At lines 170-174:

-    auto const& timestamp_pair{id_value_pairs.at(m_timestamp_node_id.value())};
-    timestamp = timestamp_pair.has_value()
-                        ? timestamp_pair.value().get_immutable_view<clp::ffi::value_int_t>()
-                        : timestamp;
+    auto timestamp_it = id_value_pairs.find(m_timestamp_node_id.value());
+    if (timestamp_it != id_value_pairs.end()) {
+        auto const& timestamp_pair = timestamp_it->second;
+        if (timestamp_pair.has_value()) {
+            timestamp = timestamp_pair.value().get_immutable_view<clp::ffi::value_int_t>();
+        }
+    }

Also applies to: 170-174

Comment on lines +159 to +160
auto StreamReader::create(DataArrayTsType const& data_array, ReaderOptions const& reader_options)
-> std::unique_ptr<StreamReader> {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Potential API Breaking Change in StreamReader::create Signature

The create method of StreamReader now requires an additional parameter, ReaderOptions. This change may break existing code that calls StreamReader::create without the new parameter. Consider providing a default value or an overloaded method to maintain backward compatibility.

Apply this diff to add a default parameter value:

-auto StreamReader::create(DataArrayTsType const& data_array, ReaderOptions const& reader_options)
+auto StreamReader::create(DataArrayTsType const& data_array, ReaderOptions const& reader_options = {})
📝 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
auto StreamReader::create(DataArrayTsType const& data_array, ReaderOptions const& reader_options)
-> std::unique_ptr<StreamReader> {
auto StreamReader::create(DataArrayTsType const& data_array, ReaderOptions const& reader_options = {})
-> std::unique_ptr<StreamReader> {

src/clp_ffi_js/ir/StreamReader.cpp Outdated Show resolved Hide resolved
junhaoliao and others added 2 commits November 7, 2024 03:31
…ions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@@ -52,6 +51,9 @@ class StreamReader {
auto operator=(StreamReader&&) -> StreamReader& = delete;

// Methods
[[nodiscard]] virtual auto get_ir_protocol_error_code(
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need to expose this method? If it's just so that the caller can determine what type of IR stream we're reading, then I think it's clearer to return some kind of enum of Structured and Unstructured (and call the method something like get_ir_stream_type).

Copy link
Contributor

@davemarco davemarco Nov 7, 2024

Choose a reason for hiding this comment

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

@kirkrodrigues this is a hack since we are not decoding the message in C++. The log viewer needs to know now if it is recieving json (irv2), or an irv1 message. If recieving json, it needs to format the string.

Copy link
Member

Choose a reason for hiding this comment

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

Gotcha. I'd say an enum indicating that is still clearer than returning the protocol error code.


// JS types used as outputs
emscripten::enum_<clp::ffi::ir_stream::IRProtocolErrorCode>("IRProtocolErrorCode")
Copy link
Member

Choose a reason for hiding this comment

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

If we end up exposing IRProtocolErrorCode, let's name it IrProtocolErrorCode. I think it's better to avoid propagating the naming errors from CLP.

std::format("Unable to create reader for IR stream with version {}.", version)
};
}
auto const version_validation_result{clp::ffi::ir_stream::validate_protocol_version(version)};
Copy link
Member

Choose a reason for hiding this comment

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

Can move this into the try to reduce its scope.

Comment on lines 47 to 49
/**
* @return A reference to the reader.
*/
Copy link
Member

Choose a reason for hiding this comment

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

Seems unnecessary. Same with the get_deserializer docstring.

src/clp_ffi_js/ir/StructuredIrStreamReader.hpp Outdated Show resolved Hide resolved
auto const json{log_event.serialize_to_json()};
if (false == json.has_value()) {
SPDLOG_ERROR("Failed to decode message.");
break;
Copy link
Member

Choose a reason for hiding this comment

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

Should we continue instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let's instead place an empty object.

src/clp_ffi_js/ir/StructuredIrStreamReader.cpp Outdated Show resolved Hide resolved
LogLevel log_level{LogLevel::NONE};
if (m_level_node_id.has_value()) {
auto const& log_level_pair{id_value_pairs.at(m_level_node_id.value())};
log_level = log_level_pair.has_value()
Copy link
Member

Choose a reason for hiding this comment

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

  • If the log level isn't an int, get_immutable_view will throw, right? We should check that the value's type matches the expected type first (using is) and then retrieve the value.
  • If the value's type is a string, we should compare it against the log level strings, right?
  • Do we need the ternary? Personally, I would write this as: if has_value, set log_level.

Copy link
Collaborator Author

@junhaoliao junhaoliao Nov 7, 2024

Choose a reason for hiding this comment

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

Sure. As we discussed offline, let's leave log level handling till another PR. Let me apply the changes for timestamp after I remove log level related handling.

Comment on lines 171 to 173
timestamp = timestamp_pair.has_value()
? timestamp_pair.value().get_immutable_view<clp::ffi::value_int_t>()
: timestamp;
Copy link
Member

Choose a reason for hiding this comment

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

As mentioned above, we need to check the type and the ternary seems unnecessary.

StreamReaderDataContext<StructuredIrDeserializer>>(
std::move(stream_reader_data_context)
)},
m_deserialized_log_events{std::move(deserialized_log_events)} {}
Copy link
Member

Choose a reason for hiding this comment

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

Move this first to match the declaration order of member variables.

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

🧹 Outside diff range and nitpick comments (8)
src/clp_ffi_js/ir/StreamReaderDataContext.hpp (1)

44-45: Consider adding documentation for consistency.

The implementation looks good, but for consistency with the class-level documentation style, consider adding a brief docstring explaining the purpose and return value of this method.

Apply this diff to add documentation:

+    /**
+     * Gets the underlying reader interface.
+     * @return Reference to the ReaderInterface instance.
+     */
     [[nodiscard]] auto get_reader() -> clp::ReaderInterface& { return *m_reader; }
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (2)

36-68: Add validation for reader options.

While the implementation is solid, consider validating that the required reader options are present and of the correct type before accessing them.

 auto StructuredIrStreamReader::create(
         std::unique_ptr<ZstdDecompressor>&& zstd_decompressor,
         clp::Array<char> data_array,
         ReaderOptions const& reader_options
 ) -> StructuredIrStreamReader {
+    if (!reader_options.hasOwnProperty(cReaderOptionsTimestampKey.data()) ||
+        !reader_options[cReaderOptionsTimestampKey.data()].isString()) {
+        throw ClpFfiJsException{
+            clp::ErrorCode::ErrorCode_InvalidArgument,
+            __FILENAME__,
+            __LINE__,
+            "Missing or invalid timestampKey in reader options"
+        };
+    }
     auto deserialized_log_events{std::make_shared<std::vector<clp::ffi::KeyValuePairLogEvent>>()};

105-108: Enhance error logging for incomplete IR stream.

Include more details in the error log to help with debugging.

         if (std::errc::result_out_of_range == error) {
-            SPDLOG_ERROR("File contains an incomplete IR stream");
+            SPDLOG_ERROR(
+                "File contains an incomplete IR stream at position {}",
+                m_stream_reader_data_context->get_reader().tellg()
+            );
             break;
         }
src/clp_ffi_js/ir/StreamReader.cpp (1)

174-192: Document seek position requirements for different reader types.

The code saves the position before version check but only restores it for UnstructuredIrStreamReader. Consider adding a comment explaining why different reader types require different seek positions to improve maintainability.

src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (4)

37-42: Ensure member initializations match declaration order

In the constructor of IrUnitHandler, the initializer list initializes m_timestamp_key and m_deserialized_log_events in that order. However, in the class definition, m_deserialized_log_events is declared after other member variables. Since C++ initializes member variables in the order of declaration, not the order specified in the initializer list, this may lead to warnings or unintended behaviour. Consider reordering the member variable declarations to match the initializer list or vice versa to maintain consistency.


28-28: Expand abbreviation in documentation for clarity

In the class description, consider expanding "kv-pair" to "key-value pair" for better clarity and to maintain consistent terminology throughout the codebase.

Apply this diff:

-     * determine the schema-tree node ID of the timestamp kv-pair.
+     * determine the schema-tree node ID of the timestamp key-value pair.

34-35: Correct parameter documentation formatting

The description for the timestamp_key parameter is split across two lines improperly. Combining them into a single line improves readability and maintains standard documentation formatting.

Apply this diff:

-         * @param timestamp_key Key name of schema-tree node that contains the authoritative timestamp
-         * for events.
+         * @param timestamp_key Key name of the schema-tree node that contains the authoritative timestamp for events.

129-130: Add description for reader_options parameter

The create method's documentation lacks a description for the reader_options parameter. Providing a clear explanation helps users understand its purpose and how it affects the method's behaviour.

Apply this diff:

          * @param data_array The array backing `zstd_decompressor`.
+         * @param reader_options Options to configure the reader's behaviour.
          * @return The created instance.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between dc652ad and 37e6f30.

📒 Files selected for processing (6)
  • src/clp_ffi_js/ir/StreamReader.cpp (6 hunks)
  • src/clp_ffi_js/ir/StreamReader.hpp (3 hunks)
  • src/clp_ffi_js/ir/StreamReaderDataContext.hpp (1 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1 hunks)
  • src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/clp_ffi_js/ir/StreamReader.hpp
  • src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp
🧰 Additional context used
📓 Learnings (3)
src/clp_ffi_js/ir/StreamReader.cpp (2)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StreamReader.cpp:179-179
Timestamp: 2024-11-07T08:38:39.882Z
Learning: The function `clp::ffi::ir_stream::validate_protocol_version` used in `src/clp_ffi_js/ir/StreamReader.cpp` is imported from the CLP upstream library and may not be present in the local codebase.
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StructuredIrStreamReader.hpp:187-190
Timestamp: 2024-11-07T08:35:20.376Z
Learning: In the `StructuredIrStreamReader` constructor of `src/clp_ffi_js/ir/StructuredIrStreamReader.hpp`, the `stream_reader_data_context` parameter is already wrapped in a `std::make_unique`, ensuring it matches the member variable `m_stream_reader_data_context` of type `std::unique_ptr<StreamReaderDataContext<StructuredIrDeserializer>>`.
src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StructuredIrStreamReader.hpp:187-190
Timestamp: 2024-11-07T08:35:20.376Z
Learning: In the `StructuredIrStreamReader` constructor of `src/clp_ffi_js/ir/StructuredIrStreamReader.hpp`, the `stream_reader_data_context` parameter is already wrapped in a `std::make_unique`, ensuring it matches the member variable `m_stream_reader_data_context` of type `std::unique_ptr<StreamReaderDataContext<StructuredIrDeserializer>>`.
🔇 Additional comments (7)
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (3)

1-27: LGTM! Well-organized includes.

The includes are properly categorized and contain all necessary headers for the implementation.


28-35: LGTM! Well-defined constants.

Constants follow proper naming conventions and are appropriately scoped.


171-179: LGTM! Constructor implementation is correct.

The constructor properly initializes member variables and follows the established patterns.

src/clp_ffi_js/ir/StreamReader.cpp (4)

25-25: LGTM! Include statement follows project conventions.

The new include statement for StructuredIrStreamReader.hpp is correctly placed after system headers and aligns with the file's functionality.


120-127: LGTM! Emscripten bindings are well-structured.

The new bindings for ReaderOptions and IrStreamType are properly registered with appropriate TypeScript-like type annotations. The enum values follow the recommended naming convention from previous feedback.

Also applies to: 137-137


153-154: Skipping comment as this was previously addressed.

A past review comment already suggested adding a default value for the reader_options parameter to maintain backward compatibility.


202-207: LGTM! Clear and informative error handling.

The error handling for unsupported versions follows the project's exception pattern and provides a helpful error message that includes the version information.

Comment on lines +74 to +84
auto StructuredIrStreamReader::get_filtered_log_event_map() const -> FilteredLogEventMapTsType {
SPDLOG_ERROR(cLogLevelFilteringNotSupportedErrorMsg);
return FilteredLogEventMapTsType{emscripten::val::null()};
}

void StructuredIrStreamReader::filter_log_events(LogLevelFilterTsType const& log_level_filter) {
if (log_level_filter.isNull()) {
return;
}
SPDLOG_ERROR(cLogLevelFilteringNotSupportedErrorMsg);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider throwing an exception for unsupported operations.

Instead of logging errors and returning null values, consider throwing a ClpFfiJsException to explicitly indicate that these operations are not supported.

 auto StructuredIrStreamReader::get_filtered_log_event_map() const -> FilteredLogEventMapTsType {
-    SPDLOG_ERROR(cLogLevelFilteringNotSupportedErrorMsg);
-    return FilteredLogEventMapTsType{emscripten::val::null()};
+    throw ClpFfiJsException{
+        clp::ErrorCode::ErrorCode_NotSupported,
+        __FILENAME__,
+        __LINE__,
+        std::string{cLogLevelFilteringNotSupportedErrorMsg}
+    };
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 158 to 165
EM_ASM(
{ Emval.toValue($0).push([UTF8ToString($1), $2, $3, $4]); },
results.as_handle(),
json_result.value().dump().c_str(),
timestamp,
LogLevel::NONE,
log_event_idx + 1
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace EM_ASM with emscripten::val for better type safety.

Using emscripten::val provides better type safety and maintainability compared to EM_ASM.

-        EM_ASM(
-                { Emval.toValue($0).push([UTF8ToString($1), $2, $3, $4]); },
-                results.as_handle(),
-                json_result.value().dump().c_str(),
-                timestamp,
-                LogLevel::NONE,
-                log_event_idx + 1
-        );
+        auto event_array = emscripten::val::array();
+        event_array.set(0, emscripten::val(json_result.value().dump()));
+        event_array.set(1, emscripten::val(timestamp));
+        event_array.set(2, emscripten::val(static_cast<int>(LogLevel::NONE)));
+        event_array.set(3, emscripten::val(log_event_idx + 1));
+        results.call<void>("push", event_array);
📝 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
EM_ASM(
{ Emval.toValue($0).push([UTF8ToString($1), $2, $3, $4]); },
results.as_handle(),
json_result.value().dump().c_str(),
timestamp,
LogLevel::NONE,
log_event_idx + 1
);
auto event_array = emscripten::val::array();
event_array.set(0, emscripten::val(json_result.value().dump()));
event_array.set(1, emscripten::val(timestamp));
event_array.set(2, emscripten::val(static_cast<int>(LogLevel::NONE)));
event_array.set(3, emscripten::val(log_event_idx + 1));
results.call<void>("push", event_array);

Comment on lines +92 to +95
[[nodiscard]] static auto handle_end_of_stream() -> clp::ffi::ir_stream::IRErrorCode {
return clp::ffi::ir_stream::IRErrorCode::IRErrorCode_Success;
}

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove static keyword from handle_end_of_stream method

Similar to handle_utc_offset_change, the handle_end_of_stream method is declared as static but should be an instance method to properly implement the interface clp::ffi::ir_stream::IrUnitHandlerInterface. Removing the static keyword ensures the method can be overridden as intended.

Apply this diff to fix the issue:

-    [[nodiscard]] static auto handle_end_of_stream() -> clp::ffi::ir_stream::IRErrorCode {
+    [[nodiscard]] auto handle_end_of_stream() -> clp::ffi::ir_stream::IRErrorCode {
📝 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
[[nodiscard]] static auto handle_end_of_stream() -> clp::ffi::ir_stream::IRErrorCode {
return clp::ffi::ir_stream::IRErrorCode::IRErrorCode_Success;
}
[[nodiscard]] auto handle_end_of_stream() -> clp::ffi::ir_stream::IRErrorCode {
return clp::ffi::ir_stream::IRErrorCode::IRErrorCode_Success;
}

Comment on lines +62 to +69
[[nodiscard]] static auto handle_utc_offset_change(
[[maybe_unused]] clp::UtcOffset utc_offset_old,
[[maybe_unused]] clp::UtcOffset utc_offset_new
) -> clp::ffi::ir_stream::IRErrorCode {
SPDLOG_WARN("UTC offset change packets aren't handled currently.");

return clp::ffi::ir_stream::IRErrorCode::IRErrorCode_Success;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove static keyword from handle_utc_offset_change method

The method handle_utc_offset_change is declared as static, but it implements an interface method from clp::ffi::ir_stream::IrUnitHandlerInterface. Since interface methods are usually virtual and cannot be static, this might prevent proper overriding and cause incorrect behaviour. Removing the static keyword ensures correct interface implementation.

Apply this diff to fix the issue:

-    [[nodiscard]] static auto handle_utc_offset_change(
+    [[nodiscard]] auto handle_utc_offset_change(
         [[maybe_unused]] clp::UtcOffset utc_offset_old,
         [[maybe_unused]] clp::UtcOffset utc_offset_new
     ) -> clp::ffi::ir_stream::IRErrorCode {
📝 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
[[nodiscard]] static auto handle_utc_offset_change(
[[maybe_unused]] clp::UtcOffset utc_offset_old,
[[maybe_unused]] clp::UtcOffset utc_offset_new
) -> clp::ffi::ir_stream::IRErrorCode {
SPDLOG_WARN("UTC offset change packets aren't handled currently.");
return clp::ffi::ir_stream::IRErrorCode::IRErrorCode_Success;
}
[[nodiscard]] auto handle_utc_offset_change(
[[maybe_unused]] clp::UtcOffset utc_offset_old,
[[maybe_unused]] clp::UtcOffset utc_offset_new
) -> clp::ffi::ir_stream::IRErrorCode {
SPDLOG_WARN("UTC offset change packets aren't handled currently.");
return clp::ffi::ir_stream::IRErrorCode::IRErrorCode_Success;
}

src/clp_ffi_js/ir/StreamReader.hpp Outdated Show resolved Hide resolved
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp Outdated Show resolved Hide resolved
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp Outdated Show resolved Hide resolved
src/clp_ffi_js/ir/StructuredIrStreamReader.cpp Outdated Show resolved Hide resolved
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: 0

🧹 Outside diff range and nitpick comments (5)
src/clp_ffi_js/ir/StreamReader.hpp (3)

16-16: Documentation needed for ReaderOptions type

Please add documentation comments explaining the purpose and expected structure of the ReaderOptions type, following the same pattern as other emscripten val types in this file.


42-44: Update create method documentation

The method documentation needs to be updated to include details about the new reader_options parameter.


60-61: Add documentation for get_ir_stream_type method

The implementation nicely follows the suggested approach from previous reviews. However, please add documentation comments explaining:

  • The method's purpose
  • Return value meanings
  • Any preconditions or exceptions
src/clp_ffi_js/ir/StreamReader.cpp (2)

122-124: Consider renaming enum values for consistency.

Based on previous feedback, we should follow a consistent naming convention. Consider renaming the enum values to match the suggested style:

 emscripten::enum_<clp_ffi_js::ir::StreamType>("IrStreamType")
-        .value("STRUCTURED", clp_ffi_js::ir::StreamType::Structured)
-        .value("UNSTRUCTURED", clp_ffi_js::ir::StreamType::Unstructured);
+        .value("Structured", clp_ffi_js::ir::StreamType::Structured)
+        .value("Unstructured", clp_ffi_js::ir::StreamType::Unstructured);

167-190: Optimize try block scope.

The try block could be more focused by moving it to only wrap the operations that might throw ZstdDecompressor::OperationFailed:

 auto const version{get_version(*zstd_decompressor)};
+ auto const version_validation_result{clp::ffi::ir_stream::validate_protocol_version(version)};
+ 
+ if (clp::ffi::ir_stream::IRProtocolErrorCode::Supported == version_validation_result) {
 try {
-    auto const version_validation_result{clp::ffi::ir_stream::validate_protocol_version(version)};
-    if (clp::ffi::ir_stream::IRProtocolErrorCode::Supported == version_validation_result) {
-        zstd_decompressor->seek_from_begin(0);
-        return std::make_unique<StructuredIrStreamReader>(StructuredIrStreamReader::create(
-                std::move(zstd_decompressor),
-                std::move(data_buffer),
-                reader_options
-        ));
-    }
-    if (clp::ffi::ir_stream::IRProtocolErrorCode::BackwardCompatible == version_validation_result) {
-        zstd_decompressor->seek_from_begin(pos);
-        return std::make_unique<UnstructuredIrStreamReader>(UnstructuredIrStreamReader::create(
-                std::move(zstd_decompressor),
-                std::move(data_buffer)
-        ));
-    }
+     zstd_decompressor->seek_from_begin(0);
+     return std::make_unique<StructuredIrStreamReader>(StructuredIrStreamReader::create(
+             std::move(zstd_decompressor),
+             std::move(data_buffer),
+             reader_options
+     ));
 } catch (ZstdDecompressor::OperationFailed const& e) {
     throw ClpFfiJsException{
             clp::ErrorCode::ErrorCode_Failure,
             __FILENAME__,
             __LINE__,
             std::format("Unable to rewind zstd decompressor: {}", e.what())
     };
 }
+ }
+ 
+ if (clp::ffi::ir_stream::IRProtocolErrorCode::BackwardCompatible == version_validation_result) {
+ try {
+     zstd_decompressor->seek_from_begin(pos);
+     return std::make_unique<UnstructuredIrStreamReader>(UnstructuredIrStreamReader::create(
+             std::move(zstd_decompressor),
+             std::move(data_buffer)
+     ));
+ } catch (ZstdDecompressor::OperationFailed const& e) {
+     throw ClpFfiJsException{
+             clp::ErrorCode::ErrorCode_Failure,
+             __FILENAME__,
+             __LINE__,
+             std::format("Unable to rewind zstd decompressor: {}", e.what())
+     };
+ }
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 37e6f30 and 12dfb9e.

📒 Files selected for processing (5)
  • src/clp_ffi_js/ir/StreamReader.cpp (6 hunks)
  • src/clp_ffi_js/ir/StreamReader.hpp (3 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1 hunks)
  • src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp
  • src/clp_ffi_js/ir/UnstructuredIrStreamReader.hpp
🧰 Additional context used
📓 Learnings (2)
src/clp_ffi_js/ir/StreamReader.cpp (2)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StreamReader.cpp:179-179
Timestamp: 2024-11-07T08:38:39.882Z
Learning: The function `clp::ffi::ir_stream::validate_protocol_version` used in `src/clp_ffi_js/ir/StreamReader.cpp` is imported from the CLP upstream library and may not be present in the local codebase.
src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (1)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StructuredIrStreamReader.hpp:187-190
Timestamp: 2024-11-07T08:35:20.376Z
Learning: In the `StructuredIrStreamReader` constructor of `src/clp_ffi_js/ir/StructuredIrStreamReader.hpp`, the `stream_reader_data_context` parameter is already wrapped in a `std::make_unique`, ensuring it matches the member variable `m_stream_reader_data_context` of type `std::unique_ptr<StreamReaderDataContext<StructuredIrDeserializer>>`.
🔇 Additional comments (9)
src/clp_ffi_js/ir/StreamReader.hpp (2)

5-5: Header inclusions look good!

The addition of these headers properly supports the new StreamType enum and IR stream decoding functionality.

Also applies to: 8-8


22-25: Excellent implementation of the StreamType enum!

This implementation nicely addresses the previous review feedback by providing a clear, type-safe enum for distinguishing between stream types. The uint8_t base type is an appropriate choice for this use case.

src/clp_ffi_js/ir/StreamReader.cpp (3)

24-24: LGTM! Include statement follows project conventions.

The include statement for StructuredIrStreamReader.hpp is properly placed after system includes and follows the project's include ordering convention.


150-151: Previous review comment about API breaking change still applies.


199-204: LGTM! Error handling is comprehensive.

The error handling provides clear context by including the version information in the error message and uses appropriate error codes.

src/clp_ffi_js/ir/StructuredIrStreamReader.hpp (4)

37-42: Constructor of IrUnitHandler correctly initializes member variables

The constructor effectively uses move semantics to initialize m_timestamp_key and m_deserialized_log_events, ensuring efficient resource management.


50-55: handle_log_event method accurately buffers log events

The implementation successfully moves the log_event into m_deserialized_log_events, maintaining the integrity of the event data.


76-87: handle_schema_tree_node_insertion properly updates node IDs

The method correctly increments the m_current_node_id and assigns m_timestamp_node_id when the key matches m_timestamp_key, ensuring accurate tracking of schema-tree nodes.


134-138: Factory method create in StructuredIrStreamReader is well-defined

The static create method provides a clear and exception-safe way to instantiate StructuredIrStreamReader objects, accommodating different reader options.


// JS types used as outputs
emscripten::enum_<clp_ffi_js::ir::StreamType>("IrStreamType")
Copy link
Member

Choose a reason for hiding this comment

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

Just double-checking, the TS type should remain IrStreamType, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right, I keep the Ir prefix intentionally.

To be precise, types registered via this method are not TS types. For every enum, emscripten creates an object, which is comparable with any transpiled enum value. For example, Module.IrStreamType.STRUCTURED / Module.IrStreamType.UNSTRUCTURED can be used to check against the return values of reader.getIrStreamType() in our case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

src/clp_ffi_js/ir/StructuredIrStreamReader.cpp Outdated Show resolved Hide resolved
… strings with internal linkage - Apply suggestions from code review

Co-authored-by: kirkrodrigues <[email protected]>
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: 0

🧹 Outside diff range and nitpick comments (3)
src/clp_ffi_js/ir/StreamReader.hpp (2)

41-43: Update method documentation to include the new parameter.

The documentation block above the create() method should be updated to include details about the reader_options parameter.

     /**
      * Creates a `StreamReader` to read from the given array.
      *
      * @param data_array An array containing a Zstandard-compressed IR stream.
+     * @param reader_options Configuration options for the reader instance.
      * @return The created instance.
      * @throw ClpFfiJsException if any error occurs.
      */

59-60: Add documentation for the new virtual method.

The get_ir_stream_type() method should be documented to explain its purpose and return value.

+    /**
+     * Returns the type of IR stream being processed.
+     *
+     * @return The stream type (Structured or Unstructured).
+     */
     [[nodiscard]] virtual auto get_ir_stream_type() const -> StreamType = 0;
src/clp_ffi_js/ir/StreamReader.cpp (1)

172-191: Consider expanding the try-catch block scope

The try-catch block could be moved to encompass the version check as well, since get_version also uses the decompressor.

-    auto const version{get_version(*zstd_decompressor)};
-    try {
+    try {
+        auto const version{get_version(*zstd_decompressor)};
         auto const version_validation_result{clp::ffi::ir_stream::validate_protocol_version(version)
         };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 12dfb9e and cca920a.

📒 Files selected for processing (4)
  • src/clp_ffi_js/ir/StreamReader.cpp (6 hunks)
  • src/clp_ffi_js/ir/StreamReader.hpp (4 hunks)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp (1 hunks)
  • src/submodules/clp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/clp_ffi_js/ir/StructuredIrStreamReader.cpp
  • src/submodules/clp
🧰 Additional context used
📓 Learnings (1)
src/clp_ffi_js/ir/StreamReader.cpp (2)
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#26
File: src/clp_ffi_js/ir/StreamReader.cpp:35-45
Timestamp: 2024-11-04T20:55:01.745Z
Learning: An IRv1 version validation utility function is not planned to be added to CLP-core soon.
Learnt from: junhaoliao
PR: y-scope/clp-ffi-js#30
File: src/clp_ffi_js/ir/StreamReader.cpp:179-179
Timestamp: 2024-11-07T08:38:39.882Z
Learning: The function `clp::ffi::ir_stream::validate_protocol_version` used in `src/clp_ffi_js/ir/StreamReader.cpp` is imported from the CLP upstream library and may not be present in the local codebase.
🔇 Additional comments (7)
src/clp_ffi_js/ir/StreamReader.hpp (2)

5-5: LGTM! Header and type declarations are well-organized.

The addition of and ReaderOptions type declaration follows the existing patterns and best practices.

Also applies to: 15-15


21-24: Well-implemented enum addressing previous review feedback!

The StreamType enum class effectively addresses the previous review comments by providing a clear type-safe way to distinguish between stream types, rather than using protocol error codes.

src/clp_ffi_js/ir/StreamReader.cpp (5)

25-25: LGTM!

The include statement for StructuredIrStreamReader is properly placed and necessary for the implementation.


120-125: LGTM!

The Emscripten bindings are properly configured:

  • The IrStreamType enum follows the correct naming convention
  • ReaderOptions type registration matches its usage
  • The getIrStreamType method binding is correctly added

Also applies to: 135-135


151-152: Skipping comment about breaking change

This issue was already raised in a previous review.


168-191: LGTM! Version validation and reader creation logic is well-implemented

The code properly handles different IR stream versions by:

  • Saving the position before version check
  • Creating appropriate reader types based on version validation
  • Restoring the position for UnstructuredIrStreamReader

200-205: LGTM! Error handling is clear and informative

The exception provides detailed information about the unsupported version, which will help with debugging.

Copy link
Member

@kirkrodrigues kirkrodrigues left a comment

Choose a reason for hiding this comment

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

For the PR title, how about:

Add support for deserializing and decoding v0.1.0 IR streams, but without log-level filtering.

@junhaoliao
Copy link
Collaborator Author

For the PR title, how about:

Add support for deserializing and decoding v0.1.0 IR streams, but without log-level filtering.

How about:

Add support for deserializing and decoding v0.1.0 IR streams, but without log-level parsing and filtering.

@junhaoliao junhaoliao changed the title Add StructuredIrStreamReader which supports reading v0.1.0 IR streams without log level filtering. Add support for deserializing and decoding v0.1.0 IR streams, but without log-level parsing and filtering. Nov 9, 2024
@junhaoliao junhaoliao merged commit 5815f3b into y-scope:main Nov 9, 2024
3 checks passed
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.

3 participants