Use shutdowner library, improve logging, update deps

This commit is contained in:
Jan-Lukas Else 2021-06-17 16:34:57 +02:00
parent 08b5dc1eaf
commit ad8bf087ca
10 changed files with 90 additions and 115 deletions

3
app.go
View File

@ -6,6 +6,7 @@ import (
"net/http"
"sync"
shutdowner "git.jlel.se/jlelse/go-shutdowner"
ts "git.jlel.se/jlelse/template-strings"
"github.com/go-chi/chi/v5"
"github.com/go-fed/httpsig"
@ -66,6 +67,8 @@ type goBlog struct {
templates map[string]*template.Template
// Sessions
loginSessions, captchaSessions *dbSessionStore
// Shutdown
shutdown shutdowner.Shutdowner
// Template strings
ts *ts.TemplateStrings
// Tor

View File

@ -2,6 +2,7 @@ package main
import (
"errors"
"log"
"net/url"
"strings"
@ -225,6 +226,7 @@ type configWebmention struct {
}
func (a *goBlog) initConfig() error {
log.Println("Initialize configuration...")
viper.SetConfigName("config")
viper.AddConfigPath("./config/")
err := viper.ReadInConfig()
@ -307,6 +309,7 @@ func (a *goBlog) initConfig() error {
br.Enabled = false
}
}
log.Println("Initialized configuration")
return nil
}

View File

@ -22,6 +22,7 @@ type database struct {
}
func (a *goBlog) initDatabase() (err error) {
log.Println("Initialize database...")
// Setup db
db, err := a.openDatabase(a.cfg.Db.File, true)
if err != nil {
@ -29,9 +30,12 @@ func (a *goBlog) initDatabase() (err error) {
}
// Create appDB
a.db = db
addShutdownFunc(func() {
_ = db.close()
log.Println("Closed database")
a.shutdown.Add(func() {
if err := db.close(); err != nil {
log.Printf("Failed to close database: %v", err)
} else {
log.Println("Closed database")
}
})
if a.cfg.Db.DumpFile != "" {
hourlyHooks = append(hourlyHooks, func() {
@ -39,6 +43,7 @@ func (a *goBlog) initDatabase() (err error) {
})
db.dump(a.cfg.Db.DumpFile)
}
log.Println("Initialized database")
return nil
}
@ -113,7 +118,7 @@ func (db *database) dump(file string) {
log.Println("Error while dump db:", err.Error())
return
}
if err = sqlite3dump.DumpDB(db.db, f); err != nil {
if err = sqlite3dump.DumpDB(db.db, f, sqlite3dump.WithTransaction(true)); err != nil {
log.Println("Error while dump db:", err.Error())
}
}

10
go.mod
View File

@ -4,6 +4,7 @@ go 1.16
require (
git.jlel.se/jlelse/go-geouri v0.0.0-20210525190615-a9c1d50f42d6
git.jlel.se/jlelse/go-shutdowner v0.0.0-20210617142609-b824b8996568
git.jlel.se/jlelse/goldmark-mark v0.0.0-20210522162520-9788c89266a4
git.jlel.se/jlelse/template-strings v0.0.0-20210523080439-57437f8d23ee
github.com/PuerkitoBio/goquery v1.7.0
@ -34,11 +35,11 @@ require (
github.com/lib/pq v1.9.0 // indirect
github.com/lopezator/migrator v0.3.0
github.com/mattn/go-sqlite3 v1.14.7
github.com/microcosm-cc/bluemonday v1.0.10
github.com/microcosm-cc/bluemonday v1.0.14
github.com/mitchellh/go-server-timing v1.0.1
github.com/paulmach/go.geojson v1.4.0
github.com/pquerna/otp v1.3.0
github.com/schollz/sqlite3dump v1.2.4
github.com/schollz/sqlite3dump v1.3.0
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/snabb/sitemap v1.0.0
github.com/spf13/cast v1.3.1
@ -48,14 +49,15 @@ require (
github.com/thoas/go-funk v0.8.0
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2
github.com/yuin/goldmark v1.3.7
github.com/yuin/goldmark v1.3.8
// master
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
go.uber.org/atomic v1.8.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 // indirect
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b

22
go.sum
View File

@ -40,6 +40,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.jlel.se/jlelse/go-geouri v0.0.0-20210525190615-a9c1d50f42d6 h1:d7k1NKd9fr+Eq7EtUrqUly+HDqDzpx9T9v8Gl2jJvpo=
git.jlel.se/jlelse/go-geouri v0.0.0-20210525190615-a9c1d50f42d6/go.mod h1:eKL81ZHiGWZ4cdv9MI0ADmPiG9p0C+ajkSldNTr2ftQ=
git.jlel.se/jlelse/go-shutdowner v0.0.0-20210617142609-b824b8996568 h1:lsGzeyyxEnbf3rYRnb1eIx7kCP2rNipDhfo75K9qzTw=
git.jlel.se/jlelse/go-shutdowner v0.0.0-20210617142609-b824b8996568/go.mod h1:ekOAwB3OuHq9a5aInTRZeJic5oPltZXgZXChUxWw6HA=
git.jlel.se/jlelse/goldmark-mark v0.0.0-20210522162520-9788c89266a4 h1:p3c/vCY6MUADNXWCYI/hsZ8ZEvN7LtvwHzK2B8Y6BSk=
git.jlel.se/jlelse/goldmark-mark v0.0.0-20210522162520-9788c89266a4/go.mod h1:ZFhxwbX+afhgbzh5rpkSJUp6vIduNPtIGDrsWpIcHTE=
git.jlel.se/jlelse/template-strings v0.0.0-20210523080439-57437f8d23ee h1:zun+B6UygGTYm+OBxK9eoPUHSd3M7AebIxXJyFyZzR4=
@ -287,14 +289,13 @@ github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9v
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk=
github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
github.com/microcosm-cc/bluemonday v1.0.10 h1:hsW4ch5StWWscflW8orGkX3TP2AVelTmwYO26qwGjqg=
github.com/microcosm-cc/bluemonday v1.0.10/go.mod h1:beubO5lmWoy1tU8niaMyXNriNgROO37H3U/tsrcZsy0=
github.com/microcosm-cc/bluemonday v1.0.14 h1:Djd+GeTanVeA23todvVC0AO5hsI+vAwQMLTy794Zr5I=
github.com/microcosm-cc/bluemonday v1.0.14/go.mod h1:beubO5lmWoy1tU8niaMyXNriNgROO37H3U/tsrcZsy0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY=
github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
@ -333,8 +334,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/schollz/sqlite3dump v1.2.4 h1:b3dgcKLsHZhF6OsB2EK+e/oA77vh4P/45TAh2R35OFI=
github.com/schollz/sqlite3dump v1.2.4/go.mod h1:SEajZA5udi52Taht5xQYlFfHwr7AIrqPrLDrAoFv17o=
github.com/schollz/sqlite3dump v1.3.0 h1:ll4MjfwoXbfZ0HpMa73x09uCj4h3R+G6YI+CmNssw5s=
github.com/schollz/sqlite3dump v1.3.0/go.mod h1:mzSTjZpJH4zAb1FN3iNlhWPbbdyeBpOaTW0hukyMHyI=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@ -386,8 +387,9 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.3.7 h1:NSaHgaeJFCtWXCBkBKXw0rhgMuJ0VoE9FB5mWldcrQ4=
github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.3.8 h1:Nw158Q8QN+CPgTmVRByhVwapp8Mm1e2blinhmx4wx5E=
github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38 h1:XZjLcLoTPNZuxppY3gwhRqo/T2XF6JMGFFdkAjX3w1w=
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
@ -419,8 +421,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -567,8 +570,9 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 h1:X/2sJAybVknnUnV7AD2HdT6rm2p5BP6eH2j+igduWgk=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -9,10 +9,10 @@ import (
)
func (a *goBlog) preStartHooks() {
for _, cmd := range a.cfg.Hooks.PreStart {
cfg := a.cfg.Hooks
for _, cmd := range cfg.PreStart {
func(cmd string) {
log.Println("Executing pre-start hook:", cmd)
a.cfg.Hooks.executeCommand(cmd)
executeHookCommand("pre-start", cfg.Shell, cmd)
}(cmd)
}
}
@ -75,53 +75,56 @@ func (cfg *configHooks) executeTemplateCommand(hookType string, tmpl string, dat
return
}
cmd := cmdBuf.String()
log.Println("Executing "+hookType+" hook:", cmd)
cfg.executeCommand(cmd)
executeHookCommand(hookType, cfg.Shell, cmd)
}
var hourlyHooks = []func(){}
func (a *goBlog) startHourlyHooks() {
cfg := a.cfg.Hooks
// Add configured hourly hooks
for _, cmd := range a.cfg.Hooks.Hourly {
for _, cmd := range cfg.Hourly {
c := cmd
f := func() {
log.Println("Executing hourly hook:", c)
a.cfg.Hooks.executeCommand(c)
executeHookCommand("hourly", cfg.Shell, c)
}
hourlyHooks = append(hourlyHooks, f)
}
// Calculate waiting time for first exec
n := time.Now()
f := time.Date(n.Year(), n.Month(), n.Day(), n.Hour(), 0, 0, 0, n.Location()).Add(time.Hour)
w := f.Sub(n)
// When there are hooks, start ticker
if len(hourlyHooks) > 0 {
go func() {
// Wait for next hour to begin
time.Sleep(w)
// Wait for next full hour
tr := time.AfterFunc(time.Until(time.Now().Truncate(time.Hour).Add(time.Hour)), func() {
// Execute once
for _, f := range hourlyHooks {
go f()
}
// Start ticker and execute regularly
ticker := time.NewTicker(1 * time.Hour)
a.shutdown.Add(func() {
ticker.Stop()
log.Println("Stopped hourly hooks")
})
for range ticker.C {
for _, f := range hourlyHooks {
go f()
}
}
}()
})
a.shutdown.Add(func() {
if tr.Stop() {
log.Println("Canceled hourly hooks")
}
})
}
}
func (cfg *configHooks) executeCommand(cmd string) {
out, err := exec.Command(cfg.Shell, "-c", cmd).CombinedOutput()
func executeHookCommand(hookType, shell, cmd string) {
log.Printf("Executing %v hook: %v", hookType, cmd)
out, err := exec.Command(shell, "-c", cmd).CombinedOutput()
if err != nil {
log.Println("Failed to execute command:", err.Error())
}
if len(out) > 0 {
log.Println("Output:")
log.Print(string(out))
log.Printf("Output:\n%v", string(out))
}
}

17
http.go
View File

@ -45,6 +45,7 @@ const (
)
func (a *goBlog) startServer() (err error) {
log.Println("Start server(s)...")
// Start
a.d = &dynamicHandler{}
// Set basic middlewares
@ -81,7 +82,7 @@ func (a *goBlog) startServer() (err error) {
ReadTimeout: 5 * time.Minute,
WriteTimeout: 5 * time.Minute,
}
addShutdownFunc(shutdownServer(s, "main server"))
a.shutdown.Add(shutdownServer(s, "main server"))
if a.cfg.Server.PublicHTTPS {
// Configure
certmagic.Default.Storage = &certmagic.FileStorage{Path: "data/https"}
@ -94,7 +95,7 @@ func (a *goBlog) startServer() (err error) {
ReadTimeout: 5 * time.Minute,
WriteTimeout: 5 * time.Minute,
}
addShutdownFunc(shutdownServer(httpServer, "http server"))
a.shutdown.Add(shutdownServer(httpServer, "http server"))
go func() {
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Println("Failed to start HTTP server:", err.Error())
@ -125,8 +126,10 @@ func (a *goBlog) startServer() (err error) {
func shutdownServer(s *http.Server, name string) func() {
return func() {
toc, c := context.WithTimeout(context.Background(), 5*time.Second)
_ = s.Shutdown(toc)
c()
defer c()
if err := s.Shutdown(toc); err != nil {
log.Printf("Error on server shutdown (%v): %v", name, err)
}
log.Println("Stopped server:", name)
}
}
@ -627,13 +630,13 @@ func (d *dynamicHandler) swapHandler(h *chi.Mux) {
}
func (d *dynamicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for !d.initialized {
time.Sleep(1 * time.Second)
}
// Fix to use Path routing instead of RawPath routing in Chi
r.URL.RawPath = ""
// Serve request
d.mutex.RLock()
for !d.initialized {
time.Sleep(10 * time.Millisecond)
}
router := d.router
d.mutex.RUnlock()
router.ServeHTTP(w, r)

44
main.go
View File

@ -50,9 +50,8 @@ func main() {
app := &goBlog{}
// Initialize config
log.Println("Initialize configuration...")
if err = app.initConfig(); err != nil {
logErrAndQuit("Failed to init config:", err.Error())
app.logErrAndQuit("Failed to init config:", err.Error())
return
}
@ -60,7 +59,7 @@ func main() {
if len(os.Args) >= 2 && os.Args[1] == "healthcheck" {
// Connect to public address + "/ping" and exit with 0 when successful
health := app.healthcheckExitCode()
shutdown()
app.shutdown.Shutdown()
os.Exit(health)
return
}
@ -72,11 +71,11 @@ func main() {
AccountName: app.cfg.User.Nick,
})
if err != nil {
logErrAndQuit(err.Error())
app.logErrAndQuit(err.Error())
return
}
log.Println("TOTP-Secret:", key.Secret())
shutdown()
app.shutdown.Shutdown()
return
}
@ -87,48 +86,49 @@ func main() {
app.preStartHooks()
// Initialize database and markdown
log.Println("Initialize database...")
if err = app.initDatabase(); err != nil {
logErrAndQuit("Failed to init database:", err.Error())
app.logErrAndQuit("Failed to init database:", err.Error())
return
}
log.Println("Initialize server components...")
log.Println("Initialize components...")
app.initMarkdown()
// Link check tool after init of markdown
if len(os.Args) >= 2 && os.Args[1] == "check" {
app.checkAllExternalLinks()
shutdown()
app.shutdown.Shutdown()
return
}
// More initializations
if err = app.initTemplateAssets(); err != nil { // Needs minify
logErrAndQuit("Failed to init template assets:", err.Error())
app.logErrAndQuit("Failed to init template assets:", err.Error())
return
}
if err = app.initTemplateStrings(); err != nil {
logErrAndQuit("Failed to init template translations:", err.Error())
app.logErrAndQuit("Failed to init template translations:", err.Error())
return
}
if err = app.initRendering(); err != nil { // Needs assets and minify
logErrAndQuit("Failed to init HTML rendering:", err.Error())
app.logErrAndQuit("Failed to init HTML rendering:", err.Error())
return
}
if err = app.initCache(); err != nil {
logErrAndQuit("Failed to init HTTP cache:", err.Error())
app.logErrAndQuit("Failed to init HTTP cache:", err.Error())
return
}
if err = app.initRegexRedirects(); err != nil {
logErrAndQuit("Failed to init redirects:", err.Error())
app.logErrAndQuit("Failed to init redirects:", err.Error())
return
}
if err = app.initHTTPLog(); err != nil {
logErrAndQuit("Failed to init HTTP logging:", err.Error())
app.logErrAndQuit("Failed to init HTTP logging:", err.Error())
return
}
if err = app.initActivityPub(); err != nil {
logErrAndQuit("Failed to init ActivityPub:", err.Error())
app.logErrAndQuit("Failed to init ActivityPub:", err.Error())
return
}
app.initWebmention()
@ -139,21 +139,21 @@ func main() {
// Start cron hooks
app.startHourlyHooks()
log.Println("Initialized components")
// Start the server
log.Println("Starting server(s)...")
err = app.startServer()
if err != nil {
logErrAndQuit("Failed to start server(s):", err.Error())
app.logErrAndQuit("Failed to start server(s):", err.Error())
return
}
// Wait till everything is shutdown
waitForShutdown()
app.shutdown.Wait()
}
func logErrAndQuit(v ...interface{}) {
func (a *goBlog) logErrAndQuit(v ...interface{}) {
log.Println(v...)
shutdown()
a.shutdown.Shutdown()
os.Exit(1)
}

View File

@ -1,48 +0,0 @@
package main
import (
"os"
"os/signal"
"sync"
"syscall"
)
var (
quit = make(chan os.Signal, 1)
shutdownFuncs = []func(){}
shutdownWg sync.WaitGroup
shutdownFuncMapMutex sync.Mutex
)
func init() {
signal.Notify(quit,
os.Interrupt,
syscall.SIGINT,
syscall.SIGTERM, // e.g. Docker stop
)
go func() {
<-quit
shutdown()
}()
}
func addShutdownFunc(f func()) {
shutdownWg.Add(1)
shutdownFuncMapMutex.Lock()
shutdownFuncs = append(shutdownFuncs, f)
shutdownFuncMapMutex.Unlock()
}
func shutdown() {
for _, f := range shutdownFuncs {
go func(f func()) {
defer shutdownWg.Done()
f()
}(f)
}
shutdownWg.Wait()
}
func waitForShutdown() {
shutdownWg.Wait()
}

2
tor.go
View File

@ -82,7 +82,7 @@ func (a *goBlog) startOnionService(h http.Handler) error {
ReadTimeout: 5 * time.Minute,
WriteTimeout: 5 * time.Minute,
}
addShutdownFunc(shutdownServer(s, "tor"))
a.shutdown.Add(shutdownServer(s, "tor"))
if err = s.Serve(onion); err != nil && err != http.ErrServerClosed {
return err
}