Skip to content

Improve performance and error handling in web components#506

Merged
askpt merged 17 commits intomainfrom
askpt/fix-issues
Mar 12, 2026
Merged

Improve performance and error handling in web components#506
askpt merged 17 commits intomainfrom
askpt/fix-issues

Conversation

@askpt
Copy link
Copy Markdown
Owner

@askpt askpt commented Mar 12, 2026

Enhance database query efficiency by applying Take() at the SQL layer and caching prompt files to reduce disk I/O. Remove unnecessary debug logs and implement error handling in the FeatureFlagsModal to provide clearer feedback to users when API calls fail. Add unit tests for the prompt loader functionality to ensure reliability.

closes #505
closes #504
closes #503
closes #502
closes #499
closes #498
closes #497
closes #496
closes #495

github-actions bot and others added 14 commits March 11, 2026 13:27
- WinnersService: fetch winners-count flag first, then pass the limit
  directly to GetAllDatabaseWinnersAsync so EF Core applies Take() at
  the SQL layer instead of loading all rows then discarding most of them
- WinnersService: add .AsNoTracking() on the read-only DB query to
  avoid unnecessary change-tracking overhead
- prompt_loader: add @lru_cache(maxsize=10) to load_prompt so each
  .prompt.yml file is read from disk and parsed only once per process
  lifetime instead of on every chat request

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- CarCard: remove debug console.log in toggleOwnership handler
- Home: remove debug console.log on winners load success and ownership update
- FeatureFlagsModal: add fetchError state so users see an error message
  instead of misleading 'No flags available' when the flags API call fails

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- CarCard: remove debug console.log in toggleOwnership handler
- Home: remove debug console.log on winners load success and ownership update
- FeatureFlagsModal: add fetchError state so users see an error message
  instead of misleading 'No flags available' when the flags API call fails

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- WinnersService: fetch winners-count flag first, then pass the limit
  directly to GetAllDatabaseWinnersAsync so EF Core applies Take() at
  the SQL layer instead of loading all rows then discarding most of them
- WinnersService: add .AsNoTracking() on the read-only DB query to
  avoid unnecessary change-tracking overhead
- prompt_loader: add @lru_cache(maxsize=10) to load_prompt so each
  .prompt.yml file is read from disk and parsed only once per process
  lifetime instead of on every chat request

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add test_prompt_loader.py: 12 unit tests covering render_messages,
  get_model_parameters, and load_prompt across happy-path and edge cases.
  Tests use only stdlib + pytest (no test doubles needed for pure functions).
- Add requirements-test.txt: isolates pytest from the production
  requirements.txt so the test dependency does not enter the container image.
  Run tests locally with:
    pip install -r requirements-test.txt
    pytest src/Garage.ChatService/
- Fix fetch() helper in main_test.go: the resp.Body.Close() check used
  the idiom 'if err != resp.Body.Close()' which compared the ReadAll error
  against the Close error. This silently dropped the Close error value when
  the read succeeded (err==nil). Replaced with the correct
  'if err := resp.Body.Close(); err != nil' pattern.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two imports were deferred inside function bodies, against PEP 8 and Python
style guidelines:

- 'import time' was placed inside chat() on every request, causing a
  (minor) redundant sys.modules lookup on each call; moved to module level.
- 'import grpc' was placed inside setup_telemetry() inside a branch that is
  only reached when TLS is required; grpc is an explicit production dependency
  (requirements.txt) so there is no reason to defer it. Moving it to module
  level makes the dependency visible at a glance and avoids the confusing
  'import inside a function' pattern.

No behaviour change; py_compile check still passes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The setup-python action uses cache: 'pip' but without
cache-dependency-path, it searches the whole repo for dependency
files. Since requirements.txt lives in src/Garage.ChatService/,
specifying the explicit path ensures the cache key is correctly
derived from the actual dependency file — consistent with how
the Go and Node.js jobs already configure their caches.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cking-lru-cache-1f6995db1c2d51e7' into askpt/fix-issues
…p-console-logs-error-state-a11f4ed64e7e51b0' into askpt/fix-issues
…p-console-logs-error-state-a11f4ed64e7e51b0-eb818041601a0760' into askpt/fix-issues
…cking-lru-cache-1f6995db1c2d51e7-cec4b5efd1592c5e' into askpt/fix-issues
…nd-fix-go-test-fetch-29d90cdbf5c43db0' into askpt/fix-issues
…t-cleanup-754b353e4bca722a' into askpt/fix-issues
Copilot AI review requested due to automatic review settings March 12, 2026 09:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves runtime efficiency and user feedback across the sample app by pushing winner limits down to the database query layer, caching chatbot prompt parsing, cleaning up frontend debug logging, and introducing clearer error handling for feature-flag fetch failures. It also adds initial Python unit tests for prompt loading/rendering and small CI/pipeline hygiene updates.

Changes:

  • Optimize winners retrieval by applying Take() in EF Core SQL queries and using AsNoTracking().
  • Cache .prompt.yml prompt loading in the ChatService and move deferred imports to module scope.
  • Improve web UX by removing debug logs and showing a fetch error state in FeatureFlagsModal; add Python unit tests for prompt_loader.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Garage.ApiService/Services/WinnersService.cs Pushes winner limiting into DB query and limits JSON results earlier.
src/Garage.ChatService/prompt_loader.py Adds lru_cache to avoid repeated disk I/O and YAML parsing for prompts.
src/Garage.ChatService/main.py Moves time/grpc imports to module level for clarity and minor perf.
src/Garage.ChatService/test_prompt_loader.py Adds pytest unit tests for prompt loading/rendering/model params.
src/Garage.ChatService/requirements-test.txt Introduces isolated test dependency requirements for pytest.
src/Garage.FeatureFlags/main_test.go Fixes response body close error handling in test helper.
src/Garage.Web/src/components/Home.tsx Removes debug console.log statements.
src/Garage.Web/src/components/CarCard.tsx Removes debug console.log statement.
src/Garage.Web/src/components/FeatureFlagsModal.tsx Adds an error UI state when feature-flag fetch fails.
.github/workflows/ci.yml Improves pip cache keying by pinning cache dependency path.
global.json Changes .NET SDK roll-forward behavior (now latestMajor).
Comments suppressed due to low confidence (2)

src/Garage.ChatService/prompt_loader.py:28

  • load_prompt is now cached, but it returns a mutable dict that callers can mutate. With lru_cache, any accidental mutation will affect all future callers (shared cached object) and can cause hard-to-debug cross-request behavior. Consider returning an immutable structure or a defensive copy (e.g., deep copy) to prevent cache poisoning via mutation.
@lru_cache(maxsize=10)
def load_prompt(prompt_name: str, prompts_dir: str = "prompts") -> dict[str, Any]:
    """Load a .prompt.yml file and return parsed content.

    Results are cached in-memory so repeated calls with the same arguments
    avoid redundant disk I/O and YAML parsing.
    
    Args:
        prompt_name: Name of the prompt (without extension)
        prompts_dir: Directory containing prompt files
        
    Returns:
        Parsed YAML content as a dictionary
        
    Raises:
        FileNotFoundError: If the prompt file doesn't exist
    """
    prompt_path = Path(prompts_dir) / f"{prompt_name}.prompt.yml"
    with open(prompt_path, 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)

.github/workflows/ci.yml:146

  • The new test_prompt_loader.py suite isn’t exercised in CI right now: build-python only installs requirements.txt and runs py_compile. If these tests are intended to prevent regressions, add a pytest step (installing requirements-test.txt) and consider including requirements-test.txt in cache-dependency-path so cache keys change when test deps change.
          cache-dependency-path: src/Garage.ChatService/requirements.txt
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: Check syntax
        run: python -m py_compile main.py prompt_loader.py

You can also share your feedback on Copilot code review. Take the survey.

askpt and others added 2 commits March 12, 2026 09:42
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 12, 2026 09:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

.github/workflows/ci.yml:146

  • This PR adds pytest-based unit tests under src/Garage.ChatService/, but the build-python job still only runs py_compile and never executes the tests. Consider adding a CI step to install the test requirements and run pytest so these tests actually protect against regressions (and, if you do, include requirements-test.txt in the pip cache key inputs).
          python-version: '3.14'
          allow-prereleases: true
          cache: 'pip'
          cache-dependency-path: src/Garage.ChatService/requirements.txt
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: Check syntax
        run: python -m py_compile main.py prompt_loader.py

You can also share your feedback on Copilot code review. Take the survey.

@askpt askpt merged commit ffc138e into main Mar 12, 2026
12 checks passed
@askpt askpt deleted the askpt/fix-issues branch March 12, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment