Skip to content

Codex/add lru cache for get settings helper#42

Merged
shayancoin merged 5 commits intomainfrom
codex/add-lru_cache-for-get_settings-helper
Oct 16, 2025
Merged

Codex/add lru cache for get settings helper#42
shayancoin merged 5 commits intomainfrom
codex/add-lru_cache-for-get_settings-helper

Conversation

@shayancoin
Copy link
Owner

@shayancoin shayancoin commented Oct 16, 2025

PR Type

[Feature | Fix | Documentation | Other() ]

Short Description

...

Tests Added

...

Summary by CodeRabbit

  • Documentation

    • Enhanced API documentation with clearer metadata descriptions and UI documentation endpoint details.
  • Refactor

    • Standardized error response format (ok=false with structured error details) for more consistent API responses across endpoints.

shayancoin and others added 4 commits October 14, 2025 19:11
Docstrings generation was requested by @shayancoin.

* #23 (comment)

The following files were modified:

* `backend/api/config.py`
* `backend/api/routes_sync.py`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 16, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Docstrings expanded in backend/api/config.py for FastAPI settings metadata. A new helper _error_envelope was added in backend/api/routes_sync.py to standardize error responses. No changes to public signatures or existing control flows.

Changes

Cohort / File(s) Summary
Config docstring updates
backend/api/config.py
Expanded docstrings for get_fastapi_settings(), detailing metadata and UI docs endpoints; no functional or signature changes; get_settings() remains cached.
Error response helper
backend/api/routes_sync.py
Introduced _error_envelope helper to produce standardized error dicts with ok=False and error payload (code, message, details); no changes to exported signatures.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant C as Client
    participant R as Router/Handler
    participant E as _error_envelope (new)
    participant S as Standardized Error Response

    C->>R: Request triggers error path
    R->>E: Build error envelope(code, message, details)
    Note right of E: New helper constructs { ok: false, error: {...} }
    E-->>R: Dict payload
    R-->>C: S: JSON error response
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

codex

Poem

I thump my paws at tidy lore,
New envelopes for errs we store—
Docstrings groomed, so clear and bright,
Settings whisper through the night.
With ok=false, the truth we send,
A bunny bow on each bad end. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title includes an unnecessary branch prefix and slash and is not phrased as a concise summary, even though it mentions the lru_cache change for the settings helper; it should be cleaned up to clearly state the main change without noise. Please rename the pull request to a concise statement of the change, such as “Add lru_cache to get_settings helper,” removing the “Codex/” prefix and slash.
Description Check ⚠️ Warning The pull request description contains only the template headings with placeholders and no actual information about the change, missing a filled-out PR type, summary of the change, and details on tests. Please fill in each section of the template with the chosen PR type, a short description of what was changed and why, and a list of added or updated tests before requesting review.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 989947e and bad4384.

📒 Files selected for processing (2)
  • backend/api/config.py (1 hunks)
  • backend/api/routes_sync.py (1 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

paform/backend/api/db.py

Lines 30 to 33 in 989947e

def get_engine_url() -> str:
"""Resolve the database URL from env or settings with sane defaults."""
settings = Settings()
url = os.getenv("DATABASE_URL", settings.database_url)

P0 Badge Import swap leaves Settings undefined in DB helper

The module now imports get_settings, but get_engine_url still instantiates Settings() when resolving the database URL. Because Settings is no longer imported, importing api.db raises a NameError as soon as ENGINE_URL = get_engine_url() executes, preventing the app (and Alembic) from starting. Replace the call with get_settings() or re-import Settings so the function can run.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/api/main.py (1)

37-43: Bypass of cached singleton defeats optimization purpose.

Line 40 creates a new Settings() instance instead of using the cached singleton via get_settings(), which:

  • Triggers redundant environment variable parsing
  • Bypasses the caching optimization introduced in this PR
  • Could lead to inconsistent configuration if environment changes between calls

Apply this diff to use the cached singleton:

-from api.config import Settings as _Settings
+from api.config import get_settings
 
 # Ensure tables exist in SQLite (dev/test); migrations still handle Postgres
-if _Settings().database_url.startswith("sqlite"):
+if get_settings().database_url.startswith("sqlite"):
     @app.on_event("startup")
     async def _ensure_sqlite_tables() -> None:
         Base.metadata.create_all(bind=engine)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between edd9646 and 989947e.

📒 Files selected for processing (4)
  • backend/api/config.py (2 hunks)
  • backend/api/db.py (1 hunks)
  • backend/api/main.py (2 hunks)
  • backend/api/routes_sync.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
backend/api/db.py (2)
backend/api/config.py (1)
  • get_settings (50-58)
backend/api/security.py (1)
  • get_settings (19-21)
backend/api/routes_sync.py (3)
backend/api/config.py (1)
  • get_settings (50-58)
backend/api/security.py (1)
  • get_settings (19-21)
backend/services/hygraph_service.py (1)
  • HygraphService (11-80)
backend/api/main.py (2)
backend/api/config.py (1)
  • get_settings (50-58)
backend/api/security.py (1)
  • get_settings (19-21)
🔇 Additional comments (3)
backend/api/config.py (1)

49-58: LGTM! Clean singleton implementation.

The @lru_cache() decorator correctly ensures a single Settings instance is reused across calls, preventing redundant environment variable parsing and improving performance.

backend/api/routes_sync.py (2)

41-49: Good singleton accessor pattern.

The get_hygraph_service() function provides clean access to the module-level singleton, improving testability and encapsulation.


50-62: Well-documented error helper.

The _error_envelope() function provides consistent error formatting with clear parameter documentation.

from sqlalchemy.orm import DeclarativeBase, sessionmaker

from api.config import Settings
from api.config import get_settings
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Incomplete refactoring will cause runtime NameError.

The import was changed to get_settings, but line 32 still attempts to instantiate Settings() directly, which will raise a NameError since Settings is no longer imported.

Apply this diff to use the imported function:

 def get_engine_url() -> str:
     """Resolve the database URL from env or settings with sane defaults."""
-    settings = Settings()
+    settings = get_settings()
     url = os.getenv("DATABASE_URL", settings.database_url)
     if url.startswith("sqlite"):
         return url
     return _normalize_postgres_url(url)
📝 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.

Suggested change
from api.config import get_settings
def get_engine_url() -> str:
"""Resolve the database URL from env or settings with sane defaults."""
settings = get_settings()
url = os.getenv("DATABASE_URL", settings.database_url)
if url.startswith("sqlite"):
return url
return _normalize_postgres_url(url)
🤖 Prompt for AI Agents
In backend/api/db.py around line 10 and line 32, the refactor changed the import
to get_settings but the code still calls Settings(), which will raise NameError;
replace the direct instantiation with a call to the imported function (e.g.,
settings = get_settings()) so the module uses the provided factory function
instead of the removed Settings symbol.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify no other direct Settings instantiations remain.

The relevant code snippets show that backend/api/security.py also has a get_settings() function that creates a new Settings() instance without caching, which creates inconsistency with the cached version in config.py.

Run the following script to identify all direct Settings() instantiations and duplicate get_settings implementations:


🏁 Script executed:

#!/bin/bash
# Description: Find all Settings instantiations and get_settings implementations

echo "=== Direct Settings() instantiations ==="
rg -nP '\bSettings\s*\(\s*\)' --type=py

echo -e "\n=== get_settings function definitions ==="
ast-grep --pattern 'def get_settings($$$) -> $$$:
  $$$'

echo -e "\n=== Imports of Settings class ==="
rg -nP '^from .* import.*\bSettings\b' --type=py

Length of output: 1136


Consolidate Settings instantiation and implement caching

  • Remove direct Settings() calls in db.py (line 32) and security.py (line 21); use config.get_settings().
  • Delete the duplicated get_settings() in security.py and import config.get_settings.
  • Add caching to config.get_settings() (e.g., @functools.lru_cache) so it returns a single shared Settings instance.
🤖 Prompt for AI Agents
In backend/api/db.py around line 10 and referencing usage at line 32, replace
the direct Settings() instantiation with a call to api.config.get_settings(),
and similarly update backend/api/security.py usage at line 21 to import and call
api.config.get_settings() instead of creating Settings() directly; remove the
duplicate get_settings() implementation in security.py and import the single
get_settings from config; finally, modify api.config.get_settings() to be cached
(e.g., decorate with functools.lru_cache or equivalent) so it returns a single
shared Settings instance across modules.

Comment on lines 36 to 38
# Using hygraph_token as webhook secret in MVP; adjust if separate secret provided
settings = get_settings()
_hygraph_service = HygraphService(webhook_secret=settings.hygraph_token)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify webhook secret configuration is intentional.

The comment indicates hygraph_token is being reused as the webhook secret. Ensure this is the intended configuration and that using the same credential for both API access and webhook validation aligns with security requirements.

Consider querying your external documentation or configuration management to confirm:


🔍 Additional research query:

What is the intended configuration for Hygraph webhook secrets in the paform project? Should it use a separate secret from the API token?

💡 Result:

Short answer: Yes — use a separate webhook secret, not the API token.

Why: webhook secrets are meant only to verify origin/signature of incoming requests; API tokens grant access to the Hygraph API and should be scoped and rotated differently. Keeping them separate follows least privilege, limits blast radius if one is leaked, and makes rotation/permissions simpler.


Use a dedicated webhook secret instead of the API token
Replace the webhook_secret parameter to use a separate config value:

backend/api/routes_sync.py lines 36–38:

-_hygraph_service = HygraphService(webhook_secret=settings.hygraph_token)
+_hygraph_service = HygraphService(webhook_secret=settings.hygraph_webhook_secret)

Add hygraph_webhook_secret to your settings and environment.

🤖 Prompt for AI Agents
In backend/api/routes_sync.py around lines 36 to 38, the code currently uses
settings.hygraph_token as the webhook_secret; change this to use a dedicated
settings.hygraph_webhook_secret instead. Add a new configuration entry
hygraph_webhook_secret to the settings loader and environment, validate/raise if
missing, and pass settings.hygraph_webhook_secret to
HygraphService(webhook_secret=...) so the API token and webhook secret remain
separate.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 16, 2025

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #43

@shayancoin shayancoin merged commit 9e9e2fb into main Oct 16, 2025
1 of 7 checks passed
coderabbitai bot added a commit that referenced this pull request Oct 16, 2025
Docstrings generation was requested by @shayancoin.

* #42 (comment)

The following files were modified:

* `backend/api/routes_sync.py`
shayancoin pushed a commit that referenced this pull request Oct 16, 2025
Docstrings generation was requested by @shayancoin.

* #42 (comment)

The following files were modified:

* `backend/api/routes_sync.py`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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.

1 participant