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

Implement InitialRoot option for Document attachment #913

Merged
merged 8 commits into from
Oct 23, 2024
Merged

Conversation

raararaara
Copy link
Contributor

@raararaara raararaara commented Oct 21, 2024

What this PR does / why we need it?

This PR introduces the initialRoot option during document attachment, allowing users to set initial values for documents with a predefined structure.

With this feature, developers can streamline the setup of their documents, ensuring a consistent initial state without having to check and assign default values manually after attaching the document.

Any background context you want to provide?

For more details regarding the policy related to the initialRoot option, please refer to the discussion in yorkie-team/yorkie#986.

The usage of the initialRoot option is demonstrated below, showcasing how it differs from the previous implementation:

// As is:
const doc = new yorkie.Document('key');
await client.attach(doc);

doc.update((root) => {
  if(!root.content) {
    root.content = new yorkie.Text();
  }
});
// To be:
const doc = new yorkie.Document('key');
await client.attach(doc, {
  initialRoot: {
    content: new yorkie.Text();
  }
});

What are the relevant tickets?

Related to #yorkie-team/yorkie#986
Addresses #yorkie-team/yorkie#669, #905

Checklist

  • Added relevant tests or not required
  • Didn't break anything

Summary by CodeRabbit

  • New Features

    • Enhanced the attach method to allow users to specify an initial root object when attaching documents.
    • Added comprehensive integration tests for document initialization with initial roots and various data types.
  • Bug Fixes

    • Improved handling of concurrent attachments with different initial roots to ensure correct local document state until sync occurs.

@raararaara raararaara marked this pull request as ready for review October 22, 2024 11:59
Copy link

coderabbitai bot commented Oct 22, 2024

Walkthrough

The changes in this pull request enhance the attach method of the Client class within the Yorkie SDK. An optional parameter, initialRoot, has been added to allow users to specify an initial root object when attaching a document. The method now processes this parameter to update the document's root object accordingly. Additionally, integration tests have been expanded to validate the new functionality, including tests for concurrent attachments and various data types.

Changes

File Path Change Summary
packages/sdk/src/client/client.ts Modified attach method to include an optional initialRoot parameter for document attachment.
packages/sdk/test/integration/document_test.ts Added multiple test cases for the initialRoot functionality, including handling of various data types.

Possibly related issues

Poem

🐰 In the meadow where documents play,
A new root joins the fray today!
With tests that hop and bounce around,
Initial roots in joy are found.
Attach with ease, let data flow,
In the world of Yorkie, watch it grow! 🌼


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.

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

🧹 Outside diff range and nitpick comments (1)
packages/sdk/test/integration/document_test.ts (1)

1254-1254: Simplify object destructuring by removing unnecessary renaming

In the destructuring assignment, the renaming name: name is unnecessary since the property name and variable name are identical. You can simplify it by just using name.

Apply this diff to simplify the code:

-for (const { name: name, input, expectedJSON } of testCases) {
+for (const { name, input, expectedJSON } of testCases) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between cdeeef7 and 8a2eceb.

📒 Files selected for processing (2)
  • packages/sdk/src/client/client.ts (2 hunks)
  • packages/sdk/test/integration/document_test.ts (4 hunks)
🧰 Additional context used
🪛 Biome
packages/sdk/test/integration/document_test.ts

[error] 1258-1258: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)


[error] 1278-1279: Don't use 'Object' as a type.

Prefer explicitly define the object shape. This type means "any non-nullable value", which is slightly better than 'unknown', but it's still a broad type.

(lint/complexity/noBannedTypes)

🔇 Additional comments (2)
packages/sdk/src/client/client.ts (2)

300-300: LGTM: New initialRoot option added to attach method.

The initialRoot option allows setting initial values for the document's root object when attaching it to the client. This addition enhances the flexibility of document initialization.


Line range hint 300-381: Summary: initialRoot option enhances document initialization flexibility.

The addition of the initialRoot option in the attach method provides a way to set initial values for the document's root object when attaching it to the client. This change enhances the SDK's flexibility in document initialization.

The implementation is correct, but could benefit from some type safety improvements as suggested in the previous comment. The change is well-contained and doesn't appear to have any negative impact on the rest of the Client class or file.

Overall, this is a valuable addition to the SDK's functionality.

packages/sdk/src/client/client.ts Outdated Show resolved Hide resolved
packages/sdk/test/integration/document_test.ts 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 (4)
packages/sdk/test/integration/document_test.ts (4)

1116-1121: Consider adding error handling test cases.

The test verifies successful initialization but doesn't cover error scenarios. Consider adding test cases for:

  • Invalid initial root structure
  • Malformed counter types
  • Invalid data types

Would you like me to help generate additional test cases for error scenarios?


1128-1140: Add assertions for field discarding behavior.

While the test verifies that existing fields are not overwritten, it would be clearer to explicitly assert which fields were discarded and why.

Add assertions to explicitly verify discarded fields:

 assert.equal(
   doc2.toSortedJSON(),
   '{"content":{"x":1,"y":1},"counter":0,"new":{"k":"v"}}',
 );
+// Verify discarded fields explicitly
+assert.equal(doc2.getRootObject().get('counter').getValue(), 0, 'counter should retain original value');
+assert.deepEqual(doc2.getRootObject().get('content'), { x: 1, y: 1 }, 'content should retain original structure');

1240-1241: Address the TODO comment for byte array and date cases.

The comment indicates missing test cases for byte arrays and dates. This gap in testing could lead to issues with these data types in production.

Would you like me to help implement the missing test cases for:

  1. Proper byte array handling with correct JSON serialization
  2. Date object handling with ISO string conversion

1254-1254: Remove unnecessary rename in destructuring.

The name parameter is unnecessarily renamed to itself in the destructuring.

Apply this diff to simplify the destructuring:

-for (const { name: name, input, expectedJSON } of testCases) {
+for (const { name, input, expectedJSON } of testCases) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8a2eceb and ae0e42e.

📒 Files selected for processing (2)
  • packages/sdk/src/client/client.ts (2 hunks)
  • packages/sdk/test/integration/document_test.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/sdk/src/client/client.ts
🧰 Additional context used
🪛 Biome
packages/sdk/test/integration/document_test.ts

[error] 1258-1258: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)

🔇 Additional comments (1)
packages/sdk/test/integration/document_test.ts (1)

1262-1275: 🛠️ Refactor suggestion

Consider using a more maintainable type definition approach.

The DocType interface could be improved for better maintainability.

Consider using a mapped type to reduce repetition:

-type DocType = {
-  tree?: Tree;
-  text?: Text;
-  counter?: Counter;
-  null?: null;
-  boolean?: boolean;
-  number?: number;
-  long?: Long;
-  object?: { k: string };
-  array?: Array<JSONElement>;
-  bytes?: Uint8Array;
-  // date: Date;
-};
+type TestValue = Tree | Text | Counter | null | boolean | number | Long | { k: string } | Array<JSONElement> | Uint8Array;
+type DocType = {
+  [K in typeof testCases[number]['name']]?: TestValue;
+};

Likely invalid or redundant comment.

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)
packages/sdk/test/integration/document_test.ts (3)

1146-1180: Consider enhancing concurrent attachment test coverage.

While the test effectively validates the basic concurrent attachment scenario, consider adding:

  1. Assertions to verify document states immediately after each sync operation
  2. Test cases for more complex concurrent modifications
  3. Verification of conflict resolution with different types of data

Would you like me to help generate additional test cases to improve coverage?


1262-1275: Consider improving type safety in DocType interface.

The current type definition could be enhanced to:

  1. Use more specific types for array elements
  2. Add proper JSDoc comments for each type
  3. Consider using branded types for better type safety

Apply this diff to improve type safety:

 type DocType = {
   tree?: Tree;
   text?: Text;
   counter?: Counter;
   null?: null;
   boolean?: boolean;
   number?: number;
   long?: Long;
   object?: { k: string };
-  array?: Array<JSONElement>;
+  array?: Array<number | string | boolean | null>;
   bytes?: Uint8Array;
   // date: Date;
 };

1258-1260: Remove unnecessary rename in template literal.

The variable name matches the property name, making the rename unnecessary.

Apply this diff to simplify the code:

-          const docKey = toDocKey(
-            `${task.name}-${name}-${new Date().getTime()}`,
-          );
+          const docKey = toDocKey(`${task.name}-${name}-${new Date().getTime()}`);
🧰 Tools
🪛 Biome

[error] 1258-1258: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ae0e42e and d65e904.

📒 Files selected for processing (2)
  • packages/sdk/src/client/client.ts (2 hunks)
  • packages/sdk/test/integration/document_test.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/sdk/src/client/client.ts
🧰 Additional context used
🪛 Biome
packages/sdk/test/integration/document_test.ts

[error] 1258-1258: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)

🔇 Additional comments (1)
packages/sdk/test/integration/document_test.ts (1)

1106-1144: LGTM! Well-structured test case for InitialRoot functionality.

The test case thoroughly validates:

  • Document initialization with initial root data
  • Proper handling of Counter and nested objects
  • Field overwrite behavior when attaching with existing fields

@raararaara raararaara requested a review from hackerwins October 23, 2024 06:29
Copy link
Member

@hackerwins hackerwins left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution.

@hackerwins hackerwins merged commit bd5e50f into main Oct 23, 2024
2 checks passed
@hackerwins hackerwins deleted the initial-root branch October 23, 2024 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants