8000 Feature/api rate control by jcoetsie · Pull Request #6 · tjorim/pyrail · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Feature/api rate control #6

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

Merged
merged 11 commits into from
Jan 1, 2025
Merged

Conversation

jcoetsie
Copy link
Contributor
@jcoetsie jcoetsie commented Dec 30, 2024

Adding api rate limiting & caching as specified in https://docs.irail.be

Summary by CodeRabbit

  • New Features

    • Added development container configuration for Python development
    • Enhanced documentation in README with comprehensive library overview
  • Documentation

    • Updated README with installation, usage, features, configuration, and contribution guidelines
  • Refactor

    • Improved rate limiting and logging in iRail class
    • Restructured test suite with class-based approach
  • Chores

    • Removed GitLab CI/CD pipeline configuration

Copy link
Contributor
coderabbitai bot commented Dec 30, 2024
📝 Walkthrough

Walkthrough

This pull request introduces comprehensive improvements to the pyRail library, focusing on development environment configuration, documentation enhancement, and API client functionality. The changes include adding a development container configuration, removing the GitLab CI file, significantly expanding the README documentation, refactoring the iRail API client with advanced rate limiting and logging features, and updating the test suite to support the new implementation.

Changes

File Change Summary
.devcontainer/devcontainer.json New dev container config for Python 3.9, with VS Code extensions and dependency installation
.gitlab-ci.yml Removed entire CI/CD pipeline configuration
README.md Comprehensive documentation update with overview, installation, usage, features, configuration, logging, contribution, and license sections
pyrail/irail.py Enhanced iRail class with rate limiting, logging, token management, ETag caching, and improved error handling
tests/__init__.py Added import for irail module
tests/test_irail.py Introduced class-based testing with TestiRailAPI and mocked request testing

Sequence Diagram

sequenceDiagram
    participant Client
    participant iRail
    participant API
    Client->>iRail: Create instance
    Client->>iRail: do_request()
    iRail->>iRail: Check token availability
    iRail->>API: Send request
    API-->>iRail: Return response
    iRail->>iRail: Cache ETag
    iRail-->>Client: Return response data
Loading

Poem

🚂 A Railway of Code, Swift and Bright 🌟
Where tokens dance and requests take flight
Mocked tests sing, documentation gleams
Our pyRail library fulfills dev dreams
Hopping forward with pythonic might! 🐰


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd2f330 and 658ac8e.

📒 Files selected for processing (1)
  • .gitlab-ci.yml (0 hunks)
💤 Files with no reviewable changes (1)
  • .gitlab-ci.yml

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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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: 1

🧹 Nitpick comments (12)
pyrail/irail.py (6)

1-3: Consider deferring logging configuration to application code.
Calling logging.basicConfig in a library file can override or conflict with logging settings in other parts of the application. It might be better to configure logging in the main entry point or a dedicated configuration file.


57-72: Refill tokens logic: consider negative time.sleep scenarios.
In _refill_tokens and related code, consecutive calls to time.sleep(1 - (time.time() - self.last_request_time)) may yield a negative value if the time gap is large, resulting in an immediate return instead of a wait. To handle edge cases gracefully, use max(0, 1 - (time.time() - self.last_request_time)).

- time.sleep(1 - (time.time() - self.last_request_time))
+ wait_time = 1 - (time.time() - self.last_request_time)
+ time.sleep(max(0, wait_time))

74-88: Potential indefinite retry scenario.
When tokens are depleted, the logic repeatedly sleeps and refills. In a high-load environment, repeated 429 responses could cause prolonged loops. Consider bounding the total wait time or number of iterations to avoid indefinite blocking.


94-100: Add ETag usage to logs for clarity.
You're already logging ETag additions; consider informing the user when ETag is set or used, for more transparent caching diagnostics. This helps debug scenarios where stale or missing ETags cause unexpected responses.


103-122: Enhance rate-limited retry logic.
The current approach retries once after waiting for Retry-After. If the server continues returning 429, it may loop repeatedly. Implement a maximum retry count or exponential backoff to avoid prolonged retries.


124-131: Improve exception handling.
When a requests.exceptions.RequestException occurs, you try a network call to https://1.1.1.1/. This is a neat connectivity check, but can introduce external dependencies at runtime. Consider gracefully handling unreachable cases or using a more robust approach (e.g., DNS or local circuit check) if reliability is paramount.

Do you want me to propose an updated error-handling workflow that avoids external calls for checking connectivity?

tests/test_irail.py (1)

7-23: Extensive test approach with mocks.
Using unittest.mock to simulate HTTP responses is a dependable approach. Verify additional scenarios (e.g., 429 or 304 codes) in separate tests to ensure full rate-limiting coverage.

.gitlab-ci.yml (2)

4-4: Add a stage for linting or static analysis.
You might consider adding a separate stage for linting or static analysis to catch issues early before running tests.


26-27: No new line at end of file.
yaml files often require a newline at the end of file. Consider adding it to satisfy linting tools like yamllint.

 ... 
  rules:
    - if: $CI_COMMIT_BRANCH == "main"  # Deploy only when merging into the main branch
+ 
🧰 Tools
🪛 yamllint (1.35.1)

[error] 27-27: no new line character at the end of file

(new-line-at-end-of-file)

README.md (3)

5-8: Mention rate limiting in top-level descriptions.
You have an excellent sentence about caching and rate limiting. Consider giving it more prominence by referencing best practices (e.g., “Uses a token bucket approach for rate limiting”).


17-31: Usage example matches new rate-limiting features.
The snippet effectively demonstrates how to initialize and call an endpoint. Including a short mention of possible 429 responses or caching usage could guide users even better.


51-58: Clarify dynamic logging configuration.
Your code calls logging.basicConfig inside the library, which can conflict with instructions to set logging levels at runtime. Indicating that the user might only need to call set_logging_level if the global config is not changed could prevent confusion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9486a6 and cd2f330.

📒 Files selected for processing (7)
  • .devcontainer/devcontainer.json (1 hunks)
  • .gitlab-ci.yml (1 hunks)
  • README.md (1 hunks)
  • pyrail/irail.py (3 hunks)
  • requirements.txt (1 hunks)
  • tests/__init__.py (1 hunks)
  • tests/test_irail.py (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • requirements.txt
  • .devcontainer/devcontainer.json
🧰 Additional context used
🪛 yamllint (1.35.1)
.gitlab-ci.yml

[error] 27-27: no new line character at the end of file

(new-line-at-end-of-file)

🪛 Ruff (0.8.2)
tests/__init__.py

1-1: pyrail.irail.irail imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

🔇 Additional comments (10)
pyrail/irail.py (1)

25-33: Tokens and burst tokens logic: verify partial token increments.
The current approach allows fractional tokens via elapsed * 3. This can lead to partial tokens if elapsed is not an integer, which might not align with your intended rate-limiting policy. Ensure partial token usage is acceptable, or consider rounding logic if integer tokens are desired.

tests/test_irail.py (2)

1-3: Test coverage looks good.
Importing iRail directly ensures you’re targeting the same logic the end user would exercise. This is standard and recommended practice.


25-26: Automatic test discovery.
The if __name__ == '__main__': unittest.main() pattern is standard for direct test execution. Integration with CI is straightforward. Tests appear well structured.

.gitlab-ci.yml (2)

8-8: Consolidate dependency installation.
Installing from requirements.txt ensures all dependencies are pinned and consistent. Confirm that requests, unittest.mock, and any additional libraries are present in the file.


14-20: Test stage rules look good.
Running tests on every merge request fosters reliable code. Good job enabling test runs only when CI_MERGE_REQUEST_ID is set.

README.md (5)

3-3: Concise introduction.
The overview is clear and precisely describes the library’s purpose. Great job providing immediate context for new users.


9-15: Installation instructions are straightforward.
Providing a pip command is enough for typical usage. Nicely done.


33-50: Feature highlights are thorough.
Great job enumerating endpoints, caching, ETag, and rate limiting. This ensures new users see exactly what the library supports.


59-65: Appreciation for contributors.
A dedicated contributors list is a nice, welcoming touch.


66-70: Clear license notice.
MIT license is widely recognized. The mention in README fosters transparency for open-source usage.

@@ -0,0 +1 @@
from pyrail.irail import irail
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Unused import.
According to static analysis, from pyrail.irail import irail is unused. Remove or alias it to avoid confusion.

-from pyrail.irail import irail
🧰 Tools
🪛 Ruff (0.8.2)

1-1: pyrail.irail.irail imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

@tjorim
Copy link
Owner
tjorim commented Dec 31, 2024

Hi @jcoetsie, I'll reply to your email after the holidays. Thanks for taking the effort to help with this library. As you might see in the commit history this was more of a weekend project to learn about python libraries. It was never intended to be used for something like a HA integration. We should probably just continue development here on github instead of gitlab. Some things are already updated to modern standards and tools like poetry. GitHub action will need to be added as well (e.g. for publishing). I changed the license from MIT to Apache 2.0, is this alright for you?

@tjorim tjorim merged commit 29f5674 into tjorim:master Jan 1, 2025
1 check passed
This was referenced Jan 2, 2025
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
0