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

[V3] Rework service.OnStartup to close application on error #3920

Open
wants to merge 2 commits into
base: v3-alpha
Choose a base branch
from

Conversation

atterpac
Copy link
Member

@atterpac atterpac commented Nov 27, 2024

Modifies the service.OnStartup implementation to shutdown the application and run service.OnShutdown for any services that were successfully started prior to the service that failed startup to allow for service cleanup.

# System
┌──────────────────────────────────────────────────────────────────────────────────────────┐
| Name         | Ubuntu                                                                    |
| Version      | 24.04                                                                     |
| ID           | ubuntu                                                                    |
| Branding     | 24.04.1 LTS (Noble Numbat)                                                |
| Platform     | linux                                                                     |
| Architecture | amd64                                                                     |
| CPU          | 12th Gen Intel(R) Core(TM) i5-1235U                                       |
| GPU 1        | Alder Lake-UP3 GT2 [Iris Xe Graphics] (Intel Corporation) - Driver: i915  |
| Memory       | 7GB                                                                       |
└──────────────────────────────────────────────────────────────────────────────────────────┘

# Build Environment
┌─────────────────────────────────────────────────────────┐
| Wails CLI    | v3.0.0-alpha.7                           |
| Go Version   | go1.22.4                                 |
| Revision     | 8d7f7630950a42bf81e73faf9acba6729472b81d |
| Modified     | true                                     |
| -buildmode   | exe                                      |
| -compiler    | gc                                       |
| CGO_CFLAGS   |                                          |
| CGO_CPPFLAGS |                                          |
| CGO_CXXFLAGS |                                          |
| CGO_ENABLED  | 1                                        |
| CGO_LDFLAGS  |                                          |
| GOAMD64      | v1                                       |
| GOARCH       | amd64                                    |
| GOOS         | linux                                    |
| vcs          | git                                      |
| vcs.modified | true                                     |
| vcs.revision | 8d7f7630950a42bf81e73faf9acba6729472b81d |
| vcs.time     | 2024-11-24T02:51:55Z                     |
└─────────────────────────────────────────────────────────┘

# Dependencies
┌──────────────────────────────────────┐
| gcc        | 12.10ubuntu1            |
| gtk3       | 3.24.41-4ubuntu1.2      |
| nfpm       | dev                     |
| npm        | 10.5.1                  |
| pkg-config | 1.8.1-2build1           |
| webkit2gtk | 2.46.3-0ubuntu0.24.04.1 |
└────── * - Optional Dependency ───────┘

Summary by CodeRabbit

  • New Features

    • Enhanced support for darwin universal builds.
    • Introduced new commands: wails3 update build-assets and wails3 generate runtime.
    • Added templates for SvelteKit and SvelteKit-TS for non-SSR development.
    • File association support and new window positioning options.
  • Bug Fixes

    • Resolved issues with AlwaysOnTop functionality on Mac.
    • Improved Linux systray click handling.
    • Fixed AMD64 AppImage compilation issues.
  • Improvements

    • Enhanced error handling during application startup, ensuring graceful shutdown on service failure.
    • Refactored systray click messaging for better user interaction.
    • Upgraded the go-webview2 library for improved performance.

Copy link
Contributor

coderabbitai bot commented Nov 27, 2024

Walkthrough

The changes in this pull request involve significant updates to the application's startup logic and error handling, specifically within the service.OnStartup method. Enhancements include improved logging, new features such as support for Darwin universal builds, and additional commands. The documentation has been updated to reflect these changes, including new templates for SvelteKit. Bug fixes and refactorings have been made to improve user interaction and functionality across platforms.

Changes

File Path Change Summary
mkdocs-website/docs/en/changelog.md Updated changelog to reflect modifications, additions, and bug fixes, including new features and enhancements.
v3/pkg/application/application.go Altered application startup logic for better error handling; added methods for path management and service shutdown.

Possibly related PRs

  • [v3] Added AppDataDirectory path #3823: This PR adds new methods related to path management in the application package, which aligns with the main PR's changes to the service.OnStartup method and overall application startup process.
  • Add darwin universal build and package #3902: The addition of support for Darwin universal builds in this PR is related to the main PR's updates that include new features and enhancements across various platforms, including the handling of application startup.
  • [V3-Linux] Systray OnClick on initial icon click #3907: This PR addresses improvements in the systray functionality, which is relevant to the main PR's focus on enhancing user interaction and error handling during the application startup process.

Suggested reviewers

  • leeanthony

🐰 In the meadow, changes bloom,
With features bright, dispelling gloom.
Services start, then gracefully cease,
A rabbit's hop brings sweet release.
New paths to tread, with joy we sing,
In code we trust, let the updates ring! 🌼


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.

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.

@atterpac atterpac changed the title [V3] Rework service.OnStartup to close applicatoin on error [V3] Rework service.OnStartup to close application on error Nov 27, 2024
@atterpac atterpac marked this pull request as ready for review November 27, 2024 21:06
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 (3)
mkdocs-website/docs/en/changelog.md (1)

35-35: Documentation improvement needed for critical behavior change.

While the changelog entry correctly describes the new behavior, this significant change to application lifecycle management would benefit from additional documentation:

  1. Consider adding examples of the shutdown sequence
  2. Document any timeout mechanisms during shutdown
  3. Clarify the order of service shutdown

Consider expanding the changelog entry to:

- service.OnStartup now shutdowns the application on error and runs service.OnShutdown for any prior services that started by @atterpac in [#3920](https://github.com/wailsapp/wails/pull/3920)
+ service.OnStartup now implements graceful shutdown on initialization errors:
+   - Automatically terminates the application when a service fails to start
+   - Ensures proper cleanup by calling OnShutdown() on all previously started services
+   - Services are shut down in reverse order of their startup
+   by @atterpac in [#3920](https://github.com/wailsapp/wails/pull/3920)
v3/pkg/application/application.go (2)

147-147: Clarify log message for better readability

The log message might be confusing due to missing punctuation. Adding a comma after "failed" improves clarity.

Proposed change:

- globalApplication.Logger.Error("OnStartup() failed shutting down application:", "service", name, "error", err.Error())
+ globalApplication.Logger.Error("OnStartup() failed, shutting down application:", "service", name, "error", err.Error())

149-149: Avoid variable shadowing in nested loops for improved code clarity

The inner loop variable service shadows the outer loop variable service, which can lead to confusion. Renaming the inner loop variable enhances readability.

Proposed change:

- for _, service := appOptions.Services[:i] {
+ for _, startedService := appOptions.Services[:i] {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d27e75c and a953982.

📒 Files selected for processing (2)
  • mkdocs-website/docs/en/changelog.md (1 hunks)
  • v3/pkg/application/application.go (1 hunks)
🔇 Additional comments (1)
mkdocs-website/docs/en/changelog.md (1)

Line range hint 1-24: LGTM! Well-structured changelog.

The changelog follows the Keep a Changelog format correctly and provides clear categorization of changes with proper attribution.

v3/pkg/application/application.go Outdated Show resolved Hide resolved
CHANGELOG.md

fix index out of bounds potential
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 (3)
mkdocs-website/docs/en/changelog.md (2)

35-35: Consider expanding the changelog entry with more details.

While the current entry correctly describes the change, consider adding more details about:

  • The specific error scenarios that trigger application shutdown
  • The order of operations during shutdown
  • Any potential migration steps for existing applications

Here's a suggested expansion:

- `service.OnStartup` now shutdowns the application on error and runs `service.OnShutdown`for any prior services that started by @atterpac in [#3920](https://github.com/wailsapp/wails/pull/3920)
+ `service.OnStartup` now handles errors more gracefully by:
+   - Shutting down the application when a service fails to start
+   - Running `service.OnShutdown` in reverse order for any previously started services
+   - Ensuring proper cleanup of resources before application exit
+   by @atterpac in [#3920](https://github.com/wailsapp/wails/pull/3920)

35-35: Fix typo in changelog entry.

There's a missing space between OnShutdown and for.

- `service.OnStartup` now shutdowns the application on error and runs `service.OnShutdown`for any prior services that started by @atterpac in [#3920](https://github.com/wailsapp/wails/pull/3920)
+ `service.OnStartup` now shutdowns the application on error and runs `service.OnShutdown` for any prior services that started by @atterpac in [#3920](https://github.com/wailsapp/wails/pull/3920)
v3/pkg/application/application.go (1)

147-147: Enhance error logging message

The error message could be more descriptive to help with debugging. Consider including additional context about the startup sequence.

-globalApplication.Logger.Error("OnStartup() failed shutting down application:", "service", name, "error", err.Error())
+globalApplication.Logger.Error("Application startup failed - initiating shutdown sequence", "failed_service", name, "error", err.Error(), "startup_sequence", i+1)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a953982 and dd0bb29.

📒 Files selected for processing (2)
  • mkdocs-website/docs/en/changelog.md (1 hunks)
  • v3/pkg/application/application.go (1 hunks)

Comment on lines +149 to +156
for _, service := range appOptions.Services[:i] {
if thisService, ok := service.instance.(ServiceShutdown); ok {
err := thisService.OnShutdown()
if err != nil {
globalApplication.Logger.Error("Error shutting down service: " + err.Error())
}
}
}
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

Improve shutdown sequence robustness

The shutdown sequence could be improved to handle errors more gracefully and ensure all services are attempted to be shutdown.

-for _, service := range appOptions.Services[:i] {
-  if thisService, ok := service.instance.(ServiceShutdown); ok {
-    err := thisService.OnShutdown()
-    if err != nil {
-      globalApplication.Logger.Error("Error shutting down service: " + err.Error())
-    }
-  }
-}
+shutdownErrors := []error{}
+for _, service := range appOptions.Services[:i] {
+  if thisService, ok := service.instance.(ServiceShutdown); ok {
+    if err := thisService.OnShutdown(); err != nil {
+      shutdownErrors = append(shutdownErrors, fmt.Errorf("failed to shutdown service %s: %w", service.options.Name, err))
+    }
+  }
+}
+if len(shutdownErrors) > 0 {
+  globalApplication.Logger.Error("Errors occurred during shutdown sequence", "errors", shutdownErrors)
+}
📝 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
for _, service := range appOptions.Services[:i] {
if thisService, ok := service.instance.(ServiceShutdown); ok {
err := thisService.OnShutdown()
if err != nil {
globalApplication.Logger.Error("Error shutting down service: " + err.Error())
}
}
}
shutdownErrors := []error{}
for _, service := range appOptions.Services[:i] {
if thisService, ok := service.instance.(ServiceShutdown); ok {
if err := thisService.OnShutdown(); err != nil {
shutdownErrors = append(shutdownErrors, fmt.Errorf("failed to shutdown service %s: %w", service.options.Name, err))
}
}
}
if len(shutdownErrors) > 0 {
globalApplication.Logger.Error("Errors occurred during shutdown sequence", "errors", shutdownErrors)
}

Comment on lines 157 to 158
// Shutdown the application
os.Exit(1)
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 27, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve application shutdown process

Using os.Exit(1) directly can be dangerous as it bypasses deferred functions and cleanup routines. Consider using the existing shutdown mechanisms.

-// Shutdown the application
-os.Exit(1)
+// Cleanup and shutdown the application
+if a.cleanup != nil {
+  a.cleanup()
+}
+a.cancel() // Cancel the context to signal shutdown
+runtime.Goexit() // This allows deferred functions to run

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Member

Choose a reason for hiding this comment

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

@atterpac I like this suggestion. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

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 (1)
v3/pkg/application/application.go (1)

147-147: Enhance error logging with structured fields

The error logging could be improved by using structured logging fields consistently.

-globalApplication.Logger.Error("OnStartup() failed shutting down application:", "service", name, "error", err.Error())
+globalApplication.Logger.Error("OnStartup() failed, shutting down application", 
+    "service", name,
+    "error", err,
+    "phase", "startup")
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between dd0bb29 and 6fc8b67.

📒 Files selected for processing (1)
  • v3/pkg/application/application.go (1 hunks)
🔇 Additional comments (3)
v3/pkg/application/application.go (3)

157-158: ⚠️ Potential issue

Consider using proper cleanup sequence instead of runtime.Goexit()

Using runtime.Goexit() directly can be dangerous as it immediately terminates the current goroutine without proper cleanup. Consider using the application's existing shutdown mechanisms.

-// Shutdown the application
-runtime.Goexit()
+// Cleanup and shutdown the application
+if a.cleanup != nil {
+  a.cleanup()
+}
+a.cancel() // Cancel the context to signal shutdown
+runtime.Goexit() // Keep as last resort if cleanup fails

Likely invalid or redundant comment.


149-156: 🛠️ Refactor suggestion

Improve shutdown sequence robustness

The shutdown sequence could be improved to handle errors more gracefully and ensure all services are attempted to be shutdown.

-for _, service := range appOptions.Services[:i] {
-  if thisService, ok := service.instance.(ServiceShutdown); ok {
-    err := thisService.OnShutdown()
-    if err != nil {
-      globalApplication.Logger.Error("Error shutting down service: " + err.Error())
-    }
-  }
-}
+shutdownErrors := []error{}
+for _, service := range appOptions.Services[:i] {
+  if thisService, ok := service.instance.(ServiceShutdown); ok {
+    if err := thisService.OnShutdown(); err != nil {
+      shutdownErrors = append(shutdownErrors, fmt.Errorf("failed to shutdown service %s: %w", 
+        service.options.Name, err))
+    }
+  }
+}
+if len(shutdownErrors) > 0 {
+  globalApplication.Logger.Error("errors occurred during shutdown sequence", 
+    "errors", shutdownErrors,
+    "phase", "cleanup")
+}

Likely invalid or redundant comment.


139-158: Verify error handling in dependent services

The changes affect the service startup sequence. We should verify that dependent services properly handle the case where the application shuts down during startup.

✅ Verification successful

Let me try a different approach to find service implementations.


Based on the analysis of the service implementations, I can now provide a final response:

Service shutdown handling is properly implemented

The review concern can be marked as resolved because:

  • All services properly implement error handling during shutdown
  • The shutdown sequence in application.go correctly handles failures by:
    • Iterating through started services in reverse order
    • Logging any shutdown errors but continuing with remaining services
    • Using runtime.Goexit() to ensure clean termination
  • Key services like sqlite, kvstore, and single_instance implement proper cleanup in OnShutdown()
  • Other services have explicit nil returns indicating no cleanup needed
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all service implementations to verify error handling
# Look for service implementations that might need updating

# Find all files implementing ServiceStartup
echo "Searching for ServiceStartup implementations..."
ast-grep --pattern 'type $service struct {
  $$$
}

func ($x *$service) OnStartup($ctx context.Context, $opts any) error {
  $$$
}'

# Find all files implementing ServiceShutdown
echo "Searching for ServiceShutdown implementations..."
ast-grep --pattern 'type $service struct {
  $$$
}

func ($x *$service) OnShutdown() error {
  $$$
}'

Length of output: 449


Script:

#!/bin/bash
# Search for interface implementations using ripgrep
echo "Searching for ServiceStartup interface implementations..."
rg "OnStartup\(.*context\.Context.*\)" -B 5 -A 10

echo -e "\nSearching for ServiceShutdown interface implementations..."
rg "OnShutdown\(\).*error" -B 5 -A 10

Length of output: 28262

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