mirror of https://github.com/jlelse/GoBlog
Use shutdowner library, improve logging, update deps
This commit is contained in:
parent
08b5dc1eaf
commit
ad8bf087ca
3
app.go
3
app.go
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
13
database.go
13
database.go
|
@ -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
10
go.mod
|
@ -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
22
go.sum
|
@ -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=
|
||||
|
|
43
hooks.go
43
hooks.go
|
@ -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
17
http.go
|
@ -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
44
main.go
|
@ -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)
|
||||
}
|
||||
|
|
48
shutdown.go
48
shutdown.go
|
@ -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
2
tor.go
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue