Address PR review: graceful shutdown, Role/NewUser, drop SQLite.
This commit is contained in:
+52
-17
@@ -1,10 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
@@ -17,29 +22,25 @@ import (
|
||||
func main() {
|
||||
_ = godotenv.Load()
|
||||
listen := listenAddr()
|
||||
st, err := store.Connect(os.Getenv("DATABASE_URL"), env("DATA_PATH", "data.db"), plumber.SchemaSQL)
|
||||
|
||||
databaseURL := strings.TrimSpace(os.Getenv("DATABASE_URL"))
|
||||
if databaseURL == "" {
|
||||
log.Fatal("DATABASE_URL is required")
|
||||
}
|
||||
st, err := store.OpenPostgres(databaseURL, plumber.SchemaSQL)
|
||||
if err != nil {
|
||||
log.Fatalf("database: %v", err)
|
||||
}
|
||||
defer st.Close()
|
||||
if os.Getenv("DATABASE_URL") != "" {
|
||||
log.Printf("database: postgres")
|
||||
} else {
|
||||
log.Printf("database: sqlite")
|
||||
}
|
||||
uploader := blob.NewSpaces(blob.SpacesConfig{
|
||||
Key: os.Getenv("SPACES_KEY"),
|
||||
Secret: os.Getenv("SPACES_SECRET"),
|
||||
Region: os.Getenv("SPACES_REGION"),
|
||||
Bucket: os.Getenv("SPACES_BUCKET"),
|
||||
Endpoint: os.Getenv("SPACES_ENDPOINT"),
|
||||
CDNBase: os.Getenv("SPACES_CDN_BASE"),
|
||||
})
|
||||
log.Printf("database: postgres")
|
||||
|
||||
uploader := spacesUploader()
|
||||
if uploader.Enabled() {
|
||||
log.Printf("avatars: digitalocean spaces")
|
||||
} else {
|
||||
log.Printf("avatars: uploads disabled (set SPACES_* to enable)")
|
||||
}
|
||||
|
||||
srv, err := web.New(st, st.SessionStore(), plumber.TemplateFS, plumber.StaticFS, web.Config{
|
||||
AdminUsername: os.Getenv("ADMIN_USERNAME"),
|
||||
SecureCookie: os.Getenv("SECURE_COOKIE") == "1",
|
||||
@@ -48,12 +49,46 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatalf("server: %v", err)
|
||||
}
|
||||
log.Printf("listening on %s", listen)
|
||||
if err := http.ListenAndServe(listen, srv.Handler()); err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
httpSrv := &http.Server{Addr: listen, Handler: srv.Handler()}
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
log.Printf("listening on %s", listen)
|
||||
errCh <- httpSrv.ListenAndServe()
|
||||
}()
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
select {
|
||||
case err := <-errCh:
|
||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case sig := <-sigCh:
|
||||
log.Printf("shutdown signal: %v", sig)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if err := httpSrv.Shutdown(ctx); err != nil {
|
||||
log.Printf("shutdown: %v", err)
|
||||
}
|
||||
if err := <-errCh; err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func spacesUploader() blob.Uploader {
|
||||
return blob.NewSpaces(blob.SpacesConfig{
|
||||
Key: os.Getenv("SPACES_KEY"),
|
||||
Secret: os.Getenv("SPACES_SECRET"),
|
||||
Region: os.Getenv("SPACES_REGION"),
|
||||
Bucket: os.Getenv("SPACES_BUCKET"),
|
||||
Endpoint: os.Getenv("SPACES_ENDPOINT"),
|
||||
CDNBase: os.Getenv("SPACES_CDN_BASE"),
|
||||
})
|
||||
}
|
||||
|
||||
// listenAddr prefers PORT (App Platform / PaaS), then LISTEN, then :8080.
|
||||
func listenAddr() string {
|
||||
if p := strings.TrimSpace(os.Getenv("PORT")); p != "" {
|
||||
|
||||
Reference in New Issue
Block a user