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

Gateway unsubscribe for multiple subscribed clients #1637

Merged
merged 7 commits into from
Nov 9, 2023

Conversation

zkokelj
Copy link
Contributor

@zkokelj zkokelj commented Nov 7, 2023

Why this change is needed

Since we (can) have multiple accounts/addresses registered per user and Obscuro Gateway subscribes for all of them. We return new subscriptionID. And in case users wants to unsubscribe we want to make sure the gateway also unsubscribes from all subscriptions to the node that are/were related to that specific subscriptionID.

What changes were made as part of this PR

Please provide a high level list of the changes made

PR checks pre-merging

Please indicate below by ticking the checkbox that you have read and performed the required
PR checks

  • PR checks reviewed and performed

@zkokelj zkokelj marked this pull request as ready for review November 7, 2023 14:28
Copy link

coderabbitai bot commented Nov 7, 2023

Warning

Rate Limit Exceeded

@zkokelj has exceeded the limit for the number of files or commits that can be reviewed per hour. Please wait 13 minutes and 21 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per repository.
Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
Please see our FAQ for further information.

Commits Files that changed from the base of the PR and between a9dd2a1 and 9f41086.

Walkthrough

The changes primarily focus on enhancing the subscription and unsubscription functionalities in the codebase. The modifications include the introduction of new constants, changes in function signatures, removal of unused functions, and addition of new test functions. The SubscriptionManager struct and its methods have undergone significant alterations, with changes in the data types stored and the addition of new methods to handle subscription termination and unsubscription.

Changes

File Change Summary
go/rpc/client.go Introduced a new constant Unsubscribe with the value "eth_unsubscribe".
go/rpc/encrypted_client.go Removed the setResultToSubID function and modified the Subscribe method signature.
integration/obscurogateway/obscurogateway_test.go Added two new test functions testUnsubscribe and testClosingConnectionWhileSubscribed. The subscribeToEvents function now returns an ethereum.Subscription object.
tools/walletextension/accountmanager/account_manager.go Added handling for subscription and unsubscription requests in the ProxyRequest function.
tools/walletextension/subscriptions/subscriptions.go Made significant changes to the SubscriptionManager struct and its methods. The subscriptionMappings map now stores slices of *gethrpc.ClientSubscription instead of strings. Added new methods to handle subscription termination and unsubscription.

Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai help to get help.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • 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/coderabbit-overrides.v2.json

Copy link

coderabbitai bot commented Nov 7, 2023

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

Commits Files that changed from the base of the PR and between e7ab386 and fca236a.
Files selected for processing (5)
  • go/rpc/client.go (1 hunks)
  • go/rpc/encrypted_client.go (2 hunks)
  • integration/obscurogateway/obscurogateway_test.go (5 hunks)
  • tools/walletextension/accountmanager/account_manager.go (2 hunks)
  • tools/walletextension/subscriptions/subscriptions.go (4 hunks)

Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai help to get help.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • 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/coderabbit-overrides.v2.json

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.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between e7ab386 and fca236a.
Files selected for processing (5)
  • go/rpc/client.go (1 hunks)
  • go/rpc/encrypted_client.go (2 hunks)
  • integration/obscurogateway/obscurogateway_test.go (5 hunks)
  • tools/walletextension/accountmanager/account_manager.go (2 hunks)
  • tools/walletextension/subscriptions/subscriptions.go (4 hunks)
Additional comments: 11
go/rpc/client.go (1)
  • 34-40: The addition of the "Unsubscribe" constant is consistent with the introduction of an unsubscribe functionality. Ensure that this constant is used correctly in the codebase where the "eth_unsubscribe" method is needed.
go/rpc/encrypted_client.go (2)
  • 125-130: Ensure that the removal of setResultToSubID function and its invocation doesn't affect the functionality of the Subscribe method. Verify that the subscription ID is being handled correctly in the new implementation.

  • 205-210: Ensure that the removal of setResultToSubID function and its invocation doesn't affect the functionality of the executeSensitiveCall method. Verify that the subscription ID is being handled correctly in the new implementation.

tools/walletextension/accountmanager/account_manager.go (2)
  • 61-68: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [64-74]

The ProxyRequest function now handles subscribing to events. It uses the suggestSubscriptionClient function to determine the clients to subscribe to and then calls HandleNewSubscriptions on the subscriptionsManager. Error handling and logging are also included.

  • 78-88: The ProxyRequest function now also handles unsubscribing from events. It validates the parameters, ensuring that a subscription ID is provided, and then calls HandleUnsubscribe on the subscriptionsManager.
+	if rpcReq.Method == rpc.Unsubscribe {
+		if len(rpcReq.Params) != 1 {
+			return fmt.Errorf("one parameter (subscriptionID) expected, %d parameters received", len(rpcReq.Params))
+		}
+		subscriptionID, ok := rpcReq.Params[0].(string)
+		if !ok {
+			return fmt.Errorf("subscriptionID needs to be a string. Got: %d", rpcReq.Params[0])
+		}
+		m.subscriptionsManager.HandleUnsubscribe(subscriptionID, rpcResp)
+		return nil
+	}
tools/walletextension/subscriptions/subscriptions.go (4)
  • 22-31: The SubscriptionManager struct has been updated to handle *gethrpc.ClientSubscription instead of string IDs. This change is reflected in the subscriptionMappings map and the constructor function New().

  • 55-62: The HandleNewSubscriptions function now updates the subscription mapping with a *gethrpc.ClientSubscription instead of a string. This change is reflected in the call to UpdateSubscriptionMapping().

  • 114-139: The UpdateSubscriptionMapping function has been modified to handle *gethrpc.ClientSubscription instead of string IDs. It checks if the subscription already exists in the slice before adding it, which prevents duplicate subscriptions.

  • 159-174: A new HandleUnsubscribe function has been added to handle unsubscribing from multiple subscriptions associated with a user subscription ID. It locks the SubscriptionManager struct with a mutex to prevent data races, unsubscribes from all subscriptions associated with the user subscription ID, and then deletes the user subscription ID from the subscription mappings.

integration/obscurogateway/obscurogateway_test.go (2)
  • 93-97: The addition of the new test functions testUnsubscribe and testClosingConnectionWhileSubscribed to the test suite is a good practice to ensure the new functionality works as expected.

  • 599-604: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [588-617]

The subscribeToEvents function now returns an ethereum.Subscription object, which is used in the new test functions to unsubscribe. This is a necessary change to support the new unsubscribe functionality.

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between e7ab386 and fca236a.
Files selected for processing (5)
  • go/rpc/client.go (1 hunks)
  • go/rpc/encrypted_client.go (2 hunks)
  • integration/obscurogateway/obscurogateway_test.go (5 hunks)
  • tools/walletextension/accountmanager/account_manager.go (2 hunks)
  • tools/walletextension/subscriptions/subscriptions.go (4 hunks)
Files skipped from review due to trivial changes (1)
  • go/rpc/client.go
Additional comments: 13
go/rpc/encrypted_client.go (2)
  • 125-130: The function Subscribe now returns an error if the subscription type is not SubscriptionTypeLogs. This change might affect other parts of the codebase that use this function with different subscription types. Ensure that this change doesn't break any existing functionality.

  • 205-210: The executeSensitiveCall function now encrypts the arguments before making the RPC call. This is a good security practice as it prevents sensitive data from being exposed in transit. However, ensure that the server side is able to decrypt and correctly interpret these encrypted arguments.

tools/walletextension/accountmanager/account_manager.go (3)
  • 61-68: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [64-74]

The ProxyRequest function now handles subscription requests. It first identifies the appropriate clients for the subscription using suggestSubscriptionClient. Then, it calls HandleNewSubscriptions to handle the subscription for the identified clients. If an error occurs, it logs the error and returns it. This change is significant as it allows handling multiple accounts for a single user request.

  • 78-88: The ProxyRequest function now also handles unsubscription requests. It validates the parameters for the unsubscribe method and calls the HandleUnsubscribe function of the subscriptionsManager. This change is significant as it allows handling unsubscription requests.

  • 75-91: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [64-88]

Ensure that the ProxyRequest function is being called with the correct parameters throughout the codebase. Also, verify that the error handling for suggestSubscriptionClient and HandleNewSubscriptions is done correctly.

tools/walletextension/subscriptions/subscriptions.go (4)
  • 22-31: The SubscriptionManager struct has been updated to store slices of *gethrpc.ClientSubscription instead of strings in the subscriptionMappings map. This change should be verified across the codebase to ensure compatibility.

  • 55-62: The HandleNewSubscriptions function now takes an additional parameter &sm.mu and calls checkIfUserConnIsClosedAndUnsubscribe with an additional parameter. This change should be verified across the codebase to ensure compatibility.

  • 114-139: The UpdateSubscriptionMapping function now takes a *gethrpc.ClientSubscription instead of a string for the subscription. This change should be verified across the codebase to ensure compatibility.

  • 159-174: A new HandleUnsubscribe function has been added to handle unsubscribing from subscriptions. This function should be tested thoroughly to ensure it works as expected.

integration/obscurogateway/obscurogateway_test.go (4)
  • 93-97: The new test functions testUnsubscribe and testClosingConnectionWhileSubscribed have been added to the test suite. Ensure that these tests are passing and that they cover all the edge cases related to the new unsubscribe functionality.

  • 388-436: The testUnsubscribe function tests the unsubscribe functionality. It creates a user, registers accounts, deploys a contract, subscribes to an event, triggers an event, unsubscribes, and then triggers another event to verify that no new events are received after unsubscribing. The logic seems correct.

  • 438-494: The testClosingConnectionWhileSubscribed function tests the behavior of the system when the websocket connection is closed while subscribed to events. It creates a user, registers accounts, deploys a contract, subscribes to an event, closes the websocket connection, triggers an event, re-establishes the connection, triggers another event, and then unsubscribes. The logic seems correct.

  • 599-604: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [588-617]

The subscribeToEvents function now returns an ethereum.Subscription. Ensure that all calls to this function throughout the codebase have been updated to handle the new return type.

@ten-protocol ten-protocol deleted a comment from coderabbitai bot Nov 7, 2023
@ten-protocol ten-protocol deleted a comment from coderabbitai bot Nov 7, 2023
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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between fca236a and 0a2c4bb.
Files selected for processing (3)
  • go/rpc/encrypted_client.go (4 hunks)
  • integration/obscurogateway/obscurogateway_test.go (5 hunks)
  • tools/walletextension/subscriptions/subscriptions.go (4 hunks)
Additional comments: 14
go/rpc/encrypted_client.go (4)
  • 89-95: The Subscribe method has been updated to remove the result parameter. Ensure that all calls to this function throughout the codebase have been updated to match the new signature.

  • 125-130: The Subscribe method now returns a *rpc.ClientSubscription and an error. Ensure that all calls to this function throughout the codebase have been updated to handle the new return types.

  • 205-210: The executeSensitiveCall function has been updated. Ensure that all calls to this function throughout the codebase have been updated to match the new signature.

  • 334-339: The IsSensitiveMethod function has been updated. Ensure that all calls to this function throughout the codebase have been updated to match the new signature.

integration/obscurogateway/obscurogateway_test.go (4)
  • 93-97: The new test functions testUnsubscribe and testClosingConnectionWhileSubscribed have been added to the test suite. Ensure that these tests are passing and that they cover all the edge cases related to the unsubscribe functionality and closing the connection while subscribed.

  • 388-436: The testUnsubscribe function tests the unsubscribe functionality. It creates a user, registers accounts, deploys a contract, subscribes to events, triggers events, unsubscribes, and checks that no more events are received after unsubscribing. The logic seems correct.

  • 438-494: The testClosingConnectionWhileSubscribed function tests the behavior when the websocket connection is closed while subscribed. It creates a user, registers accounts, deploys a contract, subscribes to events, closes the connection, triggers events, checks that no events are received, re-establishes the connection, triggers events again, checks that no events are received (since closing the connection unsubscribes), and finally calls unsubscribe. The logic seems correct.

  • 599-604: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [588-617]

The subscribeToEvents function now returns an ethereum.Subscription object. This change is consistent with the new unsubscribe functionality. Ensure that all calls to this function throughout the codebase have been updated to handle the new return type.

tools/walletextension/subscriptions/subscriptions.go (6)
  • 21-32: The SubscriptionManager struct has been updated to store a map of *gethrpc.ClientSubscription slices instead of strings. This change allows for multiple subscriptions per userSubscriptionID, which is a significant change in the subscription handling logic.

  • 55-65: The HandleNewSubscriptions method now uses a new method checkIfUserConnIsClosedAndUnsubscribe to handle subscription termination. This change allows for more efficient handling of closed connections and subscription termination.

  • 103-132: The unsubscribeAndRemove method has been added to handle unsubscribing and removing subscriptions from the subscriptionMappings. This method is a key part of the new subscription handling logic and is used in both checkIfUserConnIsClosedAndUnsubscribe and HandleUnsubscribe.

  • 134-140: The checkIfUserConnIsClosedAndUnsubscribe method checks if the user connection is closed and if so, unsubscribes and removes the subscription. This method is used in HandleNewSubscriptions to handle subscription termination when the user connection is closed.

  • 142-167: The UpdateSubscriptionMapping method now takes a *gethrpc.ClientSubscription instead of a string. This change aligns with the new subscription handling logic where multiple subscriptions can be associated with a single userSubscriptionID.

  • 187-202: A new method HandleUnsubscribe has been added to handle unsubscribing and removing subscriptions. This method is a key part of the new subscription handling logic and allows for unsubscribing from all subscriptions associated with a specific userSubscriptionID.

Copy link
Contributor

@otherview otherview left a comment

Choose a reason for hiding this comment

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

Minor bits nothing blocking imo

tools/walletextension/accountmanager/account_manager.go Outdated Show resolved Hide resolved
tools/walletextension/subscriptions/subscriptions.go Outdated Show resolved Hide resolved
Comment on lines 107 to 112
subscription.Unsubscribe()

subscriptions, exists := sm.subscriptionMappings[userSubscriptionID]
if !exists {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this possible to happen ? that a subscription is cancelled but there isn't one in our mapping ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should not happen, added it here to be 100% sure not to crash. I added a log that will clearly tell us if & what happened.

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 0a2c4bb and d8320d5.
Files selected for processing (1)
  • tools/walletextension/accountmanager/account_manager.go (2 hunks)
Additional comments: 2
tools/walletextension/accountmanager/account_manager.go (2)
  • 61-68: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [64-74]

The ProxyRequest function now handles rpc.Subscribe requests. It uses the suggestSubscriptionClient function to determine the clients to subscribe to, and then calls HandleNewSubscriptions on the subscriptionsManager. Error handling and logging are also included.

  • 78-88: The ProxyRequest function now also handles rpc.Unsubscribe requests. It validates the parameters and then calls HandleUnsubscribe on the subscriptionsManager.
+	if rpcReq.Method == rpc.Unsubscribe {
+		if len(rpcReq.Params) != 1 {
+			return fmt.Errorf("one parameter (subscriptionID) expected, %d parameters received", len(rpcReq.Params))
+		}
+		subscriptionID, ok := rpcReq.Params[0].(string)
+		if !ok {
+			return fmt.Errorf("subscriptionID needs to be a string. Got: %v", rpcReq.Params[0])
+		}
+		m.subscriptionsManager.HandleUnsubscribe(subscriptionID, rpcResp)
+		return nil
+	}

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between d8320d5 and a9dd2a1.
Files selected for processing (1)
  • tools/walletextension/subscriptions/subscriptions.go (4 hunks)
Additional comments: 7
tools/walletextension/subscriptions/subscriptions.go (7)
  • 19-32: The SubscriptionManager struct has been updated to store a map of gethrpc.ClientSubscription pointers instead of strings. This change allows for more direct interaction with the subscriptions.

  • 55-63: The HandleNewSubscriptions function now includes a goroutine that checks if the user connection is closed and unsubscribes if it is. This is a good practice to prevent unnecessary resource usage.

  • 103-132: The unsubscribeAndRemove function is a new addition that unsubscribes a given subscription and removes it from the subscriptionMappings map. This function is used to clean up subscriptions when they are no longer needed.

  • 134-140: The checkIfUserConnIsClosedAndUnsubscribe function is another new addition that continuously checks if a user connection is closed and unsubscribes the associated subscription if it is. This function is used to ensure that subscriptions are cleaned up when a user connection is closed.

  • 142-167: The UpdateSubscriptionMapping function has been updated to handle the new gethrpc.ClientSubscription pointers. It now checks if a subscription already exists in the map before adding it, which is a good practice to prevent duplicate entries.

  • 187-201: The HandleUnsubscribe function is a new addition that handles unsubscribing from all subscriptions associated with a given user subscription ID. This function is used to clean up all subscriptions when a user wants to unsubscribe.

  • 107-112: In response to the previous comment, it is possible for a subscription to be cancelled but not exist in the mapping. This could occur if the subscription was already removed from the mapping by another process. The current code handles this case correctly by checking if the subscription exists in the mapping before trying to remove it.

@zkokelj zkokelj merged commit 9e3cf21 into main Nov 9, 2023
1 of 2 checks passed
@zkokelj zkokelj deleted the ziga/og_unsubscribe_with_multiple_clients branch November 9, 2023 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants