mirror of https://github.com/jlelse/GoBlog
Small changes (less GC, cache stats, linter fixes)
This commit is contained in:
parent
890e226ef6
commit
68b2d604c3
|
@ -29,6 +29,7 @@ linters:
|
||||||
- bidichk
|
- bidichk
|
||||||
- containedctx
|
- containedctx
|
||||||
- contextcheck
|
- contextcheck
|
||||||
|
- gosec
|
||||||
linters-settings:
|
linters-settings:
|
||||||
gosimple:
|
gosimple:
|
||||||
go: "1.17"
|
go: "1.17"
|
||||||
|
|
|
@ -23,7 +23,7 @@ type apRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) initAPSendQueue() {
|
func (a *goBlog) initAPSendQueue() {
|
||||||
a.listenOnQueue("ap", 15*time.Second, func(qi *queueItem, dequeue func(), reschedule func(time.Duration)) {
|
a.listenOnQueue("ap", time.Minute, func(qi *queueItem, dequeue func(), reschedule func(time.Duration)) {
|
||||||
var r apRequest
|
var r apRequest
|
||||||
if err := gob.NewDecoder(bytes.NewReader(qi.content)).Decode(&r); err != nil {
|
if err := gob.NewDecoder(bytes.NewReader(qi.content)).Decode(&r); err != nil {
|
||||||
log.Println("activitypub queue:", err.Error())
|
log.Println("activitypub queue:", err.Error())
|
||||||
|
|
9
cache.go
9
cache.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -38,7 +39,15 @@ func (a *goBlog) initCache() (err error) {
|
||||||
NumCounters: 40 * 1000, // 4000 items when full with 5 KB items -> x10 = 40.000
|
NumCounters: 40 * 1000, // 4000 items when full with 5 KB items -> x10 = 40.000
|
||||||
MaxCost: 20 * 1000 * 1000, // 20 MB
|
MaxCost: 20 * 1000 * 1000, // 20 MB
|
||||||
BufferItems: 64, // recommended
|
BufferItems: 64, // recommended
|
||||||
|
Metrics: true,
|
||||||
})
|
})
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(15 * time.Minute)
|
||||||
|
for range ticker.C {
|
||||||
|
met := a.cache.c.Metrics
|
||||||
|
log.Println("\nCache:", met.String())
|
||||||
|
}
|
||||||
|
}()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
check.go
4
check.go
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
@ -51,9 +50,6 @@ func (a *goBlog) checkLinks(w io.Writer, posts ...*post) error {
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 30 * time.Second,
|
||||||
Transport: gzhttp.Transport(&http.Transport{
|
Transport: gzhttp.Transport(&http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
},
|
|
||||||
// Limits
|
// Limits
|
||||||
DisableKeepAlives: true,
|
DisableKeepAlives: true,
|
||||||
MaxConnsPerHost: 1,
|
MaxConnsPerHost: 1,
|
||||||
|
|
52
database.go
52
database.go
|
@ -210,26 +210,10 @@ func (db *database) execContext(c context.Context, query string, args ...interfa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *database) query(query string, args ...interface{}) (*sql.Rows, error) {
|
func (db *database) query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||||
if db == nil || db.db == nil {
|
return db.queryContext(context.Background(), query, args...)
|
||||||
return nil, errors.New("database not initialized")
|
|
||||||
}
|
|
||||||
// Maybe prepare
|
|
||||||
st, args, _ := db.prepare(query, args...)
|
|
||||||
// Prepare context, call hook
|
|
||||||
ctx := db.dbBefore(context.Background(), query, args...)
|
|
||||||
defer db.dbAfter(ctx, query, args...)
|
|
||||||
// Query
|
|
||||||
if st != nil {
|
|
||||||
return st.QueryContext(ctx, args...)
|
|
||||||
}
|
|
||||||
return db.db.QueryContext(ctx, query, args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *database) queryRow(query string, args ...interface{}) (*sql.Row, error) {
|
func (db *database) queryContext(c context.Context, query string, args ...interface{}) (rows *sql.Rows, err error) {
|
||||||
return db.queryRowContext(context.Background(), query, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *database) queryRowContext(c context.Context, query string, args ...interface{}) (*sql.Row, error) {
|
|
||||||
if db == nil || db.db == nil {
|
if db == nil || db.db == nil {
|
||||||
return nil, errors.New("database not initialized")
|
return nil, errors.New("database not initialized")
|
||||||
}
|
}
|
||||||
|
@ -237,12 +221,38 @@ func (db *database) queryRowContext(c context.Context, query string, args ...int
|
||||||
st, args, _ := db.prepare(query, args...)
|
st, args, _ := db.prepare(query, args...)
|
||||||
// Prepare context, call hook
|
// Prepare context, call hook
|
||||||
ctx := db.dbBefore(c, query, args...)
|
ctx := db.dbBefore(c, query, args...)
|
||||||
defer db.dbAfter(ctx, query, args...)
|
|
||||||
// Query
|
// Query
|
||||||
if st != nil {
|
if st != nil {
|
||||||
return st.QueryRowContext(ctx, args...), nil
|
rows, err = st.QueryContext(ctx, args...)
|
||||||
|
} else {
|
||||||
|
rows, err = db.db.QueryContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
return db.db.QueryRowContext(ctx, query, args...), nil
|
// Call hook
|
||||||
|
db.dbAfter(ctx, query, args...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *database) queryRow(query string, args ...interface{}) (*sql.Row, error) {
|
||||||
|
return db.queryRowContext(context.Background(), query, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *database) queryRowContext(c context.Context, query string, args ...interface{}) (row *sql.Row, err error) {
|
||||||
|
if db == nil || db.db == nil {
|
||||||
|
return nil, errors.New("database not initialized")
|
||||||
|
}
|
||||||
|
// Maybe prepare
|
||||||
|
st, args, _ := db.prepare(query, args...)
|
||||||
|
// Prepare context, call hook
|
||||||
|
ctx := db.dbBefore(c, query, args...)
|
||||||
|
// Query
|
||||||
|
if st != nil {
|
||||||
|
row = st.QueryRowContext(ctx, args...)
|
||||||
|
} else {
|
||||||
|
row = db.db.QueryRowContext(ctx, query, args...)
|
||||||
|
}
|
||||||
|
// Call hook
|
||||||
|
db.dbAfter(ctx, query, args...)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other things
|
// Other things
|
||||||
|
|
|
@ -17,6 +17,7 @@ func (a *goBlog) exportMarkdownFiles(dir string) error {
|
||||||
filename := filepath.Join(dir, p.Path+".md")
|
filename := filepath.Join(dir, p.Path+".md")
|
||||||
filedir := filepath.Dir(filename)
|
filedir := filepath.Dir(filename)
|
||||||
_ = os.MkdirAll(filedir, 0777)
|
_ = os.MkdirAll(filedir, 0777)
|
||||||
|
//nolint:gosec
|
||||||
err = os.WriteFile(filename, []byte(p.contentWithParams()), 0666)
|
err = os.WriteFile(filename, []byte(p.contentWithParams()), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
@ -8,9 +9,9 @@ import (
|
||||||
|
|
||||||
func initGC() {
|
func initGC() {
|
||||||
go func() {
|
go func() {
|
||||||
ticker := time.NewTicker(10 * time.Minute)
|
ticker := time.NewTicker(15 * time.Minute)
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
go doGC()
|
doGC()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -20,5 +21,10 @@ func doGC() {
|
||||||
runtime.ReadMemStats(&old)
|
runtime.ReadMemStats(&old)
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
runtime.ReadMemStats(&new)
|
runtime.ReadMemStats(&new)
|
||||||
log.Printf("Alloc: %v MiB → %v MiB", old.Alloc/1024/1024, new.Alloc/1024/1024)
|
log.Println(fmt.Sprintf(
|
||||||
|
"\nAlloc: %d MiB -> %d MiB\nSys: %d MiB -> %d MiB\nNumGC: %d",
|
||||||
|
old.Alloc/1024/1024, new.Alloc/1024/1024,
|
||||||
|
old.Sys/1024/1024, new.Sys/1024/1024,
|
||||||
|
new.NumGC,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ func (a *goBlog) getTCPListener(s *http.Server) (net.Listener, error) {
|
||||||
}
|
}
|
||||||
return tls.NewListener(ln, &tls.Config{
|
return tls.NewListener(ln, &tls.Config{
|
||||||
GetCertificate: tailscale.GetCertificate,
|
GetCertificate: tailscale.GetCertificate,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
}), nil
|
}), nil
|
||||||
} else {
|
} else {
|
||||||
// Default
|
// Default
|
||||||
|
|
|
@ -22,10 +22,12 @@ func Test_queue(t *testing.T) {
|
||||||
defer app.db.close()
|
defer app.db.close()
|
||||||
db := app.db
|
db := app.db
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
|
||||||
err := db.enqueue("test", []byte(""), time.Now())
|
err := db.enqueue("test", []byte(""), time.Now())
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
err = db.enqueue("test", []byte("1"), time.Now())
|
err = db.enqueue("test", []byte("1"), time1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = db.enqueue("test", []byte("2"), time.Now())
|
err = db.enqueue("test", []byte("2"), time.Now())
|
||||||
|
@ -39,6 +41,7 @@ func Test_queue(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, qi)
|
require.NotNil(t, qi)
|
||||||
require.Equal(t, []byte("1"), qi.content)
|
require.Equal(t, []byte("1"), qi.content)
|
||||||
|
require.Equal(t, time1.UTC(), qi.schedule.UTC())
|
||||||
|
|
||||||
err = db.reschedule(qi, 1*time.Second)
|
err = db.reschedule(qi, 1*time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -63,3 +66,31 @@ func Test_queue(t *testing.T) {
|
||||||
require.Equal(t, []byte("1"), qi.content)
|
require.Equal(t, []byte("1"), qi.content)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Benchmark_queue(b *testing.B) {
|
||||||
|
app := &goBlog{
|
||||||
|
cfg: &config{
|
||||||
|
Db: &configDb{
|
||||||
|
File: filepath.Join(b.TempDir(), "test.db"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_ = app.initDatabase(false)
|
||||||
|
defer app.db.close()
|
||||||
|
db := app.db
|
||||||
|
|
||||||
|
err := db.enqueue("test", []byte("1"), time.Now())
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
b.Run("Peek with item", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = db.peekQueue(context.Background(), "test")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Peek without item", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = db.peekQueue(context.Background(), "abc")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ func (a *goBlog) getTailscaleListener(addr string) (net.Listener, error) {
|
||||||
if addr == ":443" && a.cfg.Server.TailscaleHTTPS {
|
if addr == ":443" && a.cfg.Server.TailscaleHTTPS {
|
||||||
ln = tls.NewListener(ln, &tls.Config{
|
ln = tls.NewListener(ln, &tls.Config{
|
||||||
GetCertificate: tailscale.GetCertificate,
|
GetCertificate: tailscale.GetCertificate,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return ln, nil
|
return ln, nil
|
||||||
|
|
2
tor.go
2
tor.go
|
@ -41,7 +41,7 @@ func (a *goBlog) startOnionService(h http.Handler) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})
|
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})
|
||||||
_ = os.WriteFile(torKeyPath, pemEncoded, 0666)
|
_ = os.WriteFile(torKeyPath, pemEncoded, 0600)
|
||||||
} else {
|
} else {
|
||||||
d, _ := os.ReadFile(torKeyPath)
|
d, _ := os.ReadFile(torKeyPath)
|
||||||
block, _ := pem.Decode(d)
|
block, _ := pem.Decode(d)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *goBlog) initWebmentionQueue() {
|
func (a *goBlog) initWebmentionQueue() {
|
||||||
a.listenOnQueue("wm", 15*time.Second, func(qi *queueItem, dequeue func(), reschedule func(time.Duration)) {
|
a.listenOnQueue("wm", time.Minute, func(qi *queueItem, dequeue func(), reschedule func(time.Duration)) {
|
||||||
var m mention
|
var m mention
|
||||||
if err := gob.NewDecoder(bytes.NewReader(qi.content)).Decode(&m); err != nil {
|
if err := gob.NewDecoder(bytes.NewReader(qi.content)).Decode(&m); err != nil {
|
||||||
log.Println("webmention queue:", err.Error())
|
log.Println("webmention queue:", err.Error())
|
||||||
|
|
Loading…
Reference in New Issue