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

Detach documents when client is deactivated #1036

Merged
merged 8 commits into from
Oct 18, 2024
Merged

Conversation

hackerwins
Copy link
Member

@hackerwins hackerwins commented Oct 16, 2024

What this PR does / why we need it:

This PR implements the detachment of documents attached to clients upon client deactivation. Previously, the status of the document was only changed to 'detach' within DB.clients.ClientDocInfo.Status, leading to issues where the deactivated client's presence remained active and presence change events were not communicated to other clients.

With this change, on client deactivation, the document's packs.PushPull method is called directly to execute the complete detachment process.

Moreover, since the Yorkie cluster sharding mechanism assigns specific documents to specific servers, the server managing client deactivation may not always be the one handling the document. Therefore, in such cases, a request will be made to the server currently responsible for the document to detach it properly. To facilitate this communication across the cluster, a new ClusterService has been added.

Follow-up tasks that need to be addressed after this PR include:

  • Implementing authentication for cluster communication and preventing external exposure.
  • Eliminating redundant database resource requests between clients.Deactivate and server.DetachDocument.
  • Improving the p.Clear ChangePack creation logic.
  • Introducing a connection pool for clusterClient.

Which issue(s) this PR fixes:

Fixes #602

Special notes for your reviewer:

Does this PR introduce a user-facing change?:


Additional documentation:


Checklist:

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

Summary by CodeRabbit

  • New Features

    • Introduced new endpoints for detaching documents in both the Yorkie API and ClusterService.
    • Added support for API key authentication in the new system and cluster services.
    • Enhanced client functionality with new methods for document management and connection handling.
  • Improvements

    • Standardized formatting across OpenAPI specifications for better readability.
    • Improved handling of client deactivation to include project context.
    • Updated deployment configuration to support backend gateway connections.
  • Bug Fixes

    • Corrected grammatical errors in service descriptions.
  • Documentation

    • Updated OpenAPI specifications to version 3.1.0 with comprehensive metadata.

Copy link

coderabbitai bot commented Oct 16, 2024

Walkthrough

The pull request introduces new OpenAPI specification files for the Yorkie API, version 3.1.0, detailing metadata, server environments, and new endpoints for detaching documents. Protocol Buffers files define the SystemService and ClusterService, each with a DetachDocument RPC method. Significant updates to the clients package restructure client deactivation logic, while new server structs manage document detachment in RPC contexts. The system/client.go and cluster/client.go files implement clients for the admin service, including methods for managing document detachment.

Changes

File Path Change Summary
api/docs/yorkie/v1/system.openapi.yaml New OpenAPI spec file created, defining a system service with a new endpoint for detaching documents.
api/docs/yorkie/v1/cluster.openapi.yaml New OpenAPI spec file created for ClusterService with a new endpoint for detaching documents.
api/yorkie/v1/system.proto New Protocol Buffers file defining a service for document detachment with associated request/response types.
api/yorkie/v1/cluster.proto New Protocol Buffers file defining a ClusterService for managing document detachment.
server/clients/clients.go Updated Deactivate and Activate methods to include project context and altered deactivation logic.
server/rpc/system_server.go Introduced systemServer struct with methods for managing document detachment in RPC context.
server/rpc/cluster_server.go Introduced clusterServer struct with methods for managing document detachment in cluster context.
server/rpc/server.go Added handlers for both system and cluster services in the HTTP request multiplexer.
system/client.go New client implementation for admin service, including methods for managing document detachment.
cluster/client.go New client implementation for cluster service, including methods for managing document detachment.
build/charts/yorkie-cluster/templates/yorkie/deployment.yaml Added --backend-gateway-addr argument for backend connection in deployment configuration.
server/packs/packs_test.go Updated test logic for client information updates during synchronization, ensuring correct error handling.
server/rpc/yorkie_server.go Updated client activation and deactivation methods to include project context and backend reference.

Possibly related PRs

Suggested labels

enhancement 🌟

🐇 In the land of code where changes bloom,
Formatting and structure make room,
A new service to detach with grace,
Enhancing the API, we quicken the pace.
With single quotes shining bright,
Our documentation now feels just right! 🌟


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5528d78 and f89f6a4.

📒 Files selected for processing (2)
  • server/rpc/cluster_server.go (1 hunks)
  • server/rpc/server.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • server/rpc/cluster_server.go
  • server/rpc/server.go

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

🧹 Outside diff range and nitpick comments (12)
api/yorkie/v1/system.proto (2)

1-24: Consider adjusting the directory structure to match the package name.

The package name yorkie.v1 is appropriate, but the static analysis tool suggests that files with this package should be within a directory "yorkie/v1" relative to the root, rather than "api/yorkie/v1".

Consider one of the following options:

  1. Move this file to a "yorkie/v1" directory if it aligns with your project structure.
  2. If the current structure is intentional, you may want to configure the static analysis tool to ignore this warning for your specific project setup.
🧰 Tools
🪛 buf

18-18: Files with package "yorkie.v1" must be within a directory "yorkie/v1" relative to root but were in directory "api/yorkie/v1".

(PACKAGE_DIRECTORY_MATCH)


25-28: Consider renaming request and response types to follow standard conventions.

The static analysis tool suggests that the RPC request and response types should follow a standard naming convention.

Consider renaming the types as follows:

  1. DetachDocumentRequestBySystem to DetachDocumentRequest or SystemServiceDetachDocumentRequest
  2. DetachDocumentResponseBySystem to DetachDocumentResponse or SystemServiceDetachDocumentResponse

This change would improve consistency with common protobuf naming conventions and make the API more intuitive for developers familiar with these standards.

🧰 Tools
🪛 buf

27-27: RPC request type "DetachDocumentRequestBySystem" should be named "DetachDocumentRequest" or "SystemServiceDetachDocumentRequest".

(RPC_REQUEST_STANDARD_NAME)


27-27: RPC response type "DetachDocumentResponseBySystem" should be named "DetachDocumentResponse" or "SystemServiceDetachDocumentResponse".

(RPC_RESPONSE_STANDARD_NAME)

🪛 GitHub Check: build

[failure] 27-27:
RPC request type "DetachDocumentRequestBySystem" should be named "DetachDocumentRequest" or "SystemServiceDetachDocumentRequest".


[failure] 27-27:
RPC response type "DetachDocumentResponseBySystem" should be named "DetachDocumentResponse" or "SystemServiceDetachDocumentResponse".

api/docs/yorkie/v1/system.openapi.yaml (2)

12-24: Consider adding a description for the DetachDocument endpoint.

The path structure and references are well-defined. However, the description field for the DetachDocument endpoint is empty. Adding a brief description would improve the API documentation and help users understand the purpose of this endpoint.

Consider adding a description like:

description: Detaches a document from a client in the specified project.

105-106: Address TODO comment for future improvement.

There's a TODO comment suggesting a potential improvement to replace certain fields with more structured types.

Would you like me to create a GitHub issue to track this improvement? The issue could be titled "Refactor DetachDocumentRequestBySystem to use structured types" and include the following description:
"Consider replacing the fields in DetachDocumentRequestBySystem with types.Project, types.Client, and types.DocumentSummary for improved structure and type safety."

server/server.go (1)

Line range hint 153-157: LGTM with a minor suggestion for error handling

The changes to the DeactivateClient method look good. The addition of the project parameter and its usage in the clients.Deactivate function call improves the flexibility of the method by allowing project-specific client deactivation. This aligns well with the PR objective of detaching documents when a client is deactivated.

The fallback to the default project maintains backwards compatibility, which is a good practice.

Consider wrapping the error returned from clients.Deactivate with additional context:

-	_, err = clients.Deactivate(ctx, r.backend.DB, project, types.ClientRefKey{
+	_, err = clients.Deactivate(ctx, r.backend.DB, project, types.ClientRefKey{
 		ProjectID: project.ID,
 		ClientID:  types.IDFromActorID(c1.ID()),
 	})
-	return err
+	if err != nil {
+		return fmt.Errorf("failed to deactivate client: %w", err)
+	}
+	return nil

This will provide more context if an error occurs during client deactivation.

pkg/document/internal_document.go (1)

375-381: LGTM! Consider adding a brief comment for clarity.

The ToDocument method looks good and serves its purpose well. It correctly converts an InternalDocument to a Document type.

Consider adding a brief comment to explain the purpose of this method and any important details about the conversion process. For example:

// ToDocument converts the InternalDocument to a Document.
// Note: The returned Document shares the same underlying data as the InternalDocument.
func (d *InternalDocument) ToDocument() *Document {
    // ... (existing implementation)
}

This additional comment would help other developers understand the method's behavior and any potential side effects.

pkg/document/document.go (1)

457-459: Add documentation for the setInternalDoc method.

The newly added setInternalDoc method lacks documentation. To improve code maintainability and help other developers understand its purpose, please add a comment explaining the method's functionality, when it should be used, and any potential side effects.

Consider adding a comment like this:

// setInternalDoc replaces the internal document of the Document.
// This method should be used with caution as it directly modifies
// the internal state without any validation.
server/rpc/yorkie_server.go (1)

97-100: LGTM! Consider enhancing error handling.

The addition of the project parameter to the clients.Deactivate function call is a good improvement. It aligns with the PR objective of detaching documents when a client is deactivated by providing the necessary project context.

Consider wrapping the clients.Deactivate call in a more descriptive error:

-	_, err = clients.Deactivate(ctx, s.backend.DB, project, types.ClientRefKey{
+	_, err = clients.Deactivate(ctx, s.backend.DB, project, types.ClientRefKey{
 		ProjectID: project.ID,
 		ClientID:  types.IDFromActorID(actorID),
 	})
+	if err != nil {
+		return nil, fmt.Errorf("failed to deactivate client: %w", err)
+	}

This change would provide more context in case of an error, making debugging easier.

server/clients/housekeeping.go (2)

91-95: Ensure CandidatePair aligns with Go naming conventions

The fields in CandidatePair are unexported (start with lowercase letters). If CandidatePair is intended to be used outside its package, consider exporting the fields by capitalizing them. If it's only for internal use, this is acceptable.


126-129: Simplify determination of topProjectID

The logic for setting topProjectID can be simplified for readability.

Consider the following refactored code:

var topProjectID types.ID = database.DefaultProjectID
if len(projectInfos) == projectFetchSize {
	topProjectID = projectInfos[len(projectInfos)-1].ID
}
system/client.go (2)

154-156: Use standard Go comment style for function documentation

The comment for withShardKey uses block comment syntax /** ... */, which is unconventional in Go. Go documentation comments should start with the function name and use line comments (//).

Apply this diff to fix the comment style:

-/**
-* withShardKey returns a context with the given shard key in metadata.
- */
+// withShardKey returns a request with the given shard key added to the headers.

95-107: Consider renaming functions to avoid confusion between Dial methods

Currently, both the constructor function and the method on Client are named Dial. This may lead to confusion when reading the code.

Consider renaming the constructor function Dial (lines 95-107) to DialClient or NewClient for clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9513091 and 31cc753.

⛔ Files ignored due to path filters (1)
  • api/yorkie/v1/system.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (18)
  • api/docs/yorkie/v1/admin.openapi.yaml (56 hunks)
  • api/docs/yorkie/v1/resources.openapi.yaml (65 hunks)
  • api/docs/yorkie/v1/system.openapi.yaml (1 hunks)
  • api/docs/yorkie/v1/yorkie.openapi.yaml (50 hunks)
  • api/yorkie/v1/system.proto (1 hunks)
  • api/yorkie/v1/v1connect/system.connect.go (1 hunks)
  • api/yorkie/v1/yorkie.proto (1 hunks)
  • pkg/document/document.go (1 hunks)
  • pkg/document/internal_document.go (1 hunks)
  • server/backend/database/client_info.go (1 hunks)
  • server/backend/database/mongo/client.go (1 hunks)
  • server/clients/clients.go (2 hunks)
  • server/clients/housekeeping.go (2 hunks)
  • server/rpc/server.go (1 hunks)
  • server/rpc/system_server.go (1 hunks)
  • server/rpc/yorkie_server.go (1 hunks)
  • server/server.go (1 hunks)
  • system/client.go (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • api/docs/yorkie/v1/admin.openapi.yaml
  • api/docs/yorkie/v1/resources.openapi.yaml
  • api/docs/yorkie/v1/yorkie.openapi.yaml
  • api/yorkie/v1/yorkie.proto
🧰 Additional context used
🪛 buf
api/yorkie/v1/system.proto

18-18: Files with package "yorkie.v1" must be within a directory "yorkie/v1" relative to root but were in directory "api/yorkie/v1".

(PACKAGE_DIRECTORY_MATCH)


27-27: RPC request type "DetachDocumentRequestBySystem" should be named "DetachDocumentRequest" or "SystemServiceDetachDocumentRequest".

(RPC_REQUEST_STANDARD_NAME)


27-27: RPC response type "DetachDocumentResponseBySystem" should be named "DetachDocumentResponse" or "SystemServiceDetachDocumentResponse".

(RPC_RESPONSE_STANDARD_NAME)

🪛 GitHub Check: build
api/yorkie/v1/system.proto

[failure] 27-27:
RPC request type "DetachDocumentRequestBySystem" should be named "DetachDocumentRequest" or "SystemServiceDetachDocumentRequest".


[failure] 27-27:
RPC response type "DetachDocumentResponseBySystem" should be named "DetachDocumentResponse" or "SystemServiceDetachDocumentResponse".

🔇 Additional comments (19)
api/yorkie/v1/system.proto (1)

30-38: Review TODO comment and consider response message structure.

  1. The TODO comment suggests replacing simple string fields with more complex types. This could indeed provide more robust type checking and potentially more functionality.

Consider creating a follow-up task to implement this suggestion, as it could improve the API's type safety and expressiveness.

  1. The DetachDocumentResponseBySystem message is currently empty.

Is this intentional? If no response data is needed, this is fine. However, if you anticipate adding fields in the future or if there's any useful information that could be returned (e.g., a success flag or timestamp), consider adding them now to future-proof the API.

✅ Verification successful

Verified: TODO can be addressed using existing types, and the response message structure is appropriate.

  • The types Project, Client, and DocumentSummary are well-defined and widely used, supporting the proposed replacement of string fields.
  • The DetachDocumentResponseBySystem message is intentionally empty with no fields expected by any usage, confirming its correctness.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any usages of DetachDocumentResponseBySystem that expect fields
rg "DetachDocumentResponseBySystem" --type go -C 5

Length of output: 9913


Script:

#!/bin/bash
# Find definitions of types.Project, types.Client, and types.DocumentSummary
rg "type\s+Project\s+struct" --type go
rg "type\s+Client\s+struct" --type go
rg "type\s+DocumentSummary\s+struct" --type go

# Check usages of types.Project, types.Client, and types.DocumentSummary in the codebase
rg "types\.Project" --type go
rg "types\.Client" --type go
rg "types\.DocumentSummary" --type go

Length of output: 11404

api/docs/yorkie/v1/system.openapi.yaml (5)

1-6: LGTM: API metadata is well-defined.

The OpenAPI version and API information are correctly specified. The use of OpenAPI 3.1.0 is appropriate, and the API metadata (title, description, and version) is concise and informative.


7-11: LGTM: Server environments are well-defined.

The server definitions for both production and local environments are clear and appropriate. This setup facilitates easy switching between development and production environments.


25-115: LGTM: Components section is well-structured.

The components section is comprehensive and follows OpenAPI standards. The schemas for error handling and the DetachDocument operation are well-defined, providing clear structure for requests and responses.


116-120: LGTM: Security scheme is well-defined.

The API key authentication scheme is appropriately defined. Using the Authorization header for the API key follows common security practices for API authentication.


123-125: LGTM: Tag is well-defined with a clear description.

The tag for yorkie.v1.SystemService is appropriately defined with a clear and concise description. This provides useful context for the API's structure and purpose.

server/rpc/server.go (1)

76-76: Approve the addition of SystemService handler with suggestions.

The addition of the SystemService handler is consistent with the existing architecture and enhances the server's functionality. However, there are a couple of points to consider:

  1. Unlike the YorkieService and AdminService handlers, the SystemService handler doesn't use the opts... parameter. Is this intentional? If not, consider adding it for consistency:
-mux.Handle(v1connect.NewSystemServiceHandler(newSystemServer(be)))
+mux.Handle(v1connect.NewSystemServiceHandler(newSystemServer(be), opts...))
  1. The newSystemServer function is not visible in this file. Please ensure it exists and is properly implemented in the appropriate package.

To verify the existence and implementation of the newSystemServer function, please run the following script:

✅ Verification successful

Verified: SystemService handler addition

The newSystemServer function and the systemServer struct are properly implemented and integrated. The addition of the SystemService handler is consistent with the existing architecture.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and implementation of newSystemServer function

# Test: Search for the newSystemServer function definition
rg --type go -g '!*_test.go' 'func newSystemServer\('

# Test: Check if the SystemServer type is defined
rg --type go -g '!*_test.go' 'type SystemServer struct'

Length of output: 204


Script:

#!/bin/bash
# Description: Verify the existence and implementation of systemServer struct

# Test: Search for the systemServer struct definition
rg --type go -g '!*_test.go' 'type systemServer struct'

Length of output: 112

server/backend/database/client_info.go (1)

203-212: Add a comment explaining the method's purpose.

The implementation of the ServerSeq method looks good. However, it would be beneficial to add a comment explaining the purpose of this method and when it should be used. This will improve code readability and maintainability.

Consider adding a comment like this:

// ServerSeq returns the server sequence of the given document.
// It returns an error if the document is not found in the client's document map.

LGTM with a minor suggestion.

The implementation is correct and consistent with the existing codebase. As a minor suggestion, consider checking if the document is in the "attached" state before returning the ServerSeq. This could prevent potential issues if the sequence is accessed for detached or removed documents.

Let's verify the usage of this new method in the codebase:

✅ Verification successful

The ServerSeq method is utilized appropriately across the codebase.

The usage of the ServerSeq method in various components confirms that it integrates well and functions as intended. No issues were identified during the verification process.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of the new ServerSeq method

# Search for ServerSeq method calls
echo "Searching for ServerSeq method calls:"
rg --type go "ServerSeq\(" --glob '!server/backend/database/client_info.go'

# Search for potential places where ServerSeq might be useful
echo "Searching for potential places where ServerSeq might be used:"
rg --type go "ServerSeq|server_seq" --glob '!server/backend/database/client_info.go'

Length of output: 32764

pkg/document/document.go (1)

457-459: Verify the intended use and safety of setInternalDoc.

The setInternalDoc method allows direct modification of the internal document without any apparent validation or consistency checks. This could potentially lead to inconsistent state if not used carefully.

Please confirm:

  1. Is this method intended for internal use only (e.g., during synchronization or recovery)?
  2. Are there any scenarios where this method could lead to data inconsistency?
  3. Should any validation be added to ensure the new internal document is in a valid state?

Consider adding safeguards or validation if necessary to prevent potential issues.

server/rpc/system_server.go (7)

1-15: License header is correctly included

The Apache License header is properly added to the new file.


19-37: Imports are organized appropriately

The necessary packages are imported, and there are no unused imports.


39-41: Definition of systemServer

The systemServer struct is correctly defined with a reference to backend.Backend.


43-48: Constructor newSystemServer is implemented properly

The function newSystemServer initializes a new systemServer instance with the provided backend.


79-83: Handle locker unlock errors appropriately

In the deferred function, when unlocking the locker, you log the error if it occurs. While logging is helpful, consider if additional actions are necessary to handle such errors, depending on how critical the unlock failure might be for your application.


121-134: Verify the correctness of PushPullOptions

Confirm that setting the Mode to types.SyncModePushPull and the Status to document.StatusDetached aligns with the intended behavior for detaching documents. Ensure that these options correctly reflect the desired state changes in the document's lifecycle.


136-137: Response creation is appropriate

The function correctly returns a new response indicating the successful detachment of the document.

api/yorkie/v1/v1connect/system.connect.go (3)

105-112: Review HTTP handler paths for correct routing.

In the NewSystemServiceHandler function, the HTTP handler routes requests based on URL paths:

Please verify that:

  • The base path "/yorkie.v1.SystemService/" correctly matches incoming requests.
  • There are no conflicts with other service routes.
  • All expected procedures are properly handled in the switch statement.

This ensures that requests are routed to the correct handlers without unintended collisions.


85-87: ⚠️ Potential issue

Ensure the DetachDocument method is correctly implemented and tested.

The DetachDocument method has been added to the SystemServiceClient. Please verify that:

  • The method is properly implemented on both client and server sides.
  • All logic inside the method aligns with the intended functionality.
  • Comprehensive unit tests and integration tests are added to cover this new method.

16-16: Verify if generated code should be committed to version control.

Line 16 indicates that this file is generated code:

Generally, it's recommended to exclude generated code from version control to prevent merge conflicts and ensure consistency by regenerating as needed. Confirm whether including this generated file aligns with the project's version control policies.

To check for other generated files committed to the repository, you can run:

server/clients/housekeeping.go Outdated Show resolved Hide resolved
server/clients/housekeeping.go Show resolved Hide resolved
server/clients/housekeeping.go Outdated Show resolved Hide resolved
server/rpc/system_server.go Outdated Show resolved Hide resolved
server/rpc/system_server.go Outdated Show resolved Hide resolved
system/client.go Outdated Show resolved Hide resolved
api/yorkie/v1/v1connect/system.connect.go Outdated Show resolved Hide resolved
server/backend/database/mongo/client.go Show resolved Hide resolved
server/clients/clients.go Outdated Show resolved Hide resolved
server/clients/clients.go Outdated Show resolved Hide resolved
@hackerwins hackerwins force-pushed the hk-deactivate-client branch 2 times, most recently from cdf4b69 to 31fc46d Compare October 16, 2024 07:57
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Go Benchmark

Benchmark suite Current: f89f6a4 Previous: cdf4b69 Ratio
BenchmarkDocument/constructor_test 1626 ns/op 1337 B/op 24 allocs/op 1500 ns/op 1337 B/op 24 allocs/op 1.08
BenchmarkDocument/constructor_test - ns/op 1626 ns/op 1500 ns/op 1.08
BenchmarkDocument/constructor_test - B/op 1337 B/op 1337 B/op 1
BenchmarkDocument/constructor_test - allocs/op 24 allocs/op 24 allocs/op 1
BenchmarkDocument/status_test 956.5 ns/op 1305 B/op 22 allocs/op 957.7 ns/op 1305 B/op 22 allocs/op 1.00
BenchmarkDocument/status_test - ns/op 956.5 ns/op 957.7 ns/op 1.00
BenchmarkDocument/status_test - B/op 1305 B/op 1305 B/op 1
BenchmarkDocument/status_test - allocs/op 22 allocs/op 22 allocs/op 1
BenchmarkDocument/equals_test 7616 ns/op 7273 B/op 132 allocs/op 7693 ns/op 7273 B/op 132 allocs/op 0.99
BenchmarkDocument/equals_test - ns/op 7616 ns/op 7693 ns/op 0.99
BenchmarkDocument/equals_test - B/op 7273 B/op 7273 B/op 1
BenchmarkDocument/equals_test - allocs/op 132 allocs/op 132 allocs/op 1
BenchmarkDocument/nested_update_test 16811 ns/op 12138 B/op 262 allocs/op 16915 ns/op 12139 B/op 262 allocs/op 0.99
BenchmarkDocument/nested_update_test - ns/op 16811 ns/op 16915 ns/op 0.99
BenchmarkDocument/nested_update_test - B/op 12138 B/op 12139 B/op 1.00
BenchmarkDocument/nested_update_test - allocs/op 262 allocs/op 262 allocs/op 1
BenchmarkDocument/delete_test 22578 ns/op 15363 B/op 341 allocs/op 22730 ns/op 15364 B/op 341 allocs/op 0.99
BenchmarkDocument/delete_test - ns/op 22578 ns/op 22730 ns/op 0.99
BenchmarkDocument/delete_test - B/op 15363 B/op 15364 B/op 1.00
BenchmarkDocument/delete_test - allocs/op 341 allocs/op 341 allocs/op 1
BenchmarkDocument/object_test 8664 ns/op 6817 B/op 120 allocs/op 9394 ns/op 6817 B/op 120 allocs/op 0.92
BenchmarkDocument/object_test - ns/op 8664 ns/op 9394 ns/op 0.92
BenchmarkDocument/object_test - B/op 6817 B/op 6817 B/op 1
BenchmarkDocument/object_test - allocs/op 120 allocs/op 120 allocs/op 1
BenchmarkDocument/array_test 29715 ns/op 11946 B/op 276 allocs/op 30253 ns/op 11947 B/op 276 allocs/op 0.98
BenchmarkDocument/array_test - ns/op 29715 ns/op 30253 ns/op 0.98
BenchmarkDocument/array_test - B/op 11946 B/op 11947 B/op 1.00
BenchmarkDocument/array_test - allocs/op 276 allocs/op 276 allocs/op 1
BenchmarkDocument/text_test 31366 ns/op 14779 B/op 486 allocs/op 31709 ns/op 14780 B/op 486 allocs/op 0.99
BenchmarkDocument/text_test - ns/op 31366 ns/op 31709 ns/op 0.99
BenchmarkDocument/text_test - B/op 14779 B/op 14780 B/op 1.00
BenchmarkDocument/text_test - allocs/op 486 allocs/op 486 allocs/op 1
BenchmarkDocument/text_composition_test 29933 ns/op 18462 B/op 502 allocs/op 30323 ns/op 18460 B/op 502 allocs/op 0.99
BenchmarkDocument/text_composition_test - ns/op 29933 ns/op 30323 ns/op 0.99
BenchmarkDocument/text_composition_test - B/op 18462 B/op 18460 B/op 1.00
BenchmarkDocument/text_composition_test - allocs/op 502 allocs/op 502 allocs/op 1
BenchmarkDocument/rich_text_test 82404 ns/op 38708 B/op 1165 allocs/op 84275 ns/op 38708 B/op 1165 allocs/op 0.98
BenchmarkDocument/rich_text_test - ns/op 82404 ns/op 84275 ns/op 0.98
BenchmarkDocument/rich_text_test - B/op 38708 B/op 38708 B/op 1
BenchmarkDocument/rich_text_test - allocs/op 1165 allocs/op 1165 allocs/op 1
BenchmarkDocument/counter_test 17256 ns/op 10722 B/op 244 allocs/op 17555 ns/op 10722 B/op 244 allocs/op 0.98
BenchmarkDocument/counter_test - ns/op 17256 ns/op 17555 ns/op 0.98
BenchmarkDocument/counter_test - B/op 10722 B/op 10722 B/op 1
BenchmarkDocument/counter_test - allocs/op 244 allocs/op 244 allocs/op 1
BenchmarkDocument/text_edit_gc_100 1302210 ns/op 871967 B/op 17276 allocs/op 1323658 ns/op 872000 B/op 17275 allocs/op 0.98
BenchmarkDocument/text_edit_gc_100 - ns/op 1302210 ns/op 1323658 ns/op 0.98
BenchmarkDocument/text_edit_gc_100 - B/op 871967 B/op 872000 B/op 1.00
BenchmarkDocument/text_edit_gc_100 - allocs/op 17276 allocs/op 17275 allocs/op 1.00
BenchmarkDocument/text_edit_gc_1000 50825918 ns/op 50545582 B/op 186738 allocs/op 50725465 ns/op 50547210 B/op 186731 allocs/op 1.00
BenchmarkDocument/text_edit_gc_1000 - ns/op 50825918 ns/op 50725465 ns/op 1.00
BenchmarkDocument/text_edit_gc_1000 - B/op 50545582 B/op 50547210 B/op 1.00
BenchmarkDocument/text_edit_gc_1000 - allocs/op 186738 allocs/op 186731 allocs/op 1.00
BenchmarkDocument/text_split_gc_100 1920827 ns/op 1588466 B/op 15944 allocs/op 1962373 ns/op 1588527 B/op 15945 allocs/op 0.98
BenchmarkDocument/text_split_gc_100 - ns/op 1920827 ns/op 1962373 ns/op 0.98
BenchmarkDocument/text_split_gc_100 - B/op 1588466 B/op 1588527 B/op 1.00
BenchmarkDocument/text_split_gc_100 - allocs/op 15944 allocs/op 15945 allocs/op 1.00
BenchmarkDocument/text_split_gc_1000 115794976 ns/op 141483556 B/op 186147 allocs/op 116636715 ns/op 141481421 B/op 186139 allocs/op 0.99
BenchmarkDocument/text_split_gc_1000 - ns/op 115794976 ns/op 116636715 ns/op 0.99
BenchmarkDocument/text_split_gc_1000 - B/op 141483556 B/op 141481421 B/op 1.00
BenchmarkDocument/text_split_gc_1000 - allocs/op 186147 allocs/op 186139 allocs/op 1.00
BenchmarkDocument/text_delete_all_10000 16487742 ns/op 10213870 B/op 55683 allocs/op 17345072 ns/op 10212741 B/op 55681 allocs/op 0.95
BenchmarkDocument/text_delete_all_10000 - ns/op 16487742 ns/op 17345072 ns/op 0.95
BenchmarkDocument/text_delete_all_10000 - B/op 10213870 B/op 10212741 B/op 1.00
BenchmarkDocument/text_delete_all_10000 - allocs/op 55683 allocs/op 55681 allocs/op 1.00
BenchmarkDocument/text_delete_all_100000 278606239 ns/op 142972576 B/op 561724 allocs/op 314986961 ns/op 142962208 B/op 561644 allocs/op 0.88
BenchmarkDocument/text_delete_all_100000 - ns/op 278606239 ns/op 314986961 ns/op 0.88
BenchmarkDocument/text_delete_all_100000 - B/op 142972576 B/op 142962208 B/op 1.00
BenchmarkDocument/text_delete_all_100000 - allocs/op 561724 allocs/op 561644 allocs/op 1.00
BenchmarkDocument/text_100 220112 ns/op 120235 B/op 5180 allocs/op 230518 ns/op 120235 B/op 5180 allocs/op 0.95
BenchmarkDocument/text_100 - ns/op 220112 ns/op 230518 ns/op 0.95
BenchmarkDocument/text_100 - B/op 120235 B/op 120235 B/op 1
BenchmarkDocument/text_100 - allocs/op 5180 allocs/op 5180 allocs/op 1
BenchmarkDocument/text_1000 2384193 ns/op 1171023 B/op 51084 allocs/op 2480969 ns/op 1171025 B/op 51084 allocs/op 0.96
BenchmarkDocument/text_1000 - ns/op 2384193 ns/op 2480969 ns/op 0.96
BenchmarkDocument/text_1000 - B/op 1171023 B/op 1171025 B/op 1.00
BenchmarkDocument/text_1000 - allocs/op 51084 allocs/op 51084 allocs/op 1
BenchmarkDocument/array_1000 1203279 ns/op 1091486 B/op 11832 allocs/op 1272389 ns/op 1091380 B/op 11831 allocs/op 0.95
BenchmarkDocument/array_1000 - ns/op 1203279 ns/op 1272389 ns/op 0.95
BenchmarkDocument/array_1000 - B/op 1091486 B/op 1091380 B/op 1.00
BenchmarkDocument/array_1000 - allocs/op 11832 allocs/op 11831 allocs/op 1.00
BenchmarkDocument/array_10000 13101131 ns/op 9799925 B/op 120296 allocs/op 13806197 ns/op 9800443 B/op 120299 allocs/op 0.95
BenchmarkDocument/array_10000 - ns/op 13101131 ns/op 13806197 ns/op 0.95
BenchmarkDocument/array_10000 - B/op 9799925 B/op 9800443 B/op 1.00
BenchmarkDocument/array_10000 - allocs/op 120296 allocs/op 120299 allocs/op 1.00
BenchmarkDocument/array_gc_100 144651 ns/op 132732 B/op 1261 allocs/op 156238 ns/op 132715 B/op 1260 allocs/op 0.93
BenchmarkDocument/array_gc_100 - ns/op 144651 ns/op 156238 ns/op 0.93
BenchmarkDocument/array_gc_100 - B/op 132732 B/op 132715 B/op 1.00
BenchmarkDocument/array_gc_100 - allocs/op 1261 allocs/op 1260 allocs/op 1.00
BenchmarkDocument/array_gc_1000 1379574 ns/op 1159238 B/op 12877 allocs/op 1472999 ns/op 1159228 B/op 12877 allocs/op 0.94
BenchmarkDocument/array_gc_1000 - ns/op 1379574 ns/op 1472999 ns/op 0.94
BenchmarkDocument/array_gc_1000 - B/op 1159238 B/op 1159228 B/op 1.00
BenchmarkDocument/array_gc_1000 - allocs/op 12877 allocs/op 12877 allocs/op 1
BenchmarkDocument/counter_1000 200428 ns/op 193079 B/op 5771 allocs/op 216084 ns/op 193080 B/op 5771 allocs/op 0.93
BenchmarkDocument/counter_1000 - ns/op 200428 ns/op 216084 ns/op 0.93
BenchmarkDocument/counter_1000 - B/op 193079 B/op 193080 B/op 1.00
BenchmarkDocument/counter_1000 - allocs/op 5771 allocs/op 5771 allocs/op 1
BenchmarkDocument/counter_10000 2182622 ns/op 2087982 B/op 59778 allocs/op 2231338 ns/op 2087999 B/op 59778 allocs/op 0.98
BenchmarkDocument/counter_10000 - ns/op 2182622 ns/op 2231338 ns/op 0.98
BenchmarkDocument/counter_10000 - B/op 2087982 B/op 2087999 B/op 1.00
BenchmarkDocument/counter_10000 - allocs/op 59778 allocs/op 59778 allocs/op 1
BenchmarkDocument/object_1000 1369289 ns/op 1428157 B/op 9849 allocs/op 1463005 ns/op 1428097 B/op 9849 allocs/op 0.94
BenchmarkDocument/object_1000 - ns/op 1369289 ns/op 1463005 ns/op 0.94
BenchmarkDocument/object_1000 - B/op 1428157 B/op 1428097 B/op 1.00
BenchmarkDocument/object_1000 - allocs/op 9849 allocs/op 9849 allocs/op 1
BenchmarkDocument/object_10000 15115176 ns/op 12168150 B/op 100566 allocs/op 15714521 ns/op 12167743 B/op 100567 allocs/op 0.96
BenchmarkDocument/object_10000 - ns/op 15115176 ns/op 15714521 ns/op 0.96
BenchmarkDocument/object_10000 - B/op 12168150 B/op 12167743 B/op 1.00
BenchmarkDocument/object_10000 - allocs/op 100566 allocs/op 100567 allocs/op 1.00
BenchmarkDocument/tree_100 1015971 ns/op 943700 B/op 6101 allocs/op 1071780 ns/op 943704 B/op 6101 allocs/op 0.95
BenchmarkDocument/tree_100 - ns/op 1015971 ns/op 1071780 ns/op 0.95
BenchmarkDocument/tree_100 - B/op 943700 B/op 943704 B/op 1.00
BenchmarkDocument/tree_100 - allocs/op 6101 allocs/op 6101 allocs/op 1
BenchmarkDocument/tree_1000 72523307 ns/op 86460317 B/op 60115 allocs/op 79956298 ns/op 86460482 B/op 60115 allocs/op 0.91
BenchmarkDocument/tree_1000 - ns/op 72523307 ns/op 79956298 ns/op 0.91
BenchmarkDocument/tree_1000 - B/op 86460317 B/op 86460482 B/op 1.00
BenchmarkDocument/tree_1000 - allocs/op 60115 allocs/op 60115 allocs/op 1
BenchmarkDocument/tree_10000 9270046996 ns/op 8580670432 B/op 600220 allocs/op 9897994875 ns/op 8580656176 B/op 600252 allocs/op 0.94
BenchmarkDocument/tree_10000 - ns/op 9270046996 ns/op 9897994875 ns/op 0.94
BenchmarkDocument/tree_10000 - B/op 8580670432 B/op 8580656176 B/op 1.00
BenchmarkDocument/tree_10000 - allocs/op 600220 allocs/op 600252 allocs/op 1.00
BenchmarkDocument/tree_delete_all_1000 77170656 ns/op 87509977 B/op 75266 allocs/op 80032740 ns/op 87508876 B/op 75262 allocs/op 0.96
BenchmarkDocument/tree_delete_all_1000 - ns/op 77170656 ns/op 80032740 ns/op 0.96
BenchmarkDocument/tree_delete_all_1000 - B/op 87509977 B/op 87508876 B/op 1.00
BenchmarkDocument/tree_delete_all_1000 - allocs/op 75266 allocs/op 75262 allocs/op 1.00
BenchmarkDocument/tree_edit_gc_100 3823166 ns/op 4147770 B/op 15141 allocs/op 3984044 ns/op 4146682 B/op 15141 allocs/op 0.96
BenchmarkDocument/tree_edit_gc_100 - ns/op 3823166 ns/op 3984044 ns/op 0.96
BenchmarkDocument/tree_edit_gc_100 - B/op 4147770 B/op 4146682 B/op 1.00
BenchmarkDocument/tree_edit_gc_100 - allocs/op 15141 allocs/op 15141 allocs/op 1
BenchmarkDocument/tree_edit_gc_1000 304508285 ns/op 383745414 B/op 154859 allocs/op 321476574 ns/op 383745266 B/op 154868 allocs/op 0.95
BenchmarkDocument/tree_edit_gc_1000 - ns/op 304508285 ns/op 321476574 ns/op 0.95
BenchmarkDocument/tree_edit_gc_1000 - B/op 383745414 B/op 383745266 B/op 1.00
BenchmarkDocument/tree_edit_gc_1000 - allocs/op 154859 allocs/op 154868 allocs/op 1.00
BenchmarkDocument/tree_split_gc_100 2611145 ns/op 2412533 B/op 11125 allocs/op 2711129 ns/op 2412501 B/op 11125 allocs/op 0.96
BenchmarkDocument/tree_split_gc_100 - ns/op 2611145 ns/op 2711129 ns/op 0.96
BenchmarkDocument/tree_split_gc_100 - B/op 2412533 B/op 2412501 B/op 1.00
BenchmarkDocument/tree_split_gc_100 - allocs/op 11125 allocs/op 11125 allocs/op 1
BenchmarkDocument/tree_split_gc_1000 189846441 ns/op 222252193 B/op 121999 allocs/op 197945984 ns/op 222251521 B/op 122004 allocs/op 0.96
BenchmarkDocument/tree_split_gc_1000 - ns/op 189846441 ns/op 197945984 ns/op 0.96
BenchmarkDocument/tree_split_gc_1000 - B/op 222252193 B/op 222251521 B/op 1.00
BenchmarkDocument/tree_split_gc_1000 - allocs/op 121999 allocs/op 122004 allocs/op 1.00
BenchmarkRPC/client_to_server 344269850 ns/op 17096754 B/op 170769 allocs/op 349061437 ns/op 17655010 B/op 170839 allocs/op 0.99
BenchmarkRPC/client_to_server - ns/op 344269850 ns/op 349061437 ns/op 0.99
BenchmarkRPC/client_to_server - B/op 17096754 B/op 17655010 B/op 0.97
BenchmarkRPC/client_to_server - allocs/op 170769 allocs/op 170839 allocs/op 1.00
BenchmarkRPC/client_to_client_via_server 632741126 ns/op 34335296 B/op 334607 allocs/op 644490308 ns/op 34874144 B/op 331765 allocs/op 0.98
BenchmarkRPC/client_to_client_via_server - ns/op 632741126 ns/op 644490308 ns/op 0.98
BenchmarkRPC/client_to_client_via_server - B/op 34335296 B/op 34874144 B/op 0.98
BenchmarkRPC/client_to_client_via_server - allocs/op 334607 allocs/op 331765 allocs/op 1.01
BenchmarkRPC/attach_large_document 1792153773 ns/op 3035339664 B/op 13254 allocs/op 1812304287 ns/op 3021254280 B/op 12458 allocs/op 0.99
BenchmarkRPC/attach_large_document - ns/op 1792153773 ns/op 1812304287 ns/op 0.99
BenchmarkRPC/attach_large_document - B/op 3035339664 B/op 3021254280 B/op 1.00
BenchmarkRPC/attach_large_document - allocs/op 13254 allocs/op 12458 allocs/op 1.06
BenchmarkRPC/adminCli_to_server 535007956 ns/op 36770536 B/op 289580 allocs/op 537316904 ns/op 35952148 B/op 289571 allocs/op 1.00
BenchmarkRPC/adminCli_to_server - ns/op 535007956 ns/op 537316904 ns/op 1.00
BenchmarkRPC/adminCli_to_server - B/op 36770536 B/op 35952148 B/op 1.02
BenchmarkRPC/adminCli_to_server - allocs/op 289580 allocs/op 289571 allocs/op 1.00
BenchmarkLocker 63.89 ns/op 16 B/op 1 allocs/op 64.33 ns/op 16 B/op 1 allocs/op 0.99
BenchmarkLocker - ns/op 63.89 ns/op 64.33 ns/op 0.99
BenchmarkLocker - B/op 16 B/op 16 B/op 1
BenchmarkLocker - allocs/op 1 allocs/op 1 allocs/op 1
BenchmarkLockerParallel 39.41 ns/op 0 B/op 0 allocs/op 39.07 ns/op 0 B/op 0 allocs/op 1.01
BenchmarkLockerParallel - ns/op 39.41 ns/op 39.07 ns/op 1.01
BenchmarkLockerParallel - B/op 0 B/op 0 B/op 1
BenchmarkLockerParallel - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkLockerMoreKeys 145.6 ns/op 15 B/op 0 allocs/op 140.1 ns/op 15 B/op 0 allocs/op 1.04
BenchmarkLockerMoreKeys - ns/op 145.6 ns/op 140.1 ns/op 1.04
BenchmarkLockerMoreKeys - B/op 15 B/op 15 B/op 1
BenchmarkLockerMoreKeys - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkChange/Push_10_Changes 3746581 ns/op 117568 B/op 1215 allocs/op 3815517 ns/op 117211 B/op 1215 allocs/op 0.98
BenchmarkChange/Push_10_Changes - ns/op 3746581 ns/op 3815517 ns/op 0.98
BenchmarkChange/Push_10_Changes - B/op 117568 B/op 117211 B/op 1.00
BenchmarkChange/Push_10_Changes - allocs/op 1215 allocs/op 1215 allocs/op 1
BenchmarkChange/Push_100_Changes 15374384 ns/op 569233 B/op 6585 allocs/op 15648137 ns/op 570426 B/op 6586 allocs/op 0.98
BenchmarkChange/Push_100_Changes - ns/op 15374384 ns/op 15648137 ns/op 0.98
BenchmarkChange/Push_100_Changes - B/op 569233 B/op 570426 B/op 1.00
BenchmarkChange/Push_100_Changes - allocs/op 6585 allocs/op 6586 allocs/op 1.00
BenchmarkChange/Push_1000_Changes 125805094 ns/op 5208501 B/op 63077 allocs/op 126200918 ns/op 5362366 B/op 63081 allocs/op 1.00
BenchmarkChange/Push_1000_Changes - ns/op 125805094 ns/op 126200918 ns/op 1.00
BenchmarkChange/Push_1000_Changes - B/op 5208501 B/op 5362366 B/op 0.97
BenchmarkChange/Push_1000_Changes - allocs/op 63077 allocs/op 63081 allocs/op 1.00
BenchmarkChange/Pull_10_Changes 2989580 ns/op 103161 B/op 1018 allocs/op 3039996 ns/op 102555 B/op 1018 allocs/op 0.98
BenchmarkChange/Pull_10_Changes - ns/op 2989580 ns/op 3039996 ns/op 0.98
BenchmarkChange/Pull_10_Changes - B/op 103161 B/op 102555 B/op 1.01
BenchmarkChange/Pull_10_Changes - allocs/op 1018 allocs/op 1018 allocs/op 1
BenchmarkChange/Pull_100_Changes 4566810 ns/op 268225 B/op 3489 allocs/op 4590477 ns/op 266845 B/op 3488 allocs/op 0.99
BenchmarkChange/Pull_100_Changes - ns/op 4566810 ns/op 4590477 ns/op 0.99
BenchmarkChange/Pull_100_Changes - B/op 268225 B/op 266845 B/op 1.01
BenchmarkChange/Pull_100_Changes - allocs/op 3489 allocs/op 3488 allocs/op 1.00
BenchmarkChange/Pull_1000_Changes 8620347 ns/op 1492772 B/op 29870 allocs/op 8911691 ns/op 1490386 B/op 29867 allocs/op 0.97
BenchmarkChange/Pull_1000_Changes - ns/op 8620347 ns/op 8911691 ns/op 0.97
BenchmarkChange/Pull_1000_Changes - B/op 1492772 B/op 1490386 B/op 1.00
BenchmarkChange/Pull_1000_Changes - allocs/op 29870 allocs/op 29867 allocs/op 1.00
BenchmarkSnapshot/Push_3KB_snapshot 17849003 ns/op 709406 B/op 6586 allocs/op 18044547 ns/op 708528 B/op 6586 allocs/op 0.99
BenchmarkSnapshot/Push_3KB_snapshot - ns/op 17849003 ns/op 18044547 ns/op 0.99
BenchmarkSnapshot/Push_3KB_snapshot - B/op 709406 B/op 708528 B/op 1.00
BenchmarkSnapshot/Push_3KB_snapshot - allocs/op 6586 allocs/op 6586 allocs/op 1
BenchmarkSnapshot/Push_30KB_snapshot 129742374 ns/op 5542497 B/op 63078 allocs/op 129117558 ns/op 5586802 B/op 63079 allocs/op 1.00
BenchmarkSnapshot/Push_30KB_snapshot - ns/op 129742374 ns/op 129117558 ns/op 1.00
BenchmarkSnapshot/Push_30KB_snapshot - B/op 5542497 B/op 5586802 B/op 0.99
BenchmarkSnapshot/Push_30KB_snapshot - allocs/op 63078 allocs/op 63079 allocs/op 1.00
BenchmarkSnapshot/Pull_3KB_snapshot 6776254 ns/op 924015 B/op 15524 allocs/op 6690573 ns/op 921973 B/op 15522 allocs/op 1.01
BenchmarkSnapshot/Pull_3KB_snapshot - ns/op 6776254 ns/op 6690573 ns/op 1.01
BenchmarkSnapshot/Pull_3KB_snapshot - B/op 924015 B/op 921973 B/op 1.00
BenchmarkSnapshot/Pull_3KB_snapshot - allocs/op 15524 allocs/op 15522 allocs/op 1.00
BenchmarkSnapshot/Pull_30KB_snapshot 15384007 ns/op 7158354 B/op 150119 allocs/op 15789110 ns/op 7145336 B/op 150119 allocs/op 0.97
BenchmarkSnapshot/Pull_30KB_snapshot - ns/op 15384007 ns/op 15789110 ns/op 0.97
BenchmarkSnapshot/Pull_30KB_snapshot - B/op 7158354 B/op 7145336 B/op 1.00
BenchmarkSnapshot/Pull_30KB_snapshot - allocs/op 150119 allocs/op 150119 allocs/op 1
BenchmarkSplayTree/stress_test_100000 0.1952 ns/op 0 B/op 0 allocs/op 0.1869 ns/op 0 B/op 0 allocs/op 1.04
BenchmarkSplayTree/stress_test_100000 - ns/op 0.1952 ns/op 0.1869 ns/op 1.04
BenchmarkSplayTree/stress_test_100000 - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/stress_test_100000 - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSplayTree/stress_test_200000 0.378 ns/op 0 B/op 0 allocs/op 0.3992 ns/op 0 B/op 0 allocs/op 0.95
BenchmarkSplayTree/stress_test_200000 - ns/op 0.378 ns/op 0.3992 ns/op 0.95
BenchmarkSplayTree/stress_test_200000 - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/stress_test_200000 - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSplayTree/stress_test_300000 0.5881 ns/op 0 B/op 0 allocs/op 0.5808 ns/op 0 B/op 0 allocs/op 1.01
BenchmarkSplayTree/stress_test_300000 - ns/op 0.5881 ns/op 0.5808 ns/op 1.01
BenchmarkSplayTree/stress_test_300000 - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/stress_test_300000 - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSplayTree/random_access_100000 0.01257 ns/op 0 B/op 0 allocs/op 0.01302 ns/op 0 B/op 0 allocs/op 0.97
BenchmarkSplayTree/random_access_100000 - ns/op 0.01257 ns/op 0.01302 ns/op 0.97
BenchmarkSplayTree/random_access_100000 - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/random_access_100000 - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSplayTree/random_access_200000 0.02372 ns/op 0 B/op 0 allocs/op 0.02622 ns/op 0 B/op 0 allocs/op 0.90
BenchmarkSplayTree/random_access_200000 - ns/op 0.02372 ns/op 0.02622 ns/op 0.90
BenchmarkSplayTree/random_access_200000 - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/random_access_200000 - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSplayTree/random_access_300000 0.03603 ns/op 0 B/op 0 allocs/op 0.03808 ns/op 0 B/op 0 allocs/op 0.95
BenchmarkSplayTree/random_access_300000 - ns/op 0.03603 ns/op 0.03808 ns/op 0.95
BenchmarkSplayTree/random_access_300000 - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/random_access_300000 - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSplayTree/editing_trace_bench 0.001953 ns/op 0 B/op 0 allocs/op 0.002446 ns/op 0 B/op 0 allocs/op 0.80
BenchmarkSplayTree/editing_trace_bench - ns/op 0.001953 ns/op 0.002446 ns/op 0.80
BenchmarkSplayTree/editing_trace_bench - B/op 0 B/op 0 B/op 1
BenchmarkSplayTree/editing_trace_bench - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkSync/memory_sync_10_test 6858 ns/op 1286 B/op 38 allocs/op 6945 ns/op 1286 B/op 38 allocs/op 0.99
BenchmarkSync/memory_sync_10_test - ns/op 6858 ns/op 6945 ns/op 0.99
BenchmarkSync/memory_sync_10_test - B/op 1286 B/op 1286 B/op 1
BenchmarkSync/memory_sync_10_test - allocs/op 38 allocs/op 38 allocs/op 1
BenchmarkSync/memory_sync_100_test 50858 ns/op 8646 B/op 273 allocs/op 51079 ns/op 8641 B/op 273 allocs/op 1.00
BenchmarkSync/memory_sync_100_test - ns/op 50858 ns/op 51079 ns/op 1.00
BenchmarkSync/memory_sync_100_test - B/op 8646 B/op 8641 B/op 1.00
BenchmarkSync/memory_sync_100_test - allocs/op 273 allocs/op 273 allocs/op 1
BenchmarkSync/memory_sync_1000_test 588257 ns/op 74054 B/op 2103 allocs/op 581015 ns/op 74870 B/op 2152 allocs/op 1.01
BenchmarkSync/memory_sync_1000_test - ns/op 588257 ns/op 581015 ns/op 1.01
BenchmarkSync/memory_sync_1000_test - B/op 74054 B/op 74870 B/op 0.99
BenchmarkSync/memory_sync_1000_test - allocs/op 2103 allocs/op 2152 allocs/op 0.98
BenchmarkSync/memory_sync_10000_test 7347513 ns/op 744872 B/op 20288 allocs/op 7733341 ns/op 737529 B/op 20266 allocs/op 0.95
BenchmarkSync/memory_sync_10000_test - ns/op 7347513 ns/op 7733341 ns/op 0.95
BenchmarkSync/memory_sync_10000_test - B/op 744872 B/op 737529 B/op 1.01
BenchmarkSync/memory_sync_10000_test - allocs/op 20288 allocs/op 20266 allocs/op 1.00
BenchmarkTextEditing 5059291771 ns/op 3903617872 B/op 19608506 allocs/op 4945228774 ns/op 3903643616 B/op 19608559 allocs/op 1.02
BenchmarkTextEditing - ns/op 5059291771 ns/op 4945228774 ns/op 1.02
BenchmarkTextEditing - B/op 3903617872 B/op 3903643616 B/op 1.00
BenchmarkTextEditing - allocs/op 19608506 allocs/op 19608559 allocs/op 1.00
BenchmarkTree/10000_vertices_to_protobuf 3568073 ns/op 6262973 B/op 70025 allocs/op 3584593 ns/op 6263033 B/op 70025 allocs/op 1.00
BenchmarkTree/10000_vertices_to_protobuf - ns/op 3568073 ns/op 3584593 ns/op 1.00
BenchmarkTree/10000_vertices_to_protobuf - B/op 6262973 B/op 6263033 B/op 1.00
BenchmarkTree/10000_vertices_to_protobuf - allocs/op 70025 allocs/op 70025 allocs/op 1
BenchmarkTree/10000_vertices_from_protobuf 158771096 ns/op 442172620 B/op 290039 allocs/op 161101715 ns/op 442171446 B/op 290039 allocs/op 0.99
BenchmarkTree/10000_vertices_from_protobuf - ns/op 158771096 ns/op 161101715 ns/op 0.99
BenchmarkTree/10000_vertices_from_protobuf - B/op 442172620 B/op 442171446 B/op 1.00
BenchmarkTree/10000_vertices_from_protobuf - allocs/op 290039 allocs/op 290039 allocs/op 1
BenchmarkTree/20000_vertices_to_protobuf 7804219 ns/op 12716926 B/op 140028 allocs/op 8073991 ns/op 12721130 B/op 140028 allocs/op 0.97
BenchmarkTree/20000_vertices_to_protobuf - ns/op 7804219 ns/op 8073991 ns/op 0.97
BenchmarkTree/20000_vertices_to_protobuf - B/op 12716926 B/op 12721130 B/op 1.00
BenchmarkTree/20000_vertices_to_protobuf - allocs/op 140028 allocs/op 140028 allocs/op 1
BenchmarkTree/20000_vertices_from_protobuf 699299415 ns/op 1697267960 B/op 580043 allocs/op 683105482 ns/op 1697267704 B/op 580042 allocs/op 1.02
BenchmarkTree/20000_vertices_from_protobuf - ns/op 699299415 ns/op 683105482 ns/op 1.02
BenchmarkTree/20000_vertices_from_protobuf - B/op 1697267960 B/op 1697267704 B/op 1.00
BenchmarkTree/20000_vertices_from_protobuf - allocs/op 580043 allocs/op 580042 allocs/op 1.00
BenchmarkTree/30000_vertices_to_protobuf 12323406 ns/op 19324633 B/op 210030 allocs/op 12502493 ns/op 19318234 B/op 210030 allocs/op 0.99
BenchmarkTree/30000_vertices_to_protobuf - ns/op 12323406 ns/op 12502493 ns/op 0.99
BenchmarkTree/30000_vertices_to_protobuf - B/op 19324633 B/op 19318234 B/op 1.00
BenchmarkTree/30000_vertices_to_protobuf - allocs/op 210030 allocs/op 210030 allocs/op 1
BenchmarkTree/30000_vertices_from_protobuf 1634736850 ns/op 3752052888 B/op 870136 allocs/op 1629191080 ns/op 3752044008 B/op 870048 allocs/op 1.00
BenchmarkTree/30000_vertices_from_protobuf - ns/op 1634736850 ns/op 1629191080 ns/op 1.00
BenchmarkTree/30000_vertices_from_protobuf - B/op 3752052888 B/op 3752044008 B/op 1.00
BenchmarkTree/30000_vertices_from_protobuf - allocs/op 870136 allocs/op 870048 allocs/op 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@hackerwins hackerwins force-pushed the hk-deactivate-client branch 3 times, most recently from af4b0d8 to f7d2e19 Compare October 16, 2024 08:21
@hackerwins hackerwins force-pushed the hk-deactivate-client branch from f7d2e19 to e1782a3 Compare October 16, 2024 08:28
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.

Caution

Inline review comments failed to post

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (17)
api/yorkie/v1/system.proto (1)

30-36: LGTM: Request message structure is appropriate.

The SystemServiceDetachDocumentRequest message is well-defined with clear and descriptive field names.

Regarding the TODO comment:

Consider creating a separate issue to track the potential enhancement of replacing the string fields with more complex types (types.Project, types.Client, types.DocumentSummary). This will ensure the improvement isn't forgotten and can be prioritized appropriately in the future.

server/clients/clients.go (1)

Action Required: Missing project Parameter in Activate Function Calls

The Activate function has been updated to include the project *types.Project parameter. However, the following calls are missing this new parameter and need to be updated accordingly:

  • test/integration/server_test.go: assert.NoError(t, cli.Activate(ctx))
  • test/integration/retention_test.go: assert.NoError(t, cli.Activate(context.Background()))
  • test/integration/client_test.go: assert.NoError(t, cli.Activate(ctx))
  • test/integration/auth_webhook_test.go: assert.NoError(t, cli.Activate(ctx))
  • test/integration/admin_test.go: assert.NoError(t, cli.Activate(ctx))
  • test/integration/gc_test.go: assert.NoError(t, c1.Activate(ctx))
  • test/integration/document_test.go: assert.NoError(t, cli.Activate(ctx))
  • test/bench/grpc_bench_test.go: err = c.Activate(context.Background())
  • test/helper/helper.go: assert.NoError(t, cli.Activate(ctx))
  • test/complex/main_test.go: assert.NoError(t, c.Activate(context.Background()))

Please update all the above instances to include the new project parameter to ensure consistent and error-free function calls.

🔗 Analysis chain

Line range hint 38-46: LGTM: Added project parameter to Activate function.

The addition of the project *types.Project parameter to the Activate function is appropriate. This change allows for project-specific client activation.

Please ensure that all calls to the Activate function have been updated to include the new project parameter. Run the following script to verify:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `Activate` include the new project parameter.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type go -A 5 $'Activate\s*\('

Length of output: 8592


Script:

#!/bin/bash
# Description: Verify all function calls to `Activate` include the new project parameter.

# Corrected Test: Search for function calls to `Activate` with the new `project` parameter.
rg --type go 'Activate\s*\([^)]*project\s*\*types\.Project[^)]*\)'

Length of output: 68


Script:

#!/bin/bash
# Description: Verify all function calls to `Activate` include the new project parameter.

# Updated Test: Search for all `Activate` function calls and check if they include the `project` parameter.
# This regex looks for `Activate(` followed by any number of arguments and ensures `project` is one of them.
rg --type go 'Activate\s*\(([^)]*,\s*)?project\s*\*types\.Project([^)]*)?\)'

Length of output: 78


Script:

#!/bin/bash
# Description: List all `Activate` function calls to verify inclusion of the new `project` parameter.

# Search for all `Activate` function calls in Go files and display their arguments.
rg --type go 'Activate\s*\(([^)]*)\)' --context 2

Length of output: 10398

server/clients/housekeeping.go (3)

71-72: LGTM! Consider improving error handling.

The changes correctly adapt the loop to use the new CandidatePair struct. However, as previously suggested, consider handling deactivation errors individually to improve robustness. Currently, if deactivating a single client fails, the function returns immediately and skips the rest of the candidates.

You could modify the loop to collect errors:

var deactivateErrors []error
for _, pair := range candidates {
	if _, err := Deactivate(ctx, be, pair.Project.ToProject(), pair.Client.RefKey()); err != nil {
		deactivateErrors = append(deactivateErrors, err)
	}
}

if len(deactivateErrors) > 0 {
	// Handle or log errors appropriately
	return database.DefaultProjectID, fmt.Errorf("errors during deactivation: %v", deactivateErrors)
}

104-105: LGTM! Update function documentation.

The change in return type from []*database.ClientInfo to []CandidatePair is consistent with the introduction of the CandidatePair struct. However, as previously suggested, please update the function's documentation to reflect this change in the return type.

Update the function comment to reflect the new return type:

// FindDeactivateCandidates finds candidates to deactivate from the database.
// It returns the ID of the last processed project and a slice of CandidatePair structs.

110-122: LGTM! Consider optimizing slice allocation.

The changes correctly implement the use of CandidatePair structs and improve the clarity of the code. However, as previously suggested, consider optimizing the candidate collection by preallocating the slice capacity, especially if dealing with a large number of candidates.

You could preallocate the candidates slice with an estimated capacity:

estimatedTotalCandidates := len(projectInfos) * candidatesLimitPerProject
candidates := make([]CandidatePair, 0, estimatedTotalCandidates)
for _, projectInfo := range projectInfos {
	infos, err := be.DB.FindDeactivateCandidatesPerProject(ctx, projectInfo, candidatesLimitPerProject)
	if err != nil {
		return database.DefaultProjectID, nil, err
	}

	for _, info := range infos {
		candidates = append(candidates, CandidatePair{
			Project: projectInfo,
			Client:  info,
		})
	}
}
server/config.sample.yml (1)

90-92: Add a descriptive comment for the new GatewayAddr parameter.

While the addition of the GatewayAddr parameter is correctly placed and follows the existing naming conventions, it lacks a descriptive comment. To improve clarity and ease of use, please add a comment explaining:

  1. The purpose of this parameter
  2. The expected format of the address (e.g., "host:port" or full URL)
  3. Whether this is a required or optional parameter
  4. Any default behavior if left empty

Example:

# GatewayAddr is the address of the gateway server.
# Format: "host:port" or full URL. Optional. If not provided, the server will not use a gateway.
GatewayAddr: ""

This will help users understand how to properly configure this new option.

api/docs/yorkie/v1/system.openapi.yaml (4)

7-11: LGTM: Server definitions are clear and appropriate.

The server definitions for both production and local environments are well-defined. The use of HTTPS for the production server is a good security practice.

Consider adding a staging or testing server URL if applicable to your development workflow.


12-24: LGTM: Path definition for detaching documents is well-structured.

The path definition follows RESTful conventions and includes appropriate references for request and response bodies. The inclusion of a default error response is a good practice.

Consider adding a brief description for the endpoint in the description field (line 15) to provide more context about its functionality.


25-110: LGTM: Components are well-structured, but TODO needs addressing.

The components section is well-organized, with clear definitions for request bodies, responses, and schemas. The error schema is particularly comprehensive.

Please address the TODO comment in the yorkie.v1.SystemServiceDetachDocumentRequest schema (lines 105-106). Consider replacing the fields with types.Project, types.Client, and types.DocumentSummary as suggested.


116-122: LGTM: Security scheme is well-defined.

The API key authentication scheme is appropriately defined using the Authorization header, which is a standard practice.

Consider adding a brief description to the security scheme to provide more context about the expected API key format or any specific requirements.

server/backend/config.go (1)

Line range hint 32-32: Fix typo in YAML tag for SnapshotWithPurgingChanges

There's a typo in the YAML tag for the SnapshotWithPurgingChanges field. It currently reads "SnapshotWithPurgingChages", missing an 'n' in "Changes".

Please apply the following fix:

-	SnapshotWithPurgingChanges bool `yaml:"SnapshotWithPurgingChages"`
+	SnapshotWithPurgingChanges bool `yaml:"SnapshotWithPurgingChanges"`

This correction ensures proper YAML serialization and deserialization of the configuration.

server/config.go (1)

71-71: Consider consistent formatting across constants.

The spacing before the = sign for DefaultHostname has been modified. While this doesn't affect functionality, it's important to maintain consistent formatting throughout the codebase. Please ensure this change aligns with the project's style guide or formatting standards.

server/documents/documents.go (1)

138-138: LGTM. Consider addressing the N+1 problem.

The change from packs.BuildDocumentForServerSeq to packs.BuildInternalDocForServerSeq is consistent with other functions.

There's a TODO comment about resolving an N+1 problem. Consider creating an issue to track this performance improvement:

// TODO(hackerwins, kokodak): Resolve the N+1 problem.

Would you like me to create a GitHub issue to track this performance improvement?

test/helper/helper.go (1)

259-259: LGTM! Consider adding a comment for clarity.

The addition of the GatewayAddr field to the Backend configuration is well-implemented and consistent with the existing code style. It provides a unique gateway address for each test instance, which is beneficial for parallel testing scenarios.

Consider adding a brief comment explaining the purpose of the GatewayAddr field and its relationship to the RPCPort. This would enhance code readability and make it easier for other developers to understand the configuration's intent. For example:

+   // GatewayAddr specifies the address for the gateway in the test environment.
+   // It uses the same port as the RPC server to simplify the test setup.
    GatewayAddr:                fmt.Sprintf("localhost:%d", RPCPort+portOffset),
server/rpc/yorkie_server.go (1)

97-100: LGTM! Consider enhancing error handling.

The addition of the project parameter to the clients.Deactivate function call is a good improvement. It provides more context for the deactivation process, which aligns well with the PR objective of detaching documents when a client is deactivated.

Consider adding a check to ensure that project is not nil before using it:

 project := projects.From(ctx)
+if project == nil {
+    return nil, fmt.Errorf("project not found in context")
+}
 _, err = clients.Deactivate(ctx, s.backend, project, types.ClientRefKey{
     ProjectID: project.ID,
     ClientID:  types.IDFromActorID(actorID),
 })

This additional check would prevent potential nil pointer dereferences and provide a more informative error message if the project is missing from the context.

server/packs/packs.go (2)

Line range hint 233-278: Prioritize handling the TODO for large change sets

The BuildInternalDocForServerSeq function contains a TODO comment regarding the potential performance impact when applying a large number of changes if the snapshot is missing. Processing all changes at once can lead to high memory usage and prolonged processing time.

Consider implementing a mechanism to batch the application of changes, processing them in smaller chunks (e.g., 100 changes at a time). This approach can improve performance and reduce resource consumption.

Would you like assistance in drafting an implementation plan or creating a GitHub issue to track this enhancement?


Line range hint 233-278: Review logging of document content in debug mode

In the BuildInternalDocForServerSeq function, sensitive document content is being logged when debug logging is enabled:

logging.From(ctx).Debugf(
    "after apply %d changes: elements: %d removeds: %d, %s",
    len(changes),
    doc.Root().ElementMapLen(),
    doc.Root().GarbageElementLen(),
    doc.RootObject().Marshal(),
)

While detailed logs are valuable for debugging, logging the entire document content may expose sensitive information.

Consider modifying the logging statement to exclude or mask sensitive data:

 logging.From(ctx).Debugf(
     "after apply %d changes: elements: %d removeds: %d",
     len(changes),
     doc.Root().ElementMapLen(),
     doc.Root().GarbageElementLen(),
-    doc.RootObject().Marshal(),
 )
🛑 Comments failed to post (8)
api/yorkie/v1/system.proto (2)

18-18: ⚠️ Potential issue

Consider adjusting the package directory structure.

The static analysis tool indicates that files with package "yorkie.v1" should be within a directory "yorkie/v1" relative to the root, but they are currently in the "api/yorkie/v1" directory. This mismatch might cause issues with some tools or conventions.

Consider one of the following options:

  1. Move this file to the "yorkie/v1" directory.
  2. Adjust the package name to match the current directory structure.
  3. If the current structure is intentional, update the configuration of the static analysis tool to ignore this warning.

Please clarify the intended package structure for the project.

🧰 Tools
🪛 buf

18-18: Files with package "yorkie.v1" must be within a directory "yorkie/v1" relative to root but were in directory "api/yorkie/v1".

(PACKAGE_DIRECTORY_MATCH)


38-38: 🛠️ Refactor suggestion

Consider adding a status field to the response message.

The SystemServiceDetachDocumentResponse message is currently empty. While this might be intentional if no data needs to be returned, it's often useful to include at least a status field in the response.

Consider adding a status field to confirm the success of the operation:

-message SystemServiceDetachDocumentResponse {}
+message SystemServiceDetachDocumentResponse {
+  bool success = 1;
+}

This addition would provide explicit confirmation that the document was successfully detached.

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

message SystemServiceDetachDocumentResponse {
  bool success = 1;
}
server/rpc/system_server.go (4)

115-131: 🛠️ Refactor suggestion

Reminder: Maintain consistent error handling.

Continue the practice of wrapping errors with additional context in this final section of the method.

For example:

 if _, err := packs.PushPull(
     ctx,
     s.backend,
     project,
     clientInfo,
     docInfo,
     doc.CreateChangePack(),
     packs.PushPullOptions{
         Mode:   types.SyncModePushPull,
         Status: document.StatusDetached,
     },
 ); err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to push changes: %w", err)
 }
📝 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.

	if _, err := packs.PushPull(
		ctx,
		s.backend,
		project,
		clientInfo,
		docInfo,
		doc.CreateChangePack(),
		packs.PushPullOptions{
			Mode:   types.SyncModePushPull,
			Status: document.StatusDetached,
		},
	); err != nil {
		return nil, fmt.Errorf("failed to push changes: %w", err)
	}

	return connect.NewResponse(&api.SystemServiceDetachDocumentResponse{}), nil
}

85-113: ⚠️ Potential issue

Add nil check before clearing presence.

To prevent potential nil pointer dereferences, add a nil check before clearing the presence.

Apply this change:

 if err := doc.Update(func(root *json.Object, p *presence.Presence) error {
+    if p != nil {
         p.Clear()
+    }
     return nil
 }); err != nil {
     return nil, err
 }
📝 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.

	clientInfo, err := clients.FindActiveClientInfo(ctx, s.backend.DB, types.ClientRefKey{
		ProjectID: project.ID,
		ClientID:  types.IDFromActorID(actorID),
	})
	if err != nil {
		return nil, err
	}

	docRefKey := types.DocRefKey{
		ProjectID: project.ID,
		DocID:     docID,
	}

	docInfo, err := documents.FindDocInfoByRefKey(ctx, s.backend, docRefKey)
	if err != nil {
		return nil, err
	}

	doc, err := packs.BuildDocForCheckpoint(ctx, s.backend, docInfo, clientInfo.Checkpoint(docID), actorID)
	if err != nil {
		return nil, err
	}

	if err := doc.Update(func(root *json.Object, p *presence.Presence) error {
		if p != nil {
			p.Clear()
		}
		return nil
	}); err != nil {
		return nil, err
	}

85-113: 🛠️ Refactor suggestion

Reminder: Ensure consistent error handling.

As mentioned earlier, consider wrapping errors with additional context throughout this section for better debugging.

For example:

 clientInfo, err := clients.FindActiveClientInfo(ctx, s.backend.DB, types.ClientRefKey{
     ProjectID: project.ID,
     ClientID:  types.IDFromActorID(actorID),
 })
 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to find active client info: %w", err)
 }

Apply similar changes to other error returns in this section.

Committable suggestion was skipped due to low confidence.


50-83: 🛠️ Refactor suggestion

Enhance error handling for better debugging.

While the error handling is present, it could be improved to provide more context for debugging. Consider wrapping errors with additional information.

Apply this pattern to error returns:

 actorID, err := time.ActorIDFromHex(req.Msg.ClientId)
 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to parse actor ID: %w", err)
 }

 docID, err := converter.FromDocumentID(req.Msg.DocumentId)
 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to parse document ID: %w", err)
 }

Apply similar changes to other error returns within the function to enhance error reporting.

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

// DetachDocument detaches the given document from the given client.
func (s *systemServer) DetachDocument(
	ctx context.Context,
	req *connect.Request[api.SystemServiceDetachDocumentRequest],
) (*connect.Response[api.SystemServiceDetachDocumentResponse], error) {
	actorID, err := time.ActorIDFromHex(req.Msg.ClientId)
	if err != nil {
		return nil, fmt.Errorf("failed to parse actor ID: %w", err)
	}

	docID, err := converter.FromDocumentID(req.Msg.DocumentId)
	if err != nil {
		return nil, fmt.Errorf("failed to parse document ID: %w", err)
	}

	info, err := s.backend.DB.FindProjectInfoByID(ctx, types.ID(req.Msg.ProjectId))
	if err != nil {
		return nil, fmt.Errorf("failed to find project info: %w", err)
	}
	project := info.ToProject()

	locker, err := s.backend.Coordinator.NewLocker(ctx, packs.PushPullKey(project.ID, key.Key(req.Msg.DocumentKey)))
	if err != nil {
		return nil, fmt.Errorf("failed to create locker: %w", err)
	}

	if err := locker.Lock(ctx); err != nil {
		return nil, fmt.Errorf("failed to acquire lock: %w", err)
	}
	defer func() {
		if err := locker.Unlock(ctx); err != nil {
			logging.DefaultLogger().Error(fmt.Errorf("failed to release lock: %w", err))
		}
	}()
server/backend/config.go (1)

85-86: 💡 Codebase verification

Add Validation for GatewayAddr

The GatewayAddr field is actively utilized in several parts of the codebase, including cmd/yorkie/server.go and server/clients/clients.go. However, there is currently no validation in the Validate() method to ensure that GatewayAddr is correctly formatted or reachable. To maintain robustness, please add appropriate validation for this field.

🔗 Analysis chain

LGTM. Consider adding validation and clarifying the purpose.

The addition of the GatewayAddr field is appropriate. However, consider the following suggestions:

  1. Add validation for this field in the Validate() method, especially if it's required or has a specific format.
  2. Provide more context about the purpose and impact of this gateway server in the comment.

To ensure this new field is properly utilized, let's check for its usage:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of GatewayAddr in the codebase
rg --type go 'GatewayAddr'

Length of output: 539

server/packs/packs.go (1)

215-231: ⚠️ Potential issue

Check for nil actorID before setting the actor

In the BuildDocForCheckpoint function, consider verifying that actorID is not nil before calling internalDoc.SetActor(actorID). This precaution prevents potential nil pointer dereferences, enhancing the robustness of the code.

Apply this diff to include a nil check:

 func BuildDocForCheckpoint(
     ctx context.Context,
     be *backend.Backend,
     docInfo *database.DocInfo,
     cp change.Checkpoint,
     actorID *time.ActorID,
 ) (*document.Document, error) {
     internalDoc, err := BuildInternalDocForServerSeq(ctx, be, docInfo, cp.ServerSeq)
     if err != nil {
         return nil, err
     }

+    if actorID == nil {
+        return nil, fmt.Errorf("actorID is nil")
+    }
     internalDoc.SetActor(actorID)
     internalDoc.SyncCheckpoint(cp.ServerSeq, cp.ClientSeq)
     return internalDoc.ToDocument(), nil
 }
📝 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.

// BuildDocForCheckpoint returns a new document for the given checkpoint.
func BuildDocForCheckpoint(
	ctx context.Context,
	be *backend.Backend,
	docInfo *database.DocInfo,
	cp change.Checkpoint,
	actorID *time.ActorID,
) (*document.Document, error) {
	internalDoc, err := BuildInternalDocForServerSeq(ctx, be, docInfo, cp.ServerSeq)
	if err != nil {
		return nil, err
	}

	if actorID == nil {
		return nil, fmt.Errorf("actorID is nil")
	}
	internalDoc.SetActor(actorID)
	internalDoc.SyncCheckpoint(cp.ServerSeq, cp.ClientSeq)
	return internalDoc.ToDocument(), nil
}

@hackerwins hackerwins force-pushed the hk-deactivate-client branch 3 times, most recently from 917bd2e to 56c2073 Compare October 16, 2024 09:21
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.

Caution

Inline review comments failed to post

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (10)
build/charts/yorkie-cluster/values.yaml (1)

6-7: LGTM! Consider adding a comment for clarity.

The addition of the gateway parameter under the yorkie section is appropriate and aligns with the PR objectives. It likely specifies the gateway service to be used for the Yorkie cluster.

Consider adding a brief comment above this line to explain the purpose of the gateway parameter, for example:

  # Specify the gateway service for the Yorkie cluster
  gateway: yorkie-gateway

This would enhance the configuration file's readability and maintainability.

api/yorkie/v1/system.proto (3)

18-18: Consider adjusting the package directory structure.

The package "yorkie.v1" is currently located in the directory "api/yorkie/v1". According to the static analysis tool, it should be in a directory "yorkie/v1" relative to the root. This mismatch might cause issues with some tools or conventions.

Consider one of the following options:

  1. Move the file to the correct directory structure.
  2. If the current structure is intentional, document the reason for deviating from the standard convention.
🧰 Tools
🪛 buf

18-18: Files with package "yorkie.v1" must be within a directory "yorkie/v1" relative to root but were in directory "api/yorkie/v1".

(PACKAGE_DIRECTORY_MATCH)


30-36: Consider creating an issue to track the TODO comment.

The TODO comment suggests replacing the current string fields with more complex types like types.Project, types.Client, and types.DocumentSummary. This could lead to a more robust and type-safe implementation in the future.

Would you like me to create a GitHub issue to track this potential enhancement? This would help ensure it's not forgotten and can be addressed in a future update.


38-38: Consider adding a status field to the response message.

The SystemServiceDetachDocumentResponse message is currently empty. While this might be intentional if no response data is needed, it's generally useful to include at least a status field or some indication of the operation's success.

Consider adding a field such as:

message SystemServiceDetachDocumentResponse {
  bool success = 1;
  // Optionally, you could also include an error message:
  // string error_message = 2;
}

This would provide confirmation that the document was successfully detached or indicate if there was an issue.

build/charts/yorkie-cluster/templates/yorkie/deployment.yaml (1)

Line range hint 52-53: Minor indentation improvement

The indentation of the containerPort entries has been corrected, improving the YAML formatting and readability of the file.

server/clients/housekeeping.go (1)

Line range hint 1-133: Overall, good improvements with room for further enhancements.

The introduction of CandidatePair and the corresponding changes improve the code structure and clarity. However, there are still opportunities for enhancement:

  1. Improve error handling in DeactivateInactives to handle individual deactivation errors.
  2. Update the documentation for FindDeactivateCandidates to reflect the new return type.
  3. Consider optimizing slice allocation in FindDeactivateCandidates.

Addressing these points would further improve the robustness and efficiency of the code.

server/packs/packs.go (2)

215-231: LGTM with a minor suggestion for error handling.

The BuildDocForCheckpoint function is well-structured and follows good practices. It effectively uses the new BuildInternalDocForServerSeq function, which improves modularity. The function signature is clear, and it correctly handles the context and error checking.

Consider wrapping the error returned from BuildInternalDocForServerSeq with additional context:

 internalDoc, err := BuildInternalDocForServerSeq(ctx, be, docInfo, cp.ServerSeq)
 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to build internal doc: %w", err)
 }

This will provide more context if an error occurs, making debugging easier.


Line range hint 215-290: Summary: Improved document building process with potential for further optimization

The introduced changes enhance the document building process by adding two new functions: BuildDocForCheckpoint and BuildInternalDocForServerSeq. These functions provide a more flexible and modular approach to document construction based on checkpoints and server sequences.

While these changes align with the overall goal of improving document handling, they don't directly implement the PR objective of detaching documents when a client is deactivated. This functionality is likely handled elsewhere in the codebase.

Consider the following recommendations for future improvements:

  1. Address the TODO comment in BuildInternalDocForServerSeq to optimize handling of large change sets.
  2. Implement comprehensive unit tests for these new functions to ensure their correctness and performance under various scenarios.
  3. Document the relationship between these new functions and the document detachment process mentioned in the PR objectives.

These changes lay a good foundation for improved document synchronization, but careful attention to performance optimization and thorough testing will be crucial as the system scales.

server/rpc/yorkie_server.go (1)

97-100: LGTM! Consider a minor improvement for consistency.

The addition of the project parameter to the clients.Deactivate function call is a good improvement. It provides more context for the deactivation process, which aligns with the PR objective of detaching documents when a client is deactivated.

For consistency with other methods in this file, consider moving the project := projects.From(ctx) line just before the clients.Deactivate call. This would make the code more readable and maintain a consistent pattern throughout the file.

Here's a suggested minor refactor:

func (s *yorkieServer) DeactivateClient(
	ctx context.Context,
	req *connect.Request[api.DeactivateClientRequest],
) (*connect.Response[api.DeactivateClientResponse], error) {
	actorID, err := time.ActorIDFromHex(req.Msg.ClientId)
	if err != nil {
		return nil, err
	}

	if err := auth.VerifyAccess(ctx, s.backend, &types.AccessInfo{
		Method: types.DeactivateClient,
	}); err != nil {
		return nil, err
	}

-	project := projects.From(ctx)
	_, err = clients.Deactivate(ctx, s.backend, project, types.ClientRefKey{
+	project := projects.From(ctx)
+	_, err = clients.Deactivate(ctx, s.backend, project, types.ClientRefKey{
		ProjectID: project.ID,
		ClientID:  types.IDFromActorID(actorID),
	})
	if err != nil {
		return nil, err
	}

	return connect.NewResponse(&api.DeactivateClientResponse{}), nil
}
server/clients/clients.go (1)

Missing project Parameter in Activate Function Calls

Several calls to the Activate function do not include the required project parameter:

  • test/integration/retention_test.go
  • test/integration/main_test.go
  • test/integration/gc_test.go
  • test/integration/client_test.go
  • test/integration/document_test.go
  • test/integration/admin_test.go
  • test/integration/auth_webhook_test.go
  • test/helper/helper.go
  • test/bench/grpc_bench_test.go
  • test/integration/server_test.go
  • test/complex/main_test.go
  • client/client_test.go

Action Required: Update all instances of the Activate function to include the new project parameter to prevent potential runtime errors.

🔗 Analysis chain

Line range hint 38-43: Ensure all callers of Activate are updated with the new project parameter

The Activate function signature now includes project *types.Project as a parameter. Please verify that all calls to Activate in the codebase have been updated accordingly to prevent any runtime errors due to mismatched parameters.

To confirm that all callers have been updated, you can run the following script:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to the `Activate` function and check if they include the new `project` parameter.

# Search for calls to Activate in Go files, excluding the function definition itself.
rg --type go --glob '!.*/clients.go' 'Activate\(' -A 1

Length of output: 4709

🛑 Comments failed to post (5)
server/clients/clients.go (3)

60-65: ⚠️ Potential issue

Evaluate the use of WithInsecure(true) for system client connections

The systemClient is initialized with system.WithInsecure(true), which disables transport security for gRPC connections. In production environments, using insecure connections can expose the system to security risks such as man-in-the-middle attacks. Consider configuring the connection to use secure credentials or making the insecurity optional based on the environment (e.g., development vs. production).

To enhance security, you might update the initialization as follows:

-systemClient, err := system.Dial(be.Config.GatewayAddr, system.WithInsecure(true))
+systemClient, err := system.Dial(be.Config.GatewayAddr)

Ensure that the system.Dial function and your environment are configured to handle secure connections appropriately.

Committable suggestion was skipped due to low confidence.


98-98: ⚠️ Potential issue

Correct grammatical error in the function comment

The comment for FindActiveClientInfo should be updated for grammatical accuracy and to follow Go's convention for documentation comments.

Apply this diff to fix the comment:

-// FindActiveClientInfo find the active Client info by the given ref key.
+// FindActiveClientInfo finds the active client info by the given reference key.

This ensures the comment is clear and follows proper grammar.

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

// FindActiveClientInfo finds the active client info by the given reference key.

48-54: 💡 Codebase verification

Outdated Calls to Deactivate Function Found

Several calls to Deactivate are missing the new be and project parameters. Please update them to match the new function signature to prevent runtime errors.

Affected files:

  • test/integration/retention_test.go
  • test/integration/main_test.go
  • test/integration/client_test.go
  • test/integration/auth_webhook_test.go
  • test/integration/document_test.go
  • test/integration/gc_test.go
  • test/complex/main_test.go
  • test/bench/grpc_bench_test.go
  • client/client.go
🔗 Analysis chain

Ensure all callers of Deactivate are updated with the new be and project parameters

The Deactivate function signature now includes be *backend.Backend and project *types.Project as parameters. Please verify that all calls to Deactivate across the codebase have been updated to pass these new parameters to prevent any mismatches or runtime errors.

To check for any outdated usages, you can run the following script:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to the `Deactivate` function and check if they include the new parameters.

# Search for calls to Deactivate in Go files, excluding the function definition itself.
rg --type go --glob '!.*/clients.go' 'Deactivate\(' -A 1

Length of output: 3361

system/client.go (2)

133-142: ⚠️ Potential issue

Check for nil clientID to avoid potential nil pointer dereference

The parameter clientID is a pointer (*time.ActorID), and calling clientID.String() at line 142 may lead to a nil pointer dereference if clientID is nil.

Consider adding a nil check for clientID before using it, or ensure that clientID is not nil when calling this function.


140-146: ⚠️ Potential issue

Avoid including apiKey in the shard key to prevent security risks

Including apiKey in the shard key by passing it to withShardKey may expose sensitive information, posing a security risk. It's recommended to remove apiKey from the shard key and include it in the appropriate authorization header instead.

Apply this diff to exclude apiKey from the shard key and add an Authorization header:

-        ), apiKey, docKey.String()))
+        ), docKey.String()))

+    connectReq := withShardKey(connect.NewRequest(&api.SystemServiceDetachDocumentRequest{
+        ProjectId:   projectID.String(),
+        ClientId:    clientID.String(),
+        DocumentId:  docID.String(),
+        DocumentKey: docKey.String(),
+    }), docKey.String())
+    connectReq.Header().Add("Authorization", "Bearer "+apiKey)

Committable suggestion was skipped due to low confidence.

@hackerwins hackerwins force-pushed the hk-deactivate-client branch from 56c2073 to d97f668 Compare October 16, 2024 09:24
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: 2

🧹 Outside diff range and nitpick comments (2)
api/yorkie/v1/system.proto (2)

25-28: LGTM: SystemService is well-defined with a clear purpose.

The SystemService definition is concise and includes an appropriate RPC method for detaching documents.

Consider expanding the comment to provide more context:

-// System is a service that provides an API for Cluster.
+// SystemService provides API endpoints for cluster-level operations, such as managing document attachments.

This gives a clearer indication of the service's scope and functionality.


30-36: LGTM: Request message structure is appropriate for the operation.

The SystemServiceDetachDocumentRequest message contains all necessary fields to uniquely identify a document for detachment.

Consider enhancing the TODO comment:

-  // TODO(hackerwins): Consider to replace this fields with types.Project, types.Client, types.DocumentSummary
+  // TODO(hackerwins): Replace these fields with types.Project, types.Client, and types.DocumentSummary
+  // for improved type safety and consistency. Track this in issue #XXXX.

This provides more context and links the TODO to a trackable issue.

Would you like me to create a GitHub issue to track this TODO item?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 00cd44e and d97f668.

📒 Files selected for processing (6)
  • api/yorkie/v1/system.proto (1 hunks)
  • build/charts/yorkie-cluster/templates/yorkie/deployment.yaml (1 hunks)
  • build/charts/yorkie-cluster/values.yaml (1 hunks)
  • server/clients/clients.go (2 hunks)
  • test/complex/main_test.go (1 hunks)
  • test/integration/housekeeping_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • build/charts/yorkie-cluster/templates/yorkie/deployment.yaml
  • build/charts/yorkie-cluster/values.yaml
  • test/integration/housekeeping_test.go
🧰 Additional context used
🪛 buf
api/yorkie/v1/system.proto

18-18: Files with package "yorkie.v1" must be within a directory "yorkie/v1" relative to root but were in directory "api/yorkie/v1".

(PACKAGE_DIRECTORY_MATCH)

🔇 Additional comments (7)
api/yorkie/v1/system.proto (1)

1-24: LGTM: Copyright, package declaration, and options are well-defined.

The copyright notice, syntax declaration, package information, and language-specific options are correctly specified and up-to-date.

Regarding the static analysis hint about package directory mismatch, let's verify the project structure:

This will help us understand if the current structure is consistent across the project or if adjustments are needed.

✅ Verification successful

Verified: Package directory matches declarations.

The project structure aligns with the package declarations, and no discrepancies were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the project structure for proto files

# Test: Check if there are other proto files in the same directory
echo "Other proto files in api/yorkie/v1:"
fd -e proto . api/yorkie/v1

# Test: Check if there's a yorkie/v1 directory with proto files
echo "Proto files in yorkie/v1 (if exists):"
fd -e proto . yorkie/v1

# Test: Check the overall structure of proto files
echo "Overall structure of proto files:"
fd -e proto . | sed 's/^/  /'

Length of output: 655

🧰 Tools
🪛 buf

18-18: Files with package "yorkie.v1" must be within a directory "yorkie/v1" relative to root but were in directory "api/yorkie/v1".

(PACKAGE_DIRECTORY_MATCH)

server/clients/clients.go (6)

25-27: Import statements are appropriately added.

The addition of the backend and system packages is necessary for the new functionalities introduced in the code.


51-54: Updated Deactivate function signature enhances functionality.

The updated function signature now accepts *backend.Backend and *types.Project parameters, which allows access to the backend services and project-specific information required for document detachment and client deactivation.


55-59: Proper retrieval of active client information.

Using FindActiveClientInfo ensures that only active clients are processed, and appropriate error handling is in place if the client is not found or not active.


60-65: Dialing the system service with dynamic gateway address.

The use of be.Config.GatewayAddr instead of a hardcoded address enhances flexibility across different deployment environments. The system.WithInsecure(true) option is acceptable if the system operates within a trusted network, but consider using secure communication channels if possible to enhance security.

If security is a concern, verify whether the system service supports secure connections and update the dialing options accordingly.


66-85: Efficient document detachment before client deactivation.

The loop correctly iterates over the client's documents, checks their status, and detaches them using systemClient.DetachDocument. Error handling is appropriately managed at each step.

Note on the existing TODO about N+1 problem.

There is a TODO comment to solve the N+1 problem when fetching document information. Since this has been noted in previous reviews, ensure that this optimization is addressed in a future update to avoid potential performance issues.


90-95: Client deactivation is performed after successful document detachment.

The client is properly deactivated using be.DB.DeactivateClient after all associated documents have been detached. Error handling ensures that any issues during deactivation are reported.

api/yorkie/v1/system.proto Outdated Show resolved Hide resolved
test/complex/main_test.go 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: 4

🧹 Outside diff range and nitpick comments (5)
api/docs/yorkie/v1/system.openapi.yaml (2)

12-24: Add a description for the DetachDocument operation.

The path for /yorkie.v1.SystemService/DetachDocument is well-defined, but it lacks a description. Consider adding a brief explanation of what this operation does to improve API documentation.

For example, you could add:

description: "Detaches a document from a client when the client is deactivated."

290-291: Address the TODO comment in SystemServiceDetachDocumentRequest schema.

There's a TODO comment suggesting a potential refactoring of the project, client, and documentSummary fields. Consider creating an issue to track this refactoring task and remove the TODO comment from the OpenAPI specification.

system/client.go (3)

61-66: Clarify the struct comment for Client

The comment for the Client struct mentions it is a client for the admin service. Since it interacts with the SystemService, consider updating the comment to reflect this for clarity.

Apply this diff:

-// Client is a client for admin service.
+// Client is a client for the SystemService.
 type Client struct {
     conn   *http.Client
     client v1connect.SystemServiceClient
     logger *zap.Logger
 }

125-128: Update the comment for the Close method

The comment for the Close method refers to closing the connection to the admin service. For consistency and accuracy, update it to refer to the SystemService.

Apply this diff:

-// Close closes the connection to the admin service.
+// Close closes the connection to the SystemService.
 func (c *Client) Close() {
     c.conn.CloseIdleConnections()
 }

157-159: Use standard Go comment style for multi-line comments

The comment for withShardKey uses block comment syntax (/** ... */), which is uncommon in Go. It's idiomatic to use // for comments, even for multi-line comments. Consider updating for consistency.

Apply this diff:

-/**
-* withShardKey returns a context with the given shard key in metadata.
- */
+// withShardKey returns a context with the given shard key in metadata.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d97f668 and 2c225c7.

⛔ Files ignored due to path filters (1)
  • api/yorkie/v1/system.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (5)
  • api/docs/yorkie/v1/system.openapi.yaml (1 hunks)
  • api/yorkie/v1/system.proto (1 hunks)
  • server/clients/clients.go (2 hunks)
  • server/rpc/system_server.go (1 hunks)
  • system/client.go (1 hunks)
🧰 Additional context used
🪛 buf
api/yorkie/v1/system.proto

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

🔇 Additional comments (11)
api/yorkie/v1/system.proto (3)

28-30: LGTM: Service definition is clear and aligned with PR objectives.

The SystemService with the DetachDocument RPC method is well-defined and matches the PR's goal of detaching documents when a client is deactivated.


32-38: 🛠️ Refactor suggestion

Consider adding a status field to the response message.

The SystemServiceDetachDocumentRequest message is well-defined with the necessary fields. However, the SystemServiceDetachDocumentResponse message is currently empty. As suggested in a previous review, including a status field or operation result could provide valuable feedback.

Consider modifying the response message:

-message SystemServiceDetachDocumentResponse {}
+message SystemServiceDetachDocumentResponse {
+  // Indicates whether the detach operation was successful
+  bool success = 1;
+  // Optional message providing additional details about the operation
+  string message = 2;
+}

This change would allow the service to communicate the operation's outcome more explicitly.


20-20: Verify the import statement for resources.proto.

The static analysis tool indicates that the file yorkie/v1/resources.proto does not exist. Please ensure that this file is present in the correct location within your project structure.

✅ Verification successful

Import statement for resources.proto is valid and the file exists.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the imported proto file

# Test: Check if the resources.proto file exists
fd -t f resources.proto

Length of output: 55

🧰 Tools
🪛 buf

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

api/docs/yorkie/v1/system.openapi.yaml (5)

1-11: LGTM: API Information and Servers section is well-defined.

The OpenAPI version, API information, and server definitions are clear and appropriate. Good job on providing both production and local server environments.


25-300: LGTM: Components section is well-structured and comprehensive.

The components section, including request bodies, responses, and schemas, is well-defined and uses proper references. The use of google.protobuf.Timestamp for date-time fields is a good practice. The schemas are detailed and cover all necessary aspects of the API.


301-307: LGTM: Security scheme is well-defined.

The API key authentication scheme is properly defined and applied globally. This ensures that all endpoints are secured by default, which is a good security practice.


308-310: LGTM: Tags section is concise and informative.

The tag for yorkie.v1.SystemService is well-defined and includes a helpful description of the service's purpose.


1-310: Overall, excellent OpenAPI specification for the Yorkie API.

This OpenAPI 3.1.0 specification is well-structured, comprehensive, and follows best practices. It provides clear definitions for the API's endpoints, request/response schemas, and security requirements. The use of references and appropriate data types enhances maintainability and clarity.

A few minor improvements were suggested:

  1. Adding a description for the DetachDocument operation.
  2. Addressing the TODO comment in the SystemServiceDetachDocumentRequest schema.

These small enhancements will further improve the already high-quality specification.

server/rpc/system_server.go (3)

38-47: Initialization of systemServer is appropriate

The systemServer struct is correctly initialized with the provided backend in the newSystemServer function, ensuring the server has access to necessary backend services.


71-73: Handle locker unlock errors appropriately

Currently, if unlocking the locker fails, the error is logged. Consider whether additional error handling is needed, such as retrying the unlock or propagating the error if it could have significant implications.


76-82: Check for client deactivation status

Ensure that the client retrieved is active before proceeding. If the client is already deactivated, attempting to detach documents may not be necessary and could lead to errors.

Run the following script to verify the client's status:

server/clients/clients.go Outdated Show resolved Hide resolved
server/rpc/system_server.go Outdated Show resolved Hide resolved
server/rpc/system_server.go Outdated Show resolved Hide resolved
system/client.go Outdated Show resolved Hide resolved
Copy link

codecov bot commented Oct 16, 2024

Codecov Report

Attention: Patch coverage is 18.01802% with 91 lines in your changes missing coverage. Please review.

Project coverage is 48.30%. Comparing base (9513091) to head (f89f6a4).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
server/rpc/cluster_server.go 6.25% 60 Missing ⚠️
pkg/document/internal_document.go 0.00% 12 Missing ⚠️
server/packs/packs.go 0.00% 8 Missing ⚠️
server/backend/database/client_info.go 0.00% 5 Missing ⚠️
pkg/document/document.go 0.00% 2 Missing ⚠️
client/client.go 0.00% 1 Missing ⚠️
server/packs/pushpull.go 0.00% 1 Missing ⚠️
server/rpc/yorkie_server.go 87.50% 1 Missing ⚠️
server/server.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1036      +/-   ##
==========================================
- Coverage   48.76%   48.30%   -0.46%     
==========================================
  Files          79       80       +1     
  Lines       11343    11415      +72     
==========================================
- Hits         5531     5514      -17     
- Misses       5269     5358      +89     
  Partials      543      543              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 2c225c7 and e0753b4.

📒 Files selected for processing (3)
  • server/clients/clients.go (2 hunks)
  • server/rpc/server.go (1 hunks)
  • system/client.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/rpc/server.go
🧰 Additional context used
🔇 Additional comments (6)
server/clients/clients.go (4)

25-27: LGTM

The newly added import statements are appropriate and necessary for the updated functionality.


51-56: Updated function signature reflects necessary changes

The Deactivate function now accepts be *backend.Backend and project *types.Project as parameters instead of just db database.Database. This change provides access to the backend services and project information required for detaching documents properly.


71-78: Address the N+1 query problem in the document detachment loop

The current implementation fetches docInfo individually for each document using FindDocInfoByRefKey. This can lead to performance issues due to multiple database calls when a client has many documents attached. The TODO comment on line 71 acknowledges this issue.


90-95: LGTM

Client deactivation is handled correctly, and errors are appropriately managed.

system/client.go (2)

62-95: Implementation of Client struct and New function looks good

The Client struct encapsulates the necessary components for the admin service client, and the New function correctly initializes the client with configurable options.


140-150: ⚠️ Potential issue

Fix misaligned parentheses in DetachDocument method

There appears to be a misalignment of parentheses in the call to c.client.DetachDocument, which could lead to a syntax error during compilation.

Apply this diff to correct the syntax:

 func (c *Client) DetachDocument(
     ctx context.Context,
     project *types.Project,
     clientID *time.ActorID,
     docID types.ID,
     apiKey string,
     docKey key.Key,
 ) error {
     _, err := c.client.DetachDocument(
         ctx,
-        withShardKey(connect.NewRequest(&api.SystemServiceDetachDocumentRequest{
+        withShardKey(
+            connect.NewRequest(&api.SystemServiceDetachDocumentRequest{
                 Project:  converter.ToProject(project),
                 ClientId: clientID.String(),
                 DocumentSummary: converter.ToDocumentSummary(&types.DocumentSummary{
                     ID:  docID,
                     Key: docKey,
                 }),
-            },
-            ), apiKey, docKey.String()))
+            }),
+            apiKey, docKey.String(),
+        ),
+    )
     if err != nil {
         return err
     }

     return nil
 }

Likely invalid or redundant comment.

server/clients/clients.go Outdated Show resolved Hide resolved
system/client.go Outdated Show resolved Hide resolved
system/client.go 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: 7

🧹 Outside diff range and nitpick comments (5)
api/yorkie/v1/cluster.proto (1)

32-38: Consider adding a status field to the response message.

The message definitions for ClusterServiceDetachDocumentRequest and ClusterServiceDetachDocumentResponse are well-structured. The request message contains all necessary fields for the detach operation.

However, consider adding a status field to the ClusterServiceDetachDocumentResponse to provide explicit feedback on the operation's success or failure. This could be implemented as follows:

-message ClusterServiceDetachDocumentResponse {}
+message ClusterServiceDetachDocumentResponse {
+  bool success = 1;
+  string message = 2;  // Optional: for additional details or error messages
+}

This change would provide more informative responses to the client, improving error handling and debugging capabilities.

api/docs/yorkie/v1/cluster.openapi.yaml (3)

1-11: LGTM! Consider adding contact information.

The OpenAPI metadata and server definitions are well-structured and provide essential information about the API. Good job on including both production and local development server URLs.

Consider adding a contact field in the info section to provide information on how to reach the API maintainers. This can be helpful for users who need support or want to report issues. For example:

info:
  # ... existing fields ...
  contact:
    name: Yorkie Team
    url: https://yorkie.dev/contact
    email: support@yorkie.dev

12-24: Add summary and description to the endpoint.

The endpoint definition is structured well, but it lacks a summary and description. Adding these would improve the API documentation and make it more user-friendly.

Consider adding a summary and description to the endpoint like this:

/yorkie.v1.ClusterService/DetachDocument:
  post:
    summary: Detach a document from a client
    description: |
      This endpoint detaches a document from a specified client in the cluster.
      It's typically used when a client is deactivated or no longer needs access to the document.
    # ... rest of the existing definition ...

Also, consider adding operationId for easier reference in generated client code:

operationId: detachDocument

300-309: Security scheme is good, but could be more specific.

The API key authentication scheme is well-defined and appropriately applied globally. This ensures all endpoints are protected by default.

Consider specifying the expected format of the API key in the security scheme description. This can help API consumers understand how to properly construct the Authorization header. For example:

securitySchemes:
  ApiKeyAuth:
    type: apiKey
    in: header
    name: Authorization
    description: "API key authentication. Use the format: 'Bearer <API_KEY>'"

This addition clarifies that the API key should be prefixed with "Bearer " in the Authorization header, which is a common convention for token-based authentication.

client/client.go (1)

Line range hint 1-1000: Overall impact of the protocol selection change

The modification to the Dial method improves the security and clarity of the protocol selection process. However, given the critical nature of the Client struct in establishing connections, please ensure the following:

  1. Comprehensive testing of the Dial method with various configurations (with and without certificate files) to verify correct behavior.
  2. Review and update of any client-side documentation or examples that demonstrate connection establishment.
  3. Consideration of backward compatibility, especially if any existing clients rely on the previous behavior.

Consider adding a configuration option to explicitly set the desired protocol (HTTP/HTTPS) in addition to the certificate-based inference. This would provide more flexibility and control to the clients while maintaining the security improvements.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e0753b4 and 15f7e2e.

⛔ Files ignored due to path filters (1)
  • api/yorkie/v1/cluster.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (9)
  • admin/client.go (3 hunks)
  • api/docs/yorkie/v1/cluster.openapi.yaml (1 hunks)
  • api/yorkie/v1/cluster.proto (1 hunks)
  • api/yorkie/v1/v1connect/cluster.connect.go (1 hunks)
  • client/client.go (1 hunks)
  • cluster/client.go (1 hunks)
  • server/clients/clients.go (2 hunks)
  • server/rpc/cluster_server.go (1 hunks)
  • server/rpc/server.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/rpc/server.go
🧰 Additional context used
🪛 buf
api/yorkie/v1/cluster.proto

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

🔇 Additional comments (15)
api/yorkie/v1/cluster.proto (2)

27-30: LGTM: Service definition is clear and consistent.

The ClusterService definition with the DetachDocument RPC method is well-structured and aligns with the PR objectives. The naming convention follows the standard protobuf style, and the method signature is appropriate for the intended functionality.


1-26: Verify the existence of the imported file.

The file header, syntax declaration, package declaration, and language-specific options look good. However, there's a potential issue with the imported file.

Please run the following script to check if the imported file exists:

If the file doesn't exist, please ensure it's created or update the import statement accordingly.

🧰 Tools
🪛 buf

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

admin/client.go (4)

75-75: LGTM: Addition of isInsecure field enhances clarity.

The new isInsecure field in the Client struct centralizes the insecure connection logic, improving the overall design and maintainability of the code.


104-104: LGTM: Proper initialization of isInsecure field.

The isInsecure field is correctly initialized in the New function, ensuring consistency with the Options struct and proper setup of the Client instance.


Line range hint 125-129: LGTM: Improved protocol selection based on isInsecure field.

The Dial method now correctly uses the isInsecure field to determine the appropriate protocol (http or https). This change centralizes the insecure connection logic and improves code organization.


Line range hint 75-129: Summary: Successful implementation of isInsecure feature.

The changes introduce an isInsecure field to the Client struct and update the New and Dial methods accordingly. This implementation centralizes the insecure connection logic, enhancing code clarity and maintainability. The changes are consistent and well-integrated throughout the file.

api/docs/yorkie/v1/cluster.openapi.yaml (1)

1-309: Overall, excellent API specification with room for minor enhancements.

This OpenAPI 3.1.0 specification for the Yorkie ClusterService is well-structured and comprehensive. It provides clear definitions for endpoints, request/response schemas, and security requirements. The use of reusable components and standard formats (like Google's protobuf Timestamp) demonstrates good API design practices.

To further improve this already solid specification, consider implementing the following suggestions:

  1. Add contact information in the API metadata.
  2. Enhance the endpoint documentation with summaries, descriptions, and operation IDs.
  3. Clarify empty response schemas and improve descriptions for certain fields (e.g., clientDeactivateThreshold, secretKey).
  4. Specify the expected format for the API key in the security scheme description.

These enhancements will make the API even more user-friendly and easier to integrate with.

client/client.go (1)

Line range hint 196-200: Improved security and clarity in protocol selection

The change in determining whether to use HTTP or HTTPS based on the presence of a certificate file (c.options.CertFile) is a good improvement. It provides a more direct and secure approach to protocol selection.

However, please consider the following points:

  1. Ensure that all client configurations are updated to set the CertFile option correctly if HTTPS is required.
  2. Update any documentation or client setup guides to reflect this change in behavior.
  3. Consider adding a log statement (debug level) to indicate which protocol is being used, for easier troubleshooting.

To ensure this change doesn't introduce any regressions, please run the following verification:

server/clients/clients.go (3)

25-26: Import of cluster package is appropriate

The addition of the cluster package is necessary for dialing the cluster service using cluster.Dial. No issues found.


60-67: Dynamic gateway address improves flexibility

Replacing the hardcoded system service address with be.Config.GatewayAddr enhances configurability and supports different deployment environments.


73-81: Previous comment on N+1 query issue still applicable

The code still fetches docInfo individually within the loop, leading to potential performance issues due to multiple database calls. The TODO comment acknowledges this issue.

server/rpc/cluster_server.go (2)

73-76: Ensure proper handling of unlock errors

Currently, if an error occurs during locker.Unlock(ctx), it is logged but not propagated. Depending on the criticality, consider whether additional handling is necessary, such as retrying the unlock or returning the error to the caller to prevent potential resource leaks or deadlocks.


101-104: Verify that clearing presence detaches the document correctly

In the doc.Update function, only p.Clear() is called to detach the document. Please confirm that this action sufficiently detaches the document and that no additional steps are required, such as updating document status or notifying other components.

cluster/client.go (1)

142-152: ⚠️ Potential issue

Ensure apiKey is not unintentionally included in the shard key

In the DetachDocument method, the apiKey is being passed to the withShardKey function along with docKey.String(). Including the apiKey in the shard key might not be appropriate and could raise security concerns if the shard key is logged or exposed.

Consider modifying the code to handle the apiKey separately, possibly by adding it to the request headers as an authorization token.

Apply this diff to remove apiKey from the shard key:

 		}),
-		apiKey, docKey.String()))
+		docKey.String()))

+	// Add the apiKey to the request header as an authorization token.
+	req := withShardKey(connect.NewRequest(...), docKey.String())
+	req.Header().Add("Authorization", fmt.Sprintf("Bearer %s", apiKey))
+	_, err := c.client.DetachDocument(ctx, req)

Run the following script to verify how apiKey should be handled in similar contexts:

#!/bin/bash
# Description: Check how apiKey is managed in requests across the codebase.

# Find all occurrences where apiKey is set in request headers.
rg --type go 'Header\(\)\.Add\("Authorization",.*apiKey.*\)'

# Search for usage patterns of withShardKey without apiKey.
rg --type go 'withShardKey\(.*docKey\.String\(\)\)'
api/yorkie/v1/v1connect/cluster.connect.go (1)

1-120: LGTM!

The new ClusterService client and handler code are correctly implemented and align with the service definitions. The generated code follows best practices and maintains consistency across the service interfaces.

api/docs/yorkie/v1/cluster.openapi.yaml Show resolved Hide resolved
server/clients/clients.go Show resolved Hide resolved
server/rpc/cluster_server.go Outdated Show resolved Hide resolved
cluster/client.go Show resolved Hide resolved
cluster/client.go Outdated Show resolved Hide resolved
cluster/client.go Show resolved Hide resolved
@hackerwins hackerwins force-pushed the hk-deactivate-client branch from 15f7e2e to 9372629 Compare October 17, 2024 06:29
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)
api/yorkie/v1/cluster.proto (1)

32-38: LGTM: Message definitions are well-structured. Consider adding a status field to the response.

The ClusterServiceDetachDocumentRequest message is well-defined with appropriate fields for the detach operation. The empty ClusterServiceDetachDocumentResponse is acceptable if no data needs to be returned.

Consider adding a status field to the response message to explicitly indicate the success or failure of the operation. For example:

-message ClusterServiceDetachDocumentResponse {}
+message ClusterServiceDetachDocumentResponse {
+  bool success = 1;
+  string message = 2;  // Optional: for additional information or error messages
+}

This change would provide more explicit feedback about the operation's outcome.

api/docs/yorkie/v1/cluster.openapi.yaml (3)

12-24: Add a description for the DetachDocument endpoint.

The endpoint definition is correct, but it lacks a description. Consider adding a brief explanation of the endpoint's purpose to improve API documentation.

For example:

description: "Detaches a document from a client in the cluster."

178-205: Enhance schema documentation and clarify empty response.

  1. Add descriptions to the ClusterServiceDetachDocumentRequest schema properties to improve documentation.
  2. The ClusterServiceDetachDocumentResponse schema is empty. If this is intentional (i.e., the operation doesn't return any data), add a description to clarify this. Otherwise, add the expected properties to the schema.

Example improvements:

yorkie.v1.ClusterServiceDetachDocumentRequest:
  properties:
    clientId:
      description: "Unique identifier of the client detaching the document."
    documentSummary:
      description: "Summary information of the document being detached."
    project:
      description: "Project information related to the document detachment."

yorkie.v1.ClusterServiceDetachDocumentResponse:
  description: "Response object for the DetachDocument operation. This response is intentionally empty as the operation does not return any data."

261-265: Improve clientDeactivateThreshold field definition.

The clientDeactivateThreshold field in the Project schema is defined as a string without a specific format or description. Consider using a more specific format and adding a description to clarify its purpose and expected value.

Suggested improvement:

clientDeactivateThreshold:
  type: string
  format: duration
  description: "The threshold duration for client deactivation, in ISO 8601 duration format (e.g., 'PT15M' for 15 minutes)."
server/clients/clients.go (1)

Line range hint 45-45: Update the function comment to reflect the new logic

The Deactivate function now detaches documents before deactivating the client. Consider updating the function's documentation comment to reflect this change for better clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 15f7e2e and 9372629.

⛔ Files ignored due to path filters (1)
  • api/yorkie/v1/cluster.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (9)
  • admin/client.go (3 hunks)
  • api/docs/yorkie/v1/cluster.openapi.yaml (1 hunks)
  • api/yorkie/v1/cluster.proto (1 hunks)
  • api/yorkie/v1/v1connect/cluster.connect.go (1 hunks)
  • client/client.go (1 hunks)
  • cluster/client.go (1 hunks)
  • server/clients/clients.go (2 hunks)
  • server/rpc/cluster_server.go (1 hunks)
  • server/rpc/server.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • admin/client.go
  • api/yorkie/v1/v1connect/cluster.connect.go
  • client/client.go
  • cluster/client.go
  • server/rpc/cluster_server.go
  • server/rpc/server.go
🧰 Additional context used
🪛 buf
api/yorkie/v1/cluster.proto

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

🔇 Additional comments (7)
api/yorkie/v1/cluster.proto (2)

27-30: LGTM: Service definition is clear and aligns with PR objectives.

The ClusterService definition with the DetachDocument RPC method is well-structured and follows proper naming conventions. It accurately represents the functionality described in the PR objectives.


20-20: Verify the import statement and ensure the referenced file exists.

The static analysis tool indicates that the file "yorkie/v1/resources.proto" does not exist. Please verify if this file is present in the correct location within the project structure.

To verify the existence of the file, you can run the following command:

If the file is missing, consider creating it or updating the import statement. Would you like assistance in resolving this issue?

🧰 Tools
🪛 buf

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

api/docs/yorkie/v1/cluster.openapi.yaml (3)

1-11: LGTM: Well-structured OpenAPI metadata and server information.

The OpenAPI version, API information, and server URLs are correctly defined and provide clear information about the Yorkie API.


300-304: LGTM: Well-defined API key authentication scheme.

The security scheme for API key authentication is correctly defined, specifying the use of the Authorization header.


305-309: LGTM: Clear and concise tag definition for ClusterService.

The tag for the ClusterService is well-defined, including a clear description of its purpose.

server/clients/clients.go (2)

48-49: Align parameter usage between Activate and Deactivate functions

The Deactivate function now accepts be *backend.Backend and project *types.Project, whereas the Activate function accepts db database.Database and project *types.Project. For consistency and better maintainability, consider updating the Activate function to also use be *backend.Backend.


73-81: Address the N+1 query problem in the document detachment loop

The current implementation fetches docInfo individually for each document within the loop using FindDocInfoByRefKey. This can lead to performance issues due to multiple database calls, especially when a client has many documents attached. The TODO comment on line 73 acknowledges this issue.

Consider fetching all required DocInfo records in a single batch operation before the loop. You could implement a method like FindDocInfosByRefKeys that accepts a slice of DocRefKeys and returns the corresponding DocInfo objects. This change would reduce the number of database queries and improve performance.

@hackerwins hackerwins force-pushed the hk-deactivate-client branch from 9372629 to daf0b91 Compare October 17, 2024 06:41
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)
api/yorkie/v1/cluster.proto (2)

27-30: LGTM: Service definition is clear and aligned with PR objectives.

The ClusterService with its DetachDocument RPC method is well-defined and consistent with the goal of detaching documents when a client is deactivated.

Consider adding a brief comment above the DetachDocument RPC method to describe its purpose and any important details about its usage. For example:

// DetachDocument detaches a document from a client in the cluster.
// This is typically called when a client is deactivated.
rpc DetachDocument (ClusterServiceDetachDocumentRequest) returns (ClusterServiceDetachDocumentResponse) {}

32-38: LGTM: Message definitions are appropriate for the DetachDocument operation.

The ClusterServiceDetachDocumentRequest message includes all necessary fields for identifying the project, client, and document to be detached. The empty ClusterServiceDetachDocumentResponse is suitable for this operation.

For consistency with other parts of the Yorkie API, consider renaming the messages to remove the service name prefix:

message DetachDocumentRequest {
  // ... (keep the existing fields)
}

message DetachDocumentResponse {}

This change would make the messages more reusable if needed in other contexts and aligns with common gRPC naming conventions.

cluster/client.go (1)

85-90: Enhance error context when creating the default logger

When creating the default production logger, consider adding more context to the error message. This will aid in debugging and understanding the source of the failure.

Apply this diff to wrap the error with additional context:

 if logger == nil {
   l, err := zap.NewProduction()
   if err != nil {
-    return nil, fmt.Errorf("create logger: %w", err)
+    return nil, fmt.Errorf("create default production logger for cluster client: %w", err)
   }
   logger = l
 }
server/packs/packs_test.go (1)

Line range hint 234-309: Address skipped test case.

This test case is currently skipped due to an unresolved pushpull consistency problem. The test appears to be checking important edge cases related to change duplication and client info updates, which are crucial for the system's reliability.

To ensure this doesn't get overlooked:

  1. Create an issue to track the resolution of the pushpull consistency problem.
  2. Add a TODO comment in the code referencing the created issue.
  3. Once resolved, remove the t.Skip line and re-enable the test.

Would you like me to create a GitHub issue for tracking this task?

api/docs/yorkie/v1/cluster.openapi.yaml (2)

12-24: Add a description for the DetachDocument endpoint.

The endpoint is well-defined, but it lacks a description. Consider adding a brief explanation of the endpoint's purpose to improve API documentation.

For example:

description: "Detaches a document from a client in the cluster."

178-200: Add descriptions to the ClusterServiceDetachDocumentRequest schema properties.

Consider adding descriptions to the clientId, documentSummary, and project properties to provide more context about their purpose and usage.

For example:

clientId:
  type: string
  description: "Unique identifier of the client detaching the document."
server/clients/clients.go (2)

60-61: Address the TODO: Introduce cluster client pool

The current implementation creates a new cluster client connection for each deactivation. Introducing a cluster client pool, as mentioned in the TODO, would improve performance by reusing connections and reducing overhead.

Would you like assistance in implementing a cluster client pool? I can help provide a proposed solution or open a GitHub issue to track this task.


41-92: Update unit tests to cover changes in activation and deactivation

With the modifications to Activate and Deactivate functions, including new parameters and logic changes, please ensure that unit tests are updated or added to cover these changes.

Proper testing helps prevent regressions and ensures the new code behaves as expected.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9372629 and daf0b91.

⛔ Files ignored due to path filters (1)
  • api/yorkie/v1/cluster.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (11)
  • admin/client.go (3 hunks)
  • api/docs/yorkie/v1/cluster.openapi.yaml (1 hunks)
  • api/yorkie/v1/cluster.proto (1 hunks)
  • api/yorkie/v1/v1connect/cluster.connect.go (1 hunks)
  • client/client.go (1 hunks)
  • cluster/client.go (1 hunks)
  • server/clients/clients.go (2 hunks)
  • server/packs/packs_test.go (3 hunks)
  • server/rpc/cluster_server.go (1 hunks)
  • server/rpc/server.go (1 hunks)
  • server/rpc/yorkie_server.go (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • admin/client.go
  • api/yorkie/v1/v1connect/cluster.connect.go
  • client/client.go
  • server/rpc/cluster_server.go
  • server/rpc/server.go
  • server/rpc/yorkie_server.go
🧰 Additional context used
🪛 buf
api/yorkie/v1/cluster.proto

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

🔇 Additional comments (17)
api/yorkie/v1/cluster.proto (2)

1-26: LGTM: File header and metadata are well-structured.

The file header includes the appropriate license information, and the metadata (syntax, package, and options) is correctly defined for both Go and Java implementations.

🧰 Tools
🪛 buf

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)


20-20: Verify the existence and location of the imported resources.proto file.

The static analysis tool reports that the file "yorkie/v1/resources.proto" does not exist. This import is crucial as it likely contains definitions for the Project and DocumentSummary types used in the ClusterServiceDetachDocumentRequest message.

Please run the following script to check for the existence of the resources.proto file and its contents:

If the file is not found or doesn't contain the expected message definitions, please update the import statement or create the missing file with the necessary definitions.

✅ Verification successful

Import statement is valid. The resources.proto file exists and contains the required message definitions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and content of the resources.proto file

# Test 1: Check if the file exists
if fd -t f "resources.proto" | grep -q .; then
    echo "resources.proto file found"
    # Test 2: Check the content of the file
    fd -t f "resources.proto" -x cat {} \; | grep -E "message (Project|DocumentSummary)"
else
    echo "resources.proto file not found"
    # Test 3: Search for alternative locations or names
    fd -t f -e proto | xargs grep -l -E "message (Project|DocumentSummary)"
fi

Length of output: 232

🧰 Tools
🪛 buf

20-20: import "yorkie/v1/resources.proto": file does not exist

(COMPILE)

cluster/client.go (7)

44-46: LGTM: Well-implemented option function

The WithLogger function is correctly implemented as an option function, following the functional options pattern. This is a good practice for configurable structs in Go.


49-51: LGTM: Well-implemented option function

The WithSecure function is correctly implemented as an option function, following the functional options pattern. The function name and parameter are clear and intuitive.


99-111: LGTM: Well-implemented Dial function

The Dial function correctly creates a new Client instance and dials to the admin service. Error handling is implemented properly, and the function follows a clear and logical flow.


114-126: LGTM: Well-implemented Dial method

The Dial method correctly handles the RPC address, prepending the appropriate scheme based on the isSecure flag. The client initialization is done properly with the RPC address.


129-131: LGTM: Proper resource cleanup

The Close method correctly closes idle connections, which is a good practice for cleaning up resources when the client is no longer needed.


163-167: LGTM: Well-implemented generic helper function

The withShardKey function is a well-implemented generic helper that correctly adds the shard key to the request header. It's flexible enough to handle multiple keys and works with different request types.


1-167: LGTM: Well-structured and organized package

The cluster package is well-organized with a clear separation of concerns. It follows Go best practices for package structure and naming conventions. The use of the functional options pattern for client configuration is a good practice, making the client flexible and easy to use.

The code is generally well-written, maintainable, and makes good use of Go idioms and patterns.

server/packs/packs_test.go (3)

280-283: LGTM. Consistent change applied.

The update to use testBackend instead of testBackend.DB in the clients.FindActiveClientInfo call is consistent with the previous change. This demonstrates a uniform application of the modification throughout the test file.


306-309: LGTM. Verify all instances are updated.

The consistent update to use testBackend instead of testBackend.DB in the clients.FindActiveClientInfo call is approved. To ensure completeness, it's advisable to verify that all instances in the file have been updated.

Run the following command to check for any remaining instances of FindActiveClientInfo that might still be using testBackend.DB:

#!/bin/bash
# Description: Check for any remaining instances of FindActiveClientInfo using testBackend.DB

# Test: Search for FindActiveClientInfo calls still using testBackend.DB
rg --type go 'clients\.FindActiveClientInfo\(.*testBackend\.DB' server/packs/packs_test.go

234-237: LGTM. Verify FindActiveClientInfo method signature.

The change from testBackend.DB to testBackend in the clients.FindActiveClientInfo call is consistent with the expected updates. This likely reflects a change in the method signature in the clients package.

To ensure consistency across the codebase, please run the following command to verify the FindActiveClientInfo method signature:

api/docs/yorkie/v1/cluster.openapi.yaml (3)

1-11: LGTM: Well-structured OpenAPI metadata and server information.

The OpenAPI version, API information, and server URLs are correctly defined and provide clear information about the API and its environments.


300-304: LGTM: Well-defined API key authentication scheme.

The security scheme for API key authentication is correctly defined and follows best practices by using the Authorization header.


305-309: LGTM: Clear and concise tag definition for ClusterService.

The tag for ClusterService is well-defined and includes a helpful description of the service's purpose.

server/clients/clients.go (2)

41-45: Updated Activate function signature improves consistency

The Activate function now accepts be *backend.Backend and project *types.Project, aligning it with the Deactivate function. This enhances consistency and maintainability across the API.


98-101: Ensure consistent parameter usage in FindActiveClientInfo

The FindActiveClientInfo function now accepts be *backend.Backend, aligning with other functions. Ensure that all calls to this function are updated accordingly throughout the codebase.

Run the following script to find all usages of FindActiveClientInfo and verify they pass the correct parameters:

✅ Verification successful

All usages of FindActiveClientInfo have been consistently updated with the be *backend.Backend parameter.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all usages of FindActiveClientInfo have been updated.

# Search for function calls to FindActiveClientInfo
rg --type go 'FindActiveClientInfo\(' -A 2

Length of output: 2756

cluster/client.go Show resolved Hide resolved
api/docs/yorkie/v1/cluster.openapi.yaml Show resolved Hide resolved
Comment on lines +68 to 91
for docID, clientDocInfo := range info.Documents {
if clientDocInfo.Status != database.DocumentAttached {
continue
}

// TODO(hackerwins): Solve N+1
docInfo, err := be.DB.FindDocInfoByRefKey(ctx, types.DocRefKey{
ProjectID: project.ID,
DocID: docID,
})
if err != nil {
return nil, err
}

actorID, err := info.ID.ToActorID()
if err != nil {
return nil, err
}

if err := cli.DetachDocument(ctx, project, actorID, docID, project.PublicKey, docInfo.Key); err != nil {
return nil, err
}
}

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider handling partial failures during document detachment

If an error occurs while detaching a document, the function returns immediately, and the client remains active. This means that a failure in detaching one document prevents the deactivation of the client.

Consider modifying the error handling to ensure the client is deactivated even if some document detachment operations fail. You can collect the errors and proceed with deactivation:

var detachmentErrors []error
for docID, clientDocInfo := range info.Documents {
    if clientDocInfo.Status != database.DocumentAttached {
        continue
    }

    docInfo, err := be.DB.FindDocInfoByRefKey(ctx, types.DocRefKey{
        ProjectID: project.ID,
        DocID:     docID,
    })
    if err != nil {
        detachmentErrors = append(detachmentErrors, err)
        continue
    }

    actorID, err := info.ID.ToActorID()
    if err != nil {
        detachmentErrors = append(detachmentErrors, err)
        continue
    }

    if err := cli.DetachDocument(ctx, project, actorID, docID, project.PublicKey, docInfo.Key); err != nil {
        detachmentErrors = append(detachmentErrors, err)
        continue
    }
}

deactivatedClient, err := be.DB.DeactivateClient(ctx, refKey)
if err != nil {
    return nil, err
}

if len(detachmentErrors) > 0 {
    // Handle or log the errors as needed
    // For example, you could wrap them into a single error
    return deactivatedClient, fmt.Errorf("client deactivated with errors in detaching documents: %v", detachmentErrors)
}

return deactivatedClient, nil

This approach ensures the client is deactivated regardless of individual detachment failures, and errors are properly logged or handled.

Comment on lines +73 to +74
// TODO(hackerwins): Solve N+1
docInfo, err := be.DB.FindDocInfoByRefKey(ctx, types.DocRefKey{
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Address the TODO: Solve N+1 query problem

The current implementation fetches docInfo individually within the loop using FindDocInfoByRefKey, which can lead to performance issues due to multiple database calls.

Consider fetching all required DocInfo records in a single batch operation before the loop. Implementing a method like FindDocInfosByRefKeys would reduce the number of database queries:

docRefKeys := make([]types.DocRefKey, 0, len(info.Documents))
for docID, clientDocInfo := range info.Documents {
    if clientDocInfo.Status != database.DocumentAttached {
        continue
    }
    docRefKeys = append(docRefKeys, types.DocRefKey{
        ProjectID: project.ID,
        DocID:     docID,
    })
}

docInfos, err := be.DB.FindDocInfosByRefKeys(ctx, docRefKeys)
if err != nil {
    return nil, err
}

for _, docInfo := range docInfos {
    // Proceed with detachment using docInfo
}

This change would optimize database access and improve performance.

@hackerwins hackerwins merged commit 85aa05e into main Oct 18, 2024
5 checks passed
@hackerwins hackerwins deleted the hk-deactivate-client branch October 18, 2024 04:26
hackerwins added a commit that referenced this pull request Oct 18, 2024
This commit implements the detachment of documents attached to clients
upon client deactivation. Previously, the status of the document was
only changed to 'detach' within DB.clients.ClientDocInfo.Status,
leading to issues where the deactivated client's presence remained
active and presence change events were not communicated to other
clients.

With this change, on client deactivation, the document's packs.PushPull
method is called directly to execute the complete detachment process.

Moreover, since the Yorkie cluster sharding mechanism assigns specific
documents to specific servers, the server managing client deactivation
may not always be the one handling the document. Therefore, in such
cases, a request will be made to the server currently responsible for
the document to detach it properly. To facilitate this communication
across the cluster, a new ClusterService has been added.

Follow-up tasks that need to be addressed after this PR include:

- Implementing authentication for cluster communication and preventing
  external exposure.
- Eliminating redundant database resource requests between
  clients.Deactivate and server.DetachDocument.
- Improving the p.Clear ChangePack creation logic.
- Introducing a connection pool for clusterClient.

---------

Co-authored-by: raararaara <raararaara@gmail.com>
@krapie krapie added the enhancement 🌟 New feature or request label Oct 19, 2024
@coderabbitai coderabbitai bot mentioned this pull request Oct 22, 2024
2 tasks
hackerwins pushed a commit that referenced this pull request Nov 21, 2024
)

This change introduces a migration script to handle documents that remain
attached to deactivated clients from before PRs #907 and #1036. Instead of
direct detachment, the script temporarily reactivates clients to leverage the
existing housekeeping process.

The approach:
- Identifies documents still attached to deactivated clients
- Updates client states from deactivated to activated
- Lets housekeeping process handle document detachment naturally
@coderabbitai coderabbitai bot mentioned this pull request Dec 29, 2024
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement 🌟 New feature or request
Projects
Status: Backlog
Development

Successfully merging this pull request may close these issues.

Handle Presence Cleanup in Housekeeping Process
3 participants