Skip to content

🔥 feat: Add support for ReloadViews()#3876

Merged
ReneWerner87 merged 4 commits intomainfrom
add-reloadviews-method-and-tests
Nov 18, 2025
Merged

🔥 feat: Add support for ReloadViews()#3876
ReneWerner87 merged 4 commits intomainfrom
add-reloadviews-method-and-tests

Conversation

@gaby
Copy link
Member

@gaby gaby commented Nov 18, 2025

Summary

  • This pull request enhances the application's view management by introducing a ReloadViews method, which enables dynamic reloading of view templates without requiring a server restart. It also standardizes error handling for view engine configuration by defining and utilizing a new shared sentinel error, ErrNoViewEngineConfigured, ensuring more consistent and predictable error responses.

Fixes #3875

Copilot AI review requested due to automatic review settings November 18, 2025 01:48
@gaby gaby requested a review from a team as a code owner November 18, 2025 01:48
@github-actions github-actions bot added the v3 label Nov 18, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Added a new public method App.ReloadViews() that mutex-protected reloads the configured view engine, a new exported error ErrNoViewEngineConfigured, unit tests covering success/error/no-engine/interface-nil cases, and corresponding API documentation.

Changes

Cohort / File(s) Summary
Core Implementation
app.go
Added func (app *App) ReloadViews() error which acquires the app mutex, validates the configured view engine (non-nil and non-nil pointer), calls the engine's Load() method, and returns ErrNoViewEngineConfigured or a wrapped error on failure.
Error Constants
error.go
Added exported error ErrNoViewEngineConfigured = errors.New("fiber: no view engine configured").
Unit Tests
app_test.go
Added countingView test helper and tests: Test_App_ReloadViews_Success, Test_App_ReloadViews_Error, Test_App_ReloadViews_NoEngine, and interface-nil pointer case to verify success, error propagation, and missing-engine behavior.
Documentation
docs/api/app.md
Documented App.ReloadViews() error API with signature and example usage (HTTP route), including error handling examples.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant App
    participant Mutex
    participant Engine

    Client->>App: ReloadViews()
    App->>Mutex: Lock()
    Mutex-->>App: Locked

    alt Views configured (non-nil)
        App->>Engine: Load()
        alt Load succeeds
            Engine-->>App: nil
            App-->>Client: nil
        else Load fails
            Engine-->>App: error
            App-->>Client: wrapped error ("fiber: failed to reload views: ...")
        end
    else No view engine configured (nil or nil-pointer)
        App-->>Client: ErrNoViewEngineConfigured
    end

    App->>Mutex: Unlock()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Reason: small, focused feature adding a public API, a new error constant, tests, and docs. Review should validate concurrency (mutex usage), nil/interface checks, error wrapping, and test coverage.
  • Pay special attention to:
    • app.go — correctness of nil vs. nil-pointer checks for the Views interface and proper mutex usage.
    • Error wrapping and message consistency ("fiber: failed to reload views").
    • Tests in app_test.go verifying the interface-nil pointer case.

Suggested labels

✏️ Feature

Suggested reviewers

  • sixcolors
  • ReneWerner87
  • efectn

Poem

🐰 I hopped in, templates ready to mend,
A mutex embrace, then Load() to send.
Three tests nodded—success, error, and nil—
Views reloaded, the app hums still. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete. It lacks key template sections including Changes introduced checklist, Type of change selection, and detailed Checklist items. Fill out the complete description template including Changes introduced section, Type of change checkboxes, and comprehensive Checklist items to document all changes made.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for ReloadViews() method.
Linked Issues check ✅ Passed The PR fully addresses issue #3875 by implementing App.ReloadViews() method that safely exposes view reloading functionality without requiring server restart.
Out of Scope Changes check ✅ Passed All changes are in scope: ReloadViews() method implementation, new ErrNoViewEngineConfigured error constant, comprehensive tests, and documentation updates.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-reloadviews-method-and-tests

📜 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 0e401ed and 55c984c.

⛔ Files ignored due to path filters (1)
  • .markdownlint.yml is excluded by !**/*.yml
📒 Files selected for processing (2)
  • app.go (1 hunks)
  • app_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app.go
🧰 Additional context used
🧬 Code graph analysis (1)
app_test.go (3)
app.go (4)
  • New (523-636)
  • Config (115-426)
  • Error (62-65)
  • App (68-112)
ctx.go (1)
  • Views (92-95)
error.go (1)
  • ErrNoViewEngineConfigured (22-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: Compare
  • GitHub Check: unit (1.25.x, ubuntu-latest)
  • GitHub Check: unit (1.25.x, macos-latest)
  • GitHub Check: repeated
  • GitHub Check: lint
🔇 Additional comments (5)
app_test.go (5)

1989-1992: LGTM!

The countingView test helper is well-designed with focused fields that enable testing both success and error scenarios for view reloading.


1994-1999: LGTM!

The method implementations correctly support the test scenarios: Load() tracks invocation count and propagates errors, while Render() is a minimal no-op implementation sufficient for these tests.


2001-2023: LGTM!

Both test cases are well-structured:

  • Test_App_ReloadViews_Success verifies that repeated calls correctly increment the load counter
  • Test_App_ReloadViews_Error verifies proper error propagation using ErrorIs

2025-2031: LGTM!

Correctly verifies that ReloadViews() returns ErrNoViewEngineConfigured when no view engine is configured, using the appropriate ErrorIs assertion.


2033-2040: LGTM with minor note.

This test correctly validates the edge case of a nil pointer wrapped in the Views interface. The direct &App{} construction on line 2036 (rather than using New()) is intentional for testing this specific edge case, though it bypasses normal initialization. This approach is acceptable here since ReloadViews() should handle this scenario safely.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gaby, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the application's view management by introducing a ReloadViews method, which enables dynamic reloading of view templates without requiring a server restart. It also standardizes error handling for view engine configuration by defining and utilizing a new shared sentinel error, ErrNoViewEngineConfigured, ensuring more consistent and predictable error responses.

Highlights

  • New ReloadViews Method: A new ReloadViews method has been added to the App struct, allowing on-demand reloading of the configured view engine. This is particularly useful for development workflows to pick up template changes without server restarts.
  • Standardized Error Handling: A new reusable sentinel error, ErrNoViewEngineConfigured, has been introduced. The ReloadViews method now uses this shared error when no view engine is configured, improving consistency and testability.
  • Comprehensive Unit Tests: New unit tests have been added for the ReloadViews method, covering successful reloading, error propagation from the view engine, and the specific case where no view engine is configured.
  • Documentation Update: The ReloadViews method has been documented in docs/api/app.md, including its signature and an example of how to use it.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gaby gaby changed the title Use shared error for ReloadViews 🔥 feat: Add support for ReloadViews() Nov 18, 2025
@codecov
Copy link

codecov bot commented Nov 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.65%. Comparing base (aaad4cf) to head (55c984c).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3876   +/-   ##
=======================================
  Coverage   91.64%   91.65%           
=======================================
  Files         115      115           
  Lines        9848     9858   +10     
=======================================
+ Hits         9025     9035   +10     
  Misses        523      523           
  Partials      300      300           
Flag Coverage Δ
unittests 91.65% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
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 introduces a reusable sentinel error ErrNoViewEngineConfigured and a new ReloadViews() method that allows reloading the view engine on demand without restarting the server.

  • Adds a shared sentinel error for view engine configuration issues
  • Implements thread-safe view engine reloading functionality
  • Provides comprehensive test coverage for all scenarios

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
error.go Adds ErrNoViewEngineConfigured sentinel error following existing error definition patterns
app.go Implements thread-safe ReloadViews() method with proper mutex locking and error handling
app_test.go Adds three comprehensive test cases covering success, error, and no-engine scenarios
docs/api/app.md Documents the new ReloadViews() method with clear description and practical example

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new ReloadViews method to allow on-demand reloading of the view engine, which is a great addition for development workflows. It also adds a corresponding sentinel error ErrNoViewEngineConfigured, which is good practice. The implementation is clean, and it's well-documented and tested. I've found one potential issue regarding a nil pointer panic that could occur with a specific configuration, and I've provided a suggestion to make the new function more robust. Overall, this is a solid contribution.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 55c984c Previous: f15a193 Ratio
Benchmark_NewError 80.24 ns/op 24 B/op 1 allocs/op 38.96 ns/op 24 B/op 1 allocs/op 2.06
Benchmark_NewError - ns/op 80.24 ns/op 38.96 ns/op 2.06

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Member

@ReneWerner87 ReneWerner87 left a comment

Choose a reason for hiding this comment

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

Pls add something in the What´s new.md

@ReneWerner87 ReneWerner87 added v3 and removed v3 labels Nov 18, 2025
@ReneWerner87 ReneWerner87 added this to v3 Nov 18, 2025
@ReneWerner87 ReneWerner87 added this to the v3 milestone Nov 18, 2025
@ReneWerner87 ReneWerner87 merged commit 542f4eb into main Nov 18, 2025
13 of 14 checks passed
@ReneWerner87 ReneWerner87 deleted the add-reloadviews-method-and-tests branch November 18, 2025 13:19
@github-project-automation github-project-automation bot moved this to Done in v3 Nov 18, 2025
@mrusme
Copy link

mrusme commented Nov 20, 2025

I have just tested this PR by using fsnotify to detect a change in the views and then triggering app.ReloadViews() through it. The function does not return an error, so I'm assuming the views have been reloaded. However, upon calling a reoute that uses one specific view that I had edited, I can see that the route still returns the outdated version.

I'm using the following engine:

		engine = html.New(cwd, ".html")

The reload happens like this (simplified):

		srv.watcher, err = srv.getWatcher(cwd+"/views", func(f string) {
			err := srv.app.ReloadViews()
			if err != nil {
				Error("error", err)
			}
		})

app is available in a shared context (srv, pointer) and the getWatcher method looks like this:

func (srv *Web) getWatcher(path string, callback func(f string)) (*fsnotify.Watcher, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}

	go func() {
		for {
			select {
			case ev, ok := <-watcher.Events:
				if !ok {
					return
				}
				if ev.Has(fsnotify.Write) {
					callback(ev.Name)
				}
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				Error("error", err)
			}
		}
	}()

	if err = watcher.Add(path); err != nil {
		watcher.Close()
		return nil, err
	}

	return watcher, nil
}

Either it is an issue that the ReloadViews runs inside a Goroutine, at which point this feature then appears to be of relatively little use, or the implementation doesn't work/has some side-effects that weren't clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Reload views?

4 participants