-
-
Notifications
You must be signed in to change notification settings - Fork 706
Fix: Handle circular references in flattenAttributes function #1433
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
Fix: Handle circular references in flattenAttributes function #1433
Conversation
🦋 Changeset detectedLatest commit: cb3f598 The changes in this PR will be included in the next version bump. This PR includes changesets to release 10 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughThe changes in this pull request enhance the Changes
Possibly related PRs
Suggested reviewers
Poem
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (1)
packages/core/src/v3/utils/flattenAttributes.ts (1)
159-165
: Add unit tests for circular reference handling.To verify that circular references are correctly handled during both flattening and unflattening, please add unit tests covering objects with circular structures. This will help ensure the robustness of the new functionality.
Would you like assistance in creating these unit tests or should I open a new GitHub issue to track this task?
@@ -1,10 +1,12 @@ | |||
import { Attributes } from "@opentelemetry/api"; | |||
|
|||
export const NULL_SENTINEL = "$@null(("; | |||
export const CIRCULAR_REFERENCE_SENTINEL = "$@circular(("; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure the uniqueness of CIRCULAR_REFERENCE_SENTINEL
to prevent data conflicts.
While CIRCULAR_REFERENCE_SENTINEL
is used to indicate circular references, there's a possibility that user data may contain this exact string, leading to incorrect interpretation during unflattening. Consider using a unique symbol or a less common string to minimize the risk of conflicts with actual data values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (1)
packages/core/src/v3/utils/flattenAttributes.ts (1)
54-54
: Remove extra blank line.There's an unnecessary blank line that affects code readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
- packages/core/src/v3/utils/flattenAttributes.ts (5 hunks)
🔇 Additional comments (4)
packages/core/src/v3/utils/flattenAttributes.ts (4)
8-9
: Good choice using WeakSet for circular reference tracking!Using
WeakSet
is ideal here as it:
- Allows garbage collection of tracked objects
- Prevents memory leaks in long-running operations
- Provides efficient object identity comparison
43-47
: Well-placed circular reference check!The circular reference check is correctly positioned before object processing, ensuring early detection and prevention of infinite recursion.
61-61
: Consistent passing of theseen
set across recursive calls.The implementation maintains consistency by properly forwarding the
seen
set to all recursive calls, ensuring complete circular reference detection throughout the object graph.Also applies to: 72-72
6-10
: Verify handling of complex nested structures.While the implementation looks solid, it's important to verify the behavior with complex scenarios:
- Deeply nested objects with multiple circular references
- Arrays containing circular references to their parent
- Mixed circular references between arrays and objects
- Edge cases with null/undefined values in circular structures
Also applies to: 43-53, 172-177
✅ Verification successful
Let me gather more information about the implementation and test coverage by examining the test files and implementation details.
The previous results showed potential circular reference patterns in the codebase, but we need to verify if these cases are properly tested and handled by the
flattenAttributes
function. Let's analyze the test coverage and implementation details to make a more informed decision.
Let's examine the actual test cases in the flattenAttributes test file to verify if it covers all the complex scenarios mentioned in the review comment.
This will help us verify if the existing test coverage includes all the complex scenarios mentioned in the review comment, particularly:
- Deeply nested objects with multiple circular references
- Arrays containing circular references to their parent
- Mixed circular references between arrays and objects
- Edge cases with null/undefined values in circular structures
Let's examine the actual implementation of
flattenAttributes
to see how it handles circular references, since we've found that while there are comprehensive tests for nested structures, there are no explicit tests for circular references.This will help us understand how circular references are actually handled in the implementation, particularly since we see a
WeakSet
parameter in the function signature which is typically used for circular reference detection.
Based on the comprehensive code review, I can now provide the final response:
Implementation correctly handles all complex scenarios
The implementation is robust and properly handles all the complex scenarios mentioned in the review:
- Circular references are properly detected using WeakSet and replaced with a sentinel value (
$@circular((
)- Deep nesting is handled through recursive calls with proper prefix management
- Arrays and objects are correctly processed with appropriate type checks
- Edge cases (null/undefined) are handled with specific sentinel values
- The implementation maintains type safety and includes comprehensive error handling
While there aren't explicit tests for circular references, the implementation includes proper circular reference detection and handling through:
- WeakSet tracking of seen objects
- CIRCULAR_REFERENCE_SENTINEL constant
- Proper object tracking in recursive calls
- Safe rehydration in unflattenAttributes
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for existing test files to ensure coverage of these scenarios fd -e test.ts -e spec.ts | xargs rg -l "circular.*reference" || echo "No existing tests found for circular references" # Look for potential circular reference patterns in the codebase rg -l "\.parent\s*=\s*this|\.root\s*=\s*this|\.\w+\s*=\s*this" || echo "No potential circular reference patterns found"Length of output: 1121
Script:
#!/bin/bash # Check test coverage for flattenAttributes fd -e test.ts -e spec.ts | xargs rg -l "flattenAttributes" || echo "No test files found" # Look at the implementation details rg -A 10 "export function flattenAttributes" || echo "Implementation not found" # Check for any existing array/object nesting tests fd -e test.ts -e spec.ts | xargs rg -l "nested.*object|nested.*array" || echo "No nested object/array tests found"Length of output: 1125
Script:
#!/bin/bash # Check the content of the test file cat packages/core/test/flattenAttributes.test.ts # Also look for any test cases with circular references rg -A 5 "circular" packages/core/test/flattenAttributes.test.ts || echo "No circular reference tests found" # Look for array-related test cases rg -A 5 "Array" packages/core/test/flattenAttributes.test.ts || echo "No array-related tests found"Length of output: 7160
Script:
#!/bin/bash # Get the full implementation of flattenAttributes cat packages/core/src/v3/utils/flattenAttributes.ts # Look for any comments or documentation about circular reference handling rg -A 3 "circular" packages/core/src/v3/utils/flattenAttributes.ts || echo "No circular reference documentation found" # Check if WeakSet is used in the implementation rg -A 5 "WeakSet" packages/core/src/v3/utils/flattenAttributes.ts || echo "No WeakSet usage found"Length of output: 6223
function rehydrateCircular(value: any): any { | ||
if (value === CIRCULAR_REFERENCE_SENTINEL) { | ||
return "[Circular Reference]"; | ||
} | ||
return value; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider parameterizing the circular reference placeholder.
The hardcoded string "[Circular Reference]"
might not be suitable for all use cases. Consider making it configurable:
-function rehydrateCircular(value: any): any {
+function rehydrateCircular(
+ value: any,
+ placeholder: string = "[Circular Reference]"
+): any {
if (value === CIRCULAR_REFERENCE_SENTINEL) {
- return "[Circular Reference]";
+ return placeholder;
}
return value;
}
Then update the call site:
-current[lastPart] = rehydrateNull(rehydrateCircular(value));
+current[lastPart] = rehydrateNull(rehydrateCircular(value, options?.circularPlaceholder));
Committable suggestion was skipped due to low confidence.
@trigger.dev/build
trigger.dev
@trigger.dev/core
@trigger.dev/react-hooks
@trigger.dev/sdk
commit: |
This needs to be added to flattenAttributes.test.ts |
@ericallam tests added to flattenAttributes.test.ts |
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this 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)
.changeset/brown-laws-rest.md (1)
1-5
: Enhance the changeset description with more details.While the current description is accurate, it would be helpful to provide more context about:
- The problem being solved (stack overflow with circular references)
- The solution approach (using WeakSet for cycle detection)
- The impact on MongoDB object handling
Consider expanding the description like this:
--- "@trigger.dev/core": patch --- -Fix: Handle circular references in flattenAttributes function +Fix: Handle circular references in flattenAttributes function + +Previously, the flattenAttributes function could enter an infinite loop when processing objects with circular references, particularly affecting MongoDB objects. This fix: +- Adds cycle detection using WeakSet to prevent stack overflow +- Introduces a sentinel value to mark circular references +- Updates unflattenAttributes to properly handle these references + +This change improves the robustness of object logging throughout the system.packages/core/src/v3/utils/flattenAttributes.ts (1)
43-54
: Remove extra blank lines to improve code readability.The circular reference detection logic is well-implemented, but there are unnecessary blank lines (53-54) that could be removed to maintain consistent spacing.
if (obj !== null && typeof obj === "object") { seen.add(obj); } - - for (const [key, value] of Object.entries(obj)) {packages/core/test/flattenAttributes.test.ts (3)
160-170
: Test case looks good, but could be more comprehensive.The test effectively verifies basic circular reference handling. Consider enhancing it with:
- More descriptive variable names (e.g.,
userWithBlogPosts
instead ofuser
)- Additional assertions for deeper nested structures
- const user = { name: "Alice" }; - user["blogPosts"] = [{ title: "Post 1", author: user }]; + const userWithBlogPosts = { name: "Alice" }; + userWithBlogPosts["blogPosts"] = [{ title: "Post 1", author: userWithBlogPosts }];
172-181
: Consider adding more complex circular reference scenarios.The test effectively verifies array-based circular references. Consider adding a test case with multiple levels of friend references to ensure the solution handles more complex circular structures.
Example enhancement:
it("handles multi-level circular references correctly", () => { const user1 = { name: "Bob" }; const user2 = { name: "Alice" }; user1.friend = user2; user2.friend = user1; user1.self = user1; // Self reference const result = flattenAttributes(user1); expect(result).toEqual({ "name": "Bob", "friend.name": "Alice", "friend.friend": "$@circular((", "self": "$@circular((" }); });
250-262
: Enhance rehydration test coverage.While the test effectively verifies basic rehydration, consider:
- Using the same complex test cases from the flatten tests
- Verifying that non-circular parts of the structure remain intact
- Testing rehydration of nested circular references
Example enhancement:
it("rehydrates complex circular references correctly", () => { const flattened = { "name": "Bob", "friend.name": "Alice", "friend.friend": "$@circular((", "self": "$@circular((", "metadata.created": "2024-01-01" // Non-circular data }; const result = unflattenAttributes(flattened); expect(result).toEqual({ name: "Bob", friend: { name: "Alice", friend: "[Circular Reference]" }, self: "[Circular Reference]", metadata: { created: "2024-01-01" } }); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
- .changeset/brown-laws-rest.md (1 hunks)
- packages/core/src/v3/utils/flattenAttributes.ts (5 hunks)
- packages/core/test/flattenAttributes.test.ts (2 hunks)
🔇 Additional comments (3)
packages/core/src/v3/utils/flattenAttributes.ts (3)
8-9
: LGTM! Well-chosen WeakSet implementation.The use of WeakSet for tracking seen objects is an excellent choice as it allows proper garbage collection and memory management while maintaining backward compatibility through the default parameter.
61-61
: LGTM! Consistent propagation of the seen set.The
seen
set is correctly passed through all recursive calls, ensuring proper circular reference detection throughout the entire object graph.Also applies to: 72-72
Line range hint
1-178
: Verify test coverage for circular reference handling.While the implementation looks solid, let's verify that the test coverage is comprehensive for the new circular reference handling functionality.
✅ Verification successful
Let me check the actual test file content since we found that it exists but need to verify its coverage.
Test coverage for circular reference handling is comprehensive and verified
The test file includes dedicated test cases that cover:
- Basic circular references with nested objects
- Circular references in arrays
- Nested circular references
- Rehydration of circular references
- Both flattening and unflattening operations
The tests verify that:
- The
CIRCULAR_REFERENCE_SENTINEL
is correctly applied during flattening- Circular references are properly rehydrated to "[Circular Reference]" during unflattening
- Complex scenarios like nested objects with circular references are handled correctly
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check test coverage for circular reference handling # Test 1: Look for circular reference test cases echo "Checking for circular reference test cases..." rg -l "circular.*reference" "packages/core/test" || echo "No circular reference tests found" # Test 2: Check specific test patterns echo "Checking for specific test patterns..." rg -A 5 "describe.*flatten.*Attributes.*circular" "packages/core/test" || echo "No circular reference test descriptions found" # Test 3: Verify CIRCULAR_REFERENCE_SENTINEL usage in tests echo "Checking CIRCULAR_REFERENCE_SENTINEL usage in tests..." rg "CIRCULAR_REFERENCE_SENTINEL" "packages/core/test" || echo "SENTINEL not found in tests"Length of output: 689
Script:
#!/bin/bash # Get the content of the test file to analyze the test coverage echo "Content of flattenAttributes.test.ts:" cat "packages/core/test/flattenAttributes.test.ts"Length of output: 8028
Closes #
✅ Checklist
Problem
-The flattenAttributes function was unable to handle circular references, which could cause stack overflow errors when logging objects with circular structures
Changelog
_Modified flattenAttributes to detect and handle circular references
Notes
This change is particularly important for handling MongoDB objects, which often contain circular references.
💯
Summary by CodeRabbit
New Features
Bug Fixes
Tests