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

Do every API call async #574

Merged
merged 46 commits into from
Nov 19, 2024
Merged

Do every API call async #574

merged 46 commits into from
Nov 19, 2024

Conversation

jeandemeusy
Copy link
Collaborator

@jeandemeusy jeandemeusy commented Oct 29, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced channel management with increased limits for opening and funding channels.
    • Improved API interaction with a new structure for handling requests and responses.
    • Introduced a method to clear the message queue, enhancing message handling.
  • Bug Fixes

    • Streamlined retrieval and handling of addresses, balances, and channels, improving overall data access.
  • Documentation

    • Updated test fixtures and structures to reflect new data models, enhancing clarity in tests.
  • Chores

    • Removed dependency on the HOPRd SDK, simplifying the project structure.
    • Enhanced logging in the run script for better error tracking.
    • Updated Helm configuration to reflect the new version.

Results

This PR improves message sending rate from ~10 messages/s/node to ~100 messages/s/node.

image

@jeandemeusy jeandemeusy linked an issue Oct 29, 2024 that may be closed by this pull request
Copy link
Contributor

coderabbitai bot commented Oct 29, 2024

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

The changes in this pull request involve updates to configuration files, core components, and test suites. Key modifications include adjustments to channel management parameters in core_prod_config.yaml and core_staging_config.yaml, enhancements to API interaction methods in hoprd_api.py, and the introduction of new data structures in api_types.py. Additionally, various test files were updated to reflect these structural changes. The overall focus is on refining the handling of channels, addresses, and balances, as well as improving logging and error management across the application.

Changes

File Path Change Summary
ct-app/.configs/core_prod_config.yaml Increased openChannels, fundChannels, and closeOldChannels parameters; updated count and timeout in storage section.
ct-app/.configs/core_staging_config.yaml Modified timing flags and storage parameters, including reductions in topology and retrieveChannels timings, and adjustments to count and timeout in storage.
ct-app/core/__main__.py Added import for MessageQueue and a call to MessageQueue.clear() before closing the database connection.
ct-app/core/components/api_types.py Introduced classes and a utility function for managing API data structures, including ApiObject, Channel, and Channels.
ct-app/core/components/hoprd_api.py Refactored HoprdAPI class methods to remove SDK dependencies, added Method enum for HTTP methods, and updated several public methods for API calls.
ct-app/core/components/messages.py Added clear method to MessageQueue class and updated parse method parameter type to str.
ct-app/core/components/utils.py Simplified condition in balanceInChannels method for checking channel status.
ct-app/core/core.py Enhanced error handling, improved variable naming, and restructured logic in topology and apply_economic_model methods.
ct-app/core/model/budget.py Minor formatting change with no functional impact.
ct-app/core/model/subgraph/providers.py Updated GraphQLProvider class to enhance query handling and error management, added new parameters for query initialization.
ct-app/core/node.py Modified methods for address and balance retrieval, and streamlined peer handling.
ct-app/requirements.txt Removed dependency for HOPRd SDK.
ct-app/test/components/test_utils.py Updated channel_topology fixture to use new Channel class structure.
ct-app/test/conftest.py Adjusted test fixture imports and updated data structures to reflect new API types.
ct-app/test/test_node.py Updated test functions to use Channels instead of NodeChannelsResponse.
helm/values-prod.yaml Updated tag from v3.4.6 to v3.5.0 in the Helm configuration.
ct-app/core/components/decorators.py Modified logging messages in the formalin decorator for clarity.
ct-app/tests_endurance/test_fund_channels.py Updated address and channel handling to reflect new API structure.
ct-app/tests_endurance/test_get_channels.py Changed recipient address retrieval to align with new API response structure.
ct-app/tests_endurance/test_send_messages.py Adjusted recipient address handling and logging to reflect changes in the API.
ct-app/run.sh Enhanced logging by redirecting standard error output to a log file.

Possibly related PRs

  • Reduced calls to /channel endpoint and cleanups #569: The changes in core_prod_config.yaml regarding the flags section, particularly the adjustments to channel management parameters, are related to the modifications in the same file in the main PR, which also involves increasing limits for channel operations.
  • Do every API call async #574: This PR also updates the core_prod_config.yaml file, increasing the same parameters (openChannels, fundChannels, and closeOldChannels) as in the main PR, indicating a direct relation in terms of configuration changes for channel management.

Suggested labels

status:in-testing

Suggested reviewers

  • Teebor-Choka

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
Contributor

@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 (1)
ct-app/tests_endurance/test_fund_channels.py (1)

48-51: Simplify the channel lookup logic

The nested list comprehension makes the code harder to read. Consider simplifying this for better maintainability.

-                channel = channels[
-                    [
-                        c.id for c in channels if c.source_peer_id == self.address.hopr
-                    ].index(id)
-                ]
+                channel = next(
+                    (c for c in channels if c.id == id and c.source_peer_id == self.address.hopr),
+                    None
+                )
+                if channel is None:
+                    raise ValueError(f"Channel {id} not found")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9eb51fa and 13b883e.

📒 Files selected for processing (3)
  • ct-app/tests_endurance/test_fund_channels.py (2 hunks)
  • ct-app/tests_endurance/test_get_channels.py (1 hunks)
  • ct-app/tests_endurance/test_send_messages.py (3 hunks)
🔇 Additional comments (6)
ct-app/tests_endurance/test_get_channels.py (1)

14-15: Verify the API method signature change across the codebase.

The changes reflect a breaking change in how addresses are handled:

  1. Removal of "hopr" parameter from get_address()
  2. Change in return type from direct value to an object with .hopr property

Let's verify the API implementation and its usage:

✅ Verification successful

API method signature change verified and consistent across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the API method signature change and its usage

# Check the API implementation
echo "Checking API implementation:"
ast-grep --pattern 'async def get_address($$$)' 

# Check all usages of get_address
echo "\nChecking all usages:"
rg -A 2 'get_address\(' 

Length of output: 1305

ct-app/tests_endurance/test_fund_channels.py (2)

24-26: LGTM! Channel filtering updated correctly

The channel filtering logic has been properly updated to use self.address.hopr for source peer comparison while maintaining the same clear and efficient list comprehension structure.


Line range hint 1-85: Well-structured endurance test implementation

The test follows good practices with:

  • Clear separation of setup, execution, and cleanup
  • Proper error handling and timeout mechanisms
  • Comprehensive metrics collection
ct-app/tests_endurance/test_send_messages.py (3)

42-42: LGTM! Logging changes are consistent with the new object structures

The updated logging statements correctly reflect the new address and channel object structures while maintaining good visibility into the test setup.

Also applies to: 44-44


Line range hint 1-124: Well-structured test with comprehensive metrics

The endurance test is well-designed with:

  • Clear setup, execution, and validation phases
  • Comprehensive metrics collection
  • Appropriate success criteria (90% success rate)
  • Good instrumentation to measure the performance improvements mentioned in the PR description

The test structure will effectively validate the async API changes and their performance impact.


18-18: Verify address object structure changes across the codebase

The changes in address handling (removal of "hopr" parameter and addition of .hopr property) suggest a structural change in the API. Let's verify the consistency of these changes.

Also applies to: 24-24

ct-app/tests_endurance/test_fund_channels.py Show resolved Hide resolved
ct-app/tests_endurance/test_send_messages.py Outdated Show resolved Hide resolved
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
ct-app/run.sh (1)

29-29: Consider implementing log rotation.

With the increased message processing rate (100 msgs/sec) and continuous logging, the log file could grow significantly. Consider these improvements:

  1. Add timestamp to log filename
  2. Implement log rotation
-python -m core --configfile ./.configs/core_${env}_config.yaml 2>&1 | tee logs_core.log
+LOG_FILE="logs_core_$(date +%Y%m%d_%H%M%S).log"
+python -m core --configfile ./.configs/core_${env}_config.yaml 2>&1 | tee "$LOG_FILE" | rotatelogs -n 5 "$LOG_FILE" 100M
ct-app/core/components/api_types.py (3)

6-24: Improve type hints and error handling in _convert function

The function could benefit from these improvements:

  1. Add return type hint
  2. Use contextlib.suppress for more idiomatic Python error handling
-def _convert(value: Any):
+from contextlib import suppress
+
+def _convert(value: Any) -> Any:
     if value is None:
         return None
 
-    try:
+    with suppress(ValueError):
         value = float(value)
-    except ValueError:
-        pass
 
-    try:
+    with suppress(ValueError):
         integer = int(value)
         if integer == value:
             value = integer
-    except ValueError:
-        pass
 
     return value
🧰 Tools
🪛 Ruff

10-13: Use contextlib.suppress(ValueError) instead of try-except-pass

Replace with contextlib.suppress(ValueError)

(SIM105)


26-41: Add type hints and remove redundant None default

The base class implementation looks good but could be improved with better typing:

+from typing import Dict, Any, ClassVar
 
 class ApiObject:
+    keys: ClassVar[Dict[str, str]] = {}
+    
-    def __init__(self, data: dict):
+    def __init__(self, data: Dict[str, Any]):
         for key, value in self.keys.items():
-            setattr(self, key, _convert(data.get(value, None)))
+            setattr(self, key, _convert(data.get(value)))
🧰 Tools
🪛 Ruff

29-29: Use data.get(value) instead of data.get(value, None)

Replace data.get(value, None) with data.get(value)

(SIM910)


82-83: Document the magic number in TicketPrice conversion

The division by 1e18 appears to be converting from Wei to Ether, but this should be documented.

 def post_init(self):
+    # Convert from Wei (10^18 units) to Ether
     self.value = float(self.value) / 1e18
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ae7876b and dc19d26.

📒 Files selected for processing (3)
  • ct-app/core/components/api_types.py (1 hunks)
  • ct-app/core/core.py (5 hunks)
  • ct-app/run.sh (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ct-app/core/core.py
🧰 Additional context used
🪛 Ruff
ct-app/core/components/api_types.py

10-13: Use contextlib.suppress(ValueError) instead of try-except-pass

Replace with contextlib.suppress(ValueError)

(SIM105)


29-29: Use data.get(value) instead of data.get(value, None)

Replace data.get(value, None) with data.get(value)

(SIM910)

🔇 Additional comments (2)
ct-app/run.sh (1)

29-29: LGTM! Enhanced logging will help monitor async operations.

The addition of logging to both console and file will be valuable for debugging the async API calls and tracking the performance improvements.

ct-app/core/components/api_types.py (1)

90-94: ⚠️ Potential issue

Implement missing channel filtering logic

The incoming and outgoing lists are initialized but never populated. They should be filtered based on source and destination addresses.

Additionally, as noted in the previous review, this class should inherit from ApiObject for consistency. Here's the complete fix:

-class Channels:
+class Channels(ApiObject):
+    keys = {"all": "all"}
+
     def __init__(self, data: dict):
-        self.all = [Channel(channel) for channel in data.get("all", [])]
-        self.incoming = []
-        self.outgoing = []
+        super().__init__(data)
+
+    def post_init(self):
+        self.all = [Channel(channel) for channel in self.all or []]
+        self.incoming = [c for c in self.all if c.destination_address == self.our_address]
+        self.outgoing = [c for c in self.all if c.source_address == self.our_address]

However, this implementation requires access to self.our_address. Please clarify how the node's own address should be obtained.

#!/bin/bash
# Search for how our_address is used in other classes
ast-grep --pattern 'class $_ {
  $$$
  our_address
  $$$
}'

Copy link
Contributor

@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: 1

🧹 Outside diff range and nitpick comments (6)
ct-app/test/conftest.py (3)

47-47: Consider adding value validation for balance ranges.

While the transition to Balances type is good, consider if the random ranges (1-10) are representative of real-world scenarios. You might want to add constants for these ranges or make them configurable.


Line range hint 145-161: Consider optimizing the peers mock response construction.

The list comprehension creating ConnectedPeer objects could be simplified and made more efficient:

-            return_value=[
-                ConnectedPeer(peer) for peer in peers_raw[:idx] + peers_raw[idx + 1 :]
-            ],
+            return_value=[ConnectedPeer(peer) for peer in peers_raw if peers_raw.index(peer) != idx],

Line range hint 172-200: Consider improving channel mock data generation.

A few suggestions to enhance the channels fixture:

  1. Extract the balance calculation 1*1e18 to a named constant
  2. Consider adding variety to channel statuses beyond just "Open"
  3. Consider parameterizing the balance ranges
+MOCK_CHANNEL_BALANCE = 1e18
+CHANNEL_STATUSES = ["Open", "Pending", "Closing"]

 def channels(peers: set[Peer]) -> Channels:
     all_channels = list[Channel]()
     index = 0
+
+    def get_mock_balance() -> str:
+        return f"{MOCK_CHANNEL_BALANCE:.0f}"

     for src in peers:
         for dest in peers:
             if src.address == dest.address:
                 continue

             all_channels.append(
                 Channel(
                     {
-                        "balance": f"{1*1e18:.0f}",
+                        "balance": get_mock_balance(),
                         "id": f"channel_{index}",
                         "destinationAddress": dest.address.address,
                         "destinationPeerId": dest.address.id,
                         "sourceAddress": src.address.address,
                         "sourcePeerId": src.address.id,
-                        "status": "Open",
+                        "status": choice(CHANNEL_STATUSES),
                     }
                 )
             )
ct-app/core/components/hoprd_api.py (3)

33-35: Add input validation for URL and token.

Consider validating the input parameters to ensure they meet the expected format:

  1. URL should be a valid HTTP/HTTPS URL
  2. Token should not be empty
 def __init__(self, url: str, token: str):
+    if not url or not url.startswith(('http://', 'https://')):
+        raise ValueError("URL must be a valid HTTP/HTTPS URL")
+    if not token:
+        raise ValueError("Token cannot be empty")
     self.host = url
     self.headers = {"Authorization": f"Bearer {token}"}
     self.prefix = "/api/v3/"

57-61: Enhance error handling with more specific exception types.

The current error handling could be more specific to handle different types of network-related errors:

-        except OSError as e:
-            self.error(f"OSError calling {method.value} {endpoint}: {e}")
-
-        except Exception as e:
-            self.error(f"Exception calling {method.value} {endpoint}. error is: {e}")
+        except aiohttp.ClientConnectorError as e:
+            self.error(f"Connection error calling {method.value} {endpoint}: {e}")
+        except aiohttp.ServerDisconnectedError as e:
+            self.error(f"Server disconnected while calling {method.value} {endpoint}: {e}")
+        except aiohttp.ClientError as e:
+            self.error(f"Client error calling {method.value} {endpoint}: {e}")
+        except Exception as e:
+            self.error(f"Unexpected error calling {method.value} {endpoint}: {e}")

137-138: Use urllib.parse for query parameter construction.

Instead of manually constructing query parameters, use urllib.parse.urlencode for better safety and maintainability:

+from urllib.parse import urlencode
-        params_str = "&".join([f"{k}={v}" for k, v in params.items()])
+        params_str = urlencode(params)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between dc19d26 and dd99d35.

📒 Files selected for processing (7)
  • ct-app/.configs/core_prod_config.yaml (2 hunks)
  • ct-app/.configs/core_staging_config.yaml (2 hunks)
  • ct-app/core/components/hoprd_api.py (5 hunks)
  • ct-app/core/core.py (5 hunks)
  • ct-app/core/node.py (9 hunks)
  • ct-app/test/conftest.py (9 hunks)
  • helm/values-prod.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • ct-app/.configs/core_prod_config.yaml
  • ct-app/.configs/core_staging_config.yaml
  • ct-app/core/core.py
  • ct-app/core/node.py
  • helm/values-prod.yaml
🧰 Additional context used
🪛 Ruff
ct-app/core/components/hoprd_api.py

45-45: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


49-54: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


66-66: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🔇 Additional comments (6)
ct-app/test/conftest.py (4)

7-14: LGTM: Import changes align with the new async API structure.

The new imports from core.components.api_types properly support the transition to async API calls with strongly-typed responses.


108-108: LGTM: Peer object creation updated correctly.

The peer object creation is properly updated to use the new camelCase keys.


231-240: LGTM: Node fixture properly updated for async API.

The fixture correctly uses the new types and properly mocks the API responses.


93-101: Verify API response format matches the new camelCase keys.

The keys have been updated to camelCase format. Let's verify this matches the actual API response structure.

✅ Verification successful

Let me gather more context about the API response format by checking the actual API handler code.


Let me check the actual API response handling code to see how the peer data is processed.


Let me check one final thing to see how the peer data is transformed between API and internal representation.


API response format matches the camelCase keys in test fixtures

The camelCase keys in the test fixtures (peerId, peerAddress, reportedVersion) are correct as they match the API response format defined in ConnectedPeer class in ct-app/core/components/api_types.py. This class explicitly maps the snake_case internal representation to camelCase API format:

keys = {"address": "peerAddress", "peer_id": "peerId", "version": "reportedVersion"}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for API response handling code to verify key format
rg -t py "peerId|peerAddress|reportedVersion" --no-filename

Length of output: 1812


Script:

#!/bin/bash
# Search for API response handling code and route definitions
rg -t py "class.*API|@route|@app.route" -A 5

# Also search for peer-related API endpoints specifically
rg -t py "'/peers|/peer" -A 5

Length of output: 1669


Script:

#!/bin/bash
# Look for peer response handling and data transformation code
ast-grep --pattern 'response.json()' -A 5

# Also check for any peer data structure definitions
rg -t py "class Peer" -A 10

Length of output: 1381


Script:

#!/bin/bash
# Search for code that maps between API response and Peer objects
rg -t py "keys = \{.*peerId" -B 5 -A 5

Length of output: 700

ct-app/core/components/hoprd_api.py (2)

2-15: LGTM! Well-organized imports with proper type definitions.

The imports are properly structured with clear separation between standard library, third-party, and local imports. The comprehensive set of type definitions from api_types indicates good type safety practices.


21-25: LGTM! Good use of enum for HTTP methods.

Using an enum for HTTP methods is a great practice as it provides type safety, prevents typos, and makes refactoring easier. The implementation is clean and follows Python best practices.

ct-app/core/components/hoprd_api.py Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (3)
ct-app/core/components/hoprd_api.py (3)

19-19: Document the MESSAGE_TAG constant

Add a docstring explaining the purpose and significance of this magic number (0x1245).


33-35: Consider making the API prefix configurable

The API prefix is hardcoded. Consider making it a constructor parameter with a default value for better flexibility and maintainability.

-    def __init__(self, url: str, token: str):
+    def __init__(self, url: str, token: str, prefix: str = "/api/v3/"):
         self.host = url
         self.headers = {"Authorization": f"Bearer {token}"}
-        self.prefix = "/api/v3/"
+        self.prefix = prefix

78-86: Update docstring return type and improve error handling

The docstring return type doesn't match the actual Optional[Balances] return type. Also, consider logging the error response.

     async def balances(self) -> Optional[Balances]:
         """
         Returns the balance of the node.
-        :return: balances: Balances | undefined
+        :return: Optional[Balances] - None if the request fails
         """
         is_ok, response = await self.__call_api(Method.GET, "account/balances")
+        if not is_ok:
+            self.error(f"Failed to fetch balances: {response}")
         return Balances(response) if is_ok else None
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between dd99d35 and 0e28dea.

📒 Files selected for processing (1)
  • ct-app/core/components/hoprd_api.py (5 hunks)
🧰 Additional context used
🪛 Ruff
ct-app/core/components/hoprd_api.py

45-45: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


49-54: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


66-66: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🔇 Additional comments (1)
ct-app/core/components/hoprd_api.py (1)

42-56: Fix mutable default argument and optimize context managers

The existing review comments about mutable default arguments and nested with statements are still valid.

🧰 Tools
🪛 Ruff

45-45: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


49-54: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)

ct-app/core/components/hoprd_api.py Show resolved Hide resolved
ct-app/core/components/hoprd_api.py Show resolved Hide resolved
ct-app/core/components/hoprd_api.py Show resolved Hide resolved
Copy link
Contributor

@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: 1

🧹 Outside diff range and nitpick comments (2)
ct-app/core/components/hoprd_api.py (2)

33-35: Consider making the API prefix configurable.

The API prefix is hardcoded to "/api/v3/". Consider making it configurable through the constructor to support different API versions or testing environments.

-    def __init__(self, url: str, token: str):
-        self.host = url
-        self.headers = {"Authorization": f"Bearer {token}"}
-        self.prefix = "/api/v3/"
+    def __init__(self, url: str, token: str, prefix: str = "/api/v3/"):
+        self.host = url
+        self.headers = {"Authorization": f"Bearer {token}"}
+        self.prefix = prefix

149-155: Update docstring to match current implementation.

The docstring parameters don't match the current method signature:

     """
         Returns a list of peers.
-        :param: param: list or str = "peerId"
-        :param: status: str = "connected"
         :param: quality: int = 0..1
         :return: peers: list
     """
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0e28dea and 98a044d.

📒 Files selected for processing (1)
  • ct-app/core/components/hoprd_api.py (5 hunks)
🧰 Additional context used
🪛 Ruff
ct-app/core/components/hoprd_api.py

45-45: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


49-54: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


66-66: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🔇 Additional comments (4)
ct-app/core/components/hoprd_api.py (4)

2-15: LGTM! Clean implementation of Method enum and imports.

The introduction of the Method enum and structured imports improves type safety and code organization.

Also applies to: 21-25


43-77: LGTM! Solid async implementation.

The async implementation is well-structured with proper error handling and timeout management. The use of asyncio.wait_for ensures that API calls don't hang indefinitely.

🧰 Tools
🪛 Ruff

45-45: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


49-54: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


66-66: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


205-210: 🛠️ Refactor suggestion

Improve error handling in messages_pop_all.

The method should validate the response structure before accessing 'messages':

         data = {} if tag is None else {"tag": tag}
         is_ok, response = await self.__call_api(
             Method.POST, "messages/pop-all", data=data
         )
-        return response.get("messages", []) if is_ok else []
+        if not is_ok:
+            return []
+        if not isinstance(response, dict):
+            self.error(f"Unexpected response type: {type(response)}")
+            return []
+        return response.get("messages", [])

Likely invalid or redundant comment.


57-62: 🛠️ Refactor suggestion

Enhance error handling with specific exception types.

The current error handling could be more specific to help with debugging and recovery:

         except OSError as e:
-            self.error(f"OSError calling {method.value} {endpoint}: {e}")
+            self.error(f"Network error calling {method.value} {endpoint}: {e}", exc_info=True)
+            return (False, None)
+        except aiohttp.ClientError as e:
+            self.error(f"HTTP client error calling {method.value} {endpoint}: {e}", exc_info=True)
+            return (False, None)
+        except aiohttp.ContentTypeError as e:
+            self.error(f"Invalid JSON response from {method.value} {endpoint}: {e}", exc_info=True)
+            return (False, None)
         except Exception as e:
-            self.error(f"Exception calling {method.value} {endpoint}. error is: {e}")
+            self.error(f"Unexpected error calling {method.value} {endpoint}: {e}", exc_info=True)
+            return (False, None)
-        return (False, None)

Likely invalid or redundant comment.

ct-app/core/components/hoprd_api.py Show resolved Hide resolved
@jeandemeusy jeandemeusy merged commit e6f3f66 into main Nov 19, 2024
2 of 3 checks passed
@jeandemeusy jeandemeusy deleted the jean/make-api-calls-really-async branch November 19, 2024 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tasks piling up in the message queue
3 participants