pages-server/server/database/pogreb.go

135 wiersze
2.6 KiB
Go
Czysty Zwykły widok Historia

2021-12-03 03:15:48 +00:00
package database
import (
2021-12-05 18:00:57 +00:00
"bytes"
2021-12-05 16:42:53 +00:00
"context"
2021-12-05 18:00:57 +00:00
"encoding/gob"
"errors"
2021-12-03 03:15:48 +00:00
"fmt"
2021-12-05 16:42:53 +00:00
"time"
2021-12-03 03:15:48 +00:00
"github.com/akrylysov/pogreb"
"github.com/akrylysov/pogreb/fs"
2021-12-05 18:00:57 +00:00
"github.com/go-acme/lego/v4/certificate"
"github.com/rs/zerolog/log"
2021-12-03 03:15:48 +00:00
)
var _ CertDB = aDB{}
2021-12-05 16:42:53 +00:00
type aDB struct {
ctx context.Context
cancel context.CancelFunc
intern *pogreb.DB
syncInterval time.Duration
}
func (p aDB) Close() error {
p.cancel()
return p.intern.Sync()
}
2021-12-05 18:00:57 +00:00
func (p aDB) Put(name string, cert *certificate.Resource) error {
var resGob bytes.Buffer
if err := gob.NewEncoder(&resGob).Encode(cert); err != nil {
return err
}
return p.intern.Put([]byte(name), resGob.Bytes())
2021-12-05 16:42:53 +00:00
}
func (p aDB) Get(name string) (*certificate.Resource, error) {
2021-12-05 18:00:57 +00:00
cert := &certificate.Resource{}
resBytes, err := p.intern.Get([]byte(name))
2021-12-05 18:00:57 +00:00
if err != nil {
return nil, err
}
if resBytes == nil {
return nil, nil
}
if err := gob.NewDecoder(bytes.NewBuffer(resBytes)).Decode(cert); err != nil {
2021-12-05 18:00:57 +00:00
return nil, err
}
return cert, nil
2021-12-05 16:42:53 +00:00
}
func (p aDB) Delete(key string) error {
return p.intern.Delete([]byte(key))
2021-12-05 16:42:53 +00:00
}
func (p aDB) Compact() (string, error) {
result, err := p.intern.Compact()
if err != nil {
return "", err
}
return fmt.Sprintf("%+v", result), nil
2021-12-05 16:42:53 +00:00
}
func (p aDB) Items(_, _ int) ([]*Cert, error) {
items := make([]*Cert, 0, p.intern.Count())
iterator := p.intern.Items()
for {
key, resBytes, err := iterator.Next()
if err != nil {
if errors.Is(err, pogreb.ErrIterationDone) {
break
}
return nil, err
}
res := &certificate.Resource{}
if err := gob.NewDecoder(bytes.NewBuffer(resBytes)).Decode(res); err != nil {
return nil, err
}
cert, err := toCert(string(key), res)
if err != nil {
return nil, err
}
items = append(items, cert)
}
return items, nil
2021-12-05 16:42:53 +00:00
}
var _ CertDB = &aDB{}
func (p aDB) sync() {
for {
err := p.intern.Sync()
if err != nil {
log.Error().Err(err).Msg("Syncing cert database failed")
2021-12-05 16:42:53 +00:00
}
select {
case <-p.ctx.Done():
return
case <-time.After(p.syncInterval):
}
}
}
func NewPogreb(path string) (CertDB, error) {
2021-12-03 03:15:48 +00:00
if path == "" {
return nil, fmt.Errorf("path not set")
}
2021-12-05 16:42:53 +00:00
db, err := pogreb.Open(path, &pogreb.Options{
2021-12-03 03:15:48 +00:00
BackgroundSyncInterval: 30 * time.Second,
BackgroundCompactionInterval: 6 * time.Hour,
FileSystem: fs.OSMMap,
})
2021-12-05 16:42:53 +00:00
if err != nil {
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
result := &aDB{
ctx: ctx,
cancel: cancel,
intern: db,
syncInterval: 5 * time.Minute,
}
go result.sync()
return result, nil
2021-12-03 03:15:48 +00:00
}