Skip to content

Commit

Permalink
added graceful shutdown of the server
Browse files Browse the repository at this point in the history
  • Loading branch information
saalikmubeen committed Jun 4, 2024
1 parent 663d786 commit 96f2a59
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 37 deletions.
10 changes: 8 additions & 2 deletions cmd/goravel/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ func showHelp() {
help - show the help commands
version - print application version
serve - starts the server
new <project-name> - creates a new goravel application
make migration <name> - creates two new migration files one up and one down in the migrations folder
migrate - runs all up migrations that have not been run previously
migrate up - same as migrate
migrate down - reverses the most recent migration
migrate down all - reverses all migrations
migrate to <number> - migrates to a specific migration number (number: positive for up, negative for down migrations)
migrate fix - Fix the migrations table if it's corrupted by forcing the version to the last migration (-1)
migrate reset - runs all down migrations in reverse order, and then all up migrations
make migration <name> - creates two new migration files one up and one down in the migrations folder
make auth - creates and runs migrations for authentication tables, and creates models and middleware
make session - creates a table in the database as a session store
make handler <name> - creates a stub handler in the handlers directory
make model <name> - creates a new model in the data directory
make session - creates a table in the database as a session store
`)
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/goravel/templates/new/go.mod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module ${APP_URL}
go 1.22.3

require (
github.com/saalikmubeen/goravel v1.4.2
github.com/saalikmubeen/goravel v1.5.0
github.com/CloudyKit/jet/v6 v6.2.0
github.com/go-chi/chi/v5 v5.0.12
github.com/upper/db/v4 v4.7.0
Expand Down
52 changes: 51 additions & 1 deletion cmd/goravel/templates/new/main.go.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package main

import (
"os"
"os/signal"
"sync"
"syscall"

"github.com/saalikmubeen/goravel"
"${APP_URL}/handlers"
"${APP_URL}/middleware"
Expand All @@ -12,11 +17,56 @@ type application struct {
Handlers *handlers.Handlers
Models *models.Models
Middleware *middleware.Middleware
wg *sync.WaitGroup
}




func main() {

app := initGoravel()
app.App.ListenAndServe()

go app.listenForShutDown()
err := app.App.ListenAndServe()
if err != nil {
app.App.ErrorLog.Println(err)
}

}

func (app *application) listenForShutDown() {
// Create a quit channel which carries os.Signal values. Use buffered
// We need to use a buffered channel here because signal.Notify() does not
// wait for a receiver to be available when sending a signal to the quit channel.
// If we had used a regular (non-buffered) channel here instead, a signal could be
// ‘missed’ if our quit channel is not ready to receive at the exact moment that the
// signal is sent. By using a buffered channel, we avoid this problem and ensure
// that we never miss a signal.
quit := make(chan os.Signal, 1)

// Use signal.Notify() to listen for incoming SIGINT and SIGTERM signals and relay
// them to the quit channel. Any other signal will not be caught by signal.Notify()
// and will retain their default behavior.
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

// Read the signal from the quit channel. This code will block until a signal is
// received.
s := <-quit

// Log a message to say we caught the signal. Notice that we also call the
// String() method on the signal to get the signal name and include it in the log
// entry properties.
app.App.InfoLog.Printf("caught signal: %s", s.String())

// ** put any clean up tasks here

// **

// Call Wait() to block until our WaitGroup counter is zero. This essentially blocks
// until the background goroutines have finished. Then we return nil on the shutdownError
// channel to indicate that the shutdown as compleeted without any issues.
// Uses sync.WaitGroup to wait for any background goroutines before terminating the application.
app.wg.Wait()

}
34 changes: 1 addition & 33 deletions goravel.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package goravel
import (
"fmt"
"log"
"net/http"
"os"
"strconv"
"strings"
Expand All @@ -12,7 +11,6 @@ import (
"github.com/CloudyKit/jet/v6"
"github.com/alexedwards/scs/v2"
"github.com/dgraph-io/badger/v3"
"github.com/fatih/color"
"github.com/go-chi/chi/v5"
"github.com/gomodule/redigo/redis"
"github.com/joho/godotenv"
Expand All @@ -25,7 +23,7 @@ import (

const (
// Version of Goravel
Version = "1.4.2"
Version = "1.5.0"
// http://patorjk.com/software/taag/#p=display&f=Ogre&t=Goravel
Banner = `
___ _
Expand Down Expand Up @@ -379,33 +377,3 @@ func (g *Goravel) New(rootPath string) error {
return nil

}

// ListenAndServe starts the web server
func (g *Goravel) ListenAndServe() {
port := os.Getenv("PORT")
srv := &http.Server{
Addr: ":" + port,
Handler: g.Routes,
ErrorLog: g.ErrorLog,
IdleTimeout: time.Second * 30,
ReadTimeout: time.Second * 30,
WriteTimeout: time.Second * 600,
}

if g.DB.Pool != nil {
defer g.DB.Pool.Close() // close the database connection when the server stops
}

if redisPool != nil {
defer redisPool.Close() // close the redis connection when the server stops
}

if badgerConn != nil {
defer badgerConn.Close()
}

color.Yellow(Banner, Version)
color.Green("Starting server on port %s", port)
err := srv.ListenAndServe()
g.ErrorLog.Fatal(err)
}
44 changes: 44 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package goravel

import (
"net/http"
"os"
"time"

"github.com/fatih/color"
)

// ListenAndServe starts the web server
func (g *Goravel) ListenAndServe() error {
port := os.Getenv("PORT")
srv := &http.Server{
Addr: ":" + port,
Handler: g.Routes,
ErrorLog: g.ErrorLog,
IdleTimeout: time.Second * 30,
ReadTimeout: time.Second * 30,
WriteTimeout: time.Second * 600,
}

if g.DB.Pool != nil {
defer g.DB.Pool.Close() // close the database connection when the server stops
}

if redisPool != nil {
defer redisPool.Close() // close the redis connection when the server stops
}

if badgerConn != nil {
defer badgerConn.Close()
}

color.Yellow(Banner, Version)
color.Green("Starting server on port %s", port)
err := srv.ListenAndServe()

if err != nil {
return err
} else {
return nil
}
}

0 comments on commit 96f2a59

Please # to comment.