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"
|
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
|
|
|
)
|
|
|
|
|
2022-03-27 19:54:06 +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
|
|
|
}
|
|
|
|
|
2021-12-05 18:00:57 +00:00
|
|
|
func (p aDB) Get(name []byte) (*certificate.Resource, error) {
|
|
|
|
cert := &certificate.Resource{}
|
|
|
|
resBytes, err := p.intern.Get(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if resBytes == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
if err = gob.NewDecoder(bytes.NewBuffer(resBytes)).Decode(cert); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return cert, nil
|
2021-12-05 16:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p aDB) Delete(key []byte) error {
|
|
|
|
return p.intern.Delete(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p aDB) Compact() (pogreb.CompactionResult, error) {
|
|
|
|
return p.intern.Compact()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p aDB) Items() *pogreb.ItemIterator {
|
|
|
|
return p.intern.Items()
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ CertDB = &aDB{}
|
|
|
|
|
|
|
|
func (p aDB) sync() {
|
|
|
|
for {
|
|
|
|
err := p.intern.Sync()
|
|
|
|
if err != nil {
|
|
|
|
log.Err(err).Msg("Syncing cert database failed")
|
|
|
|
}
|
|
|
|
select {
|
|
|
|
case <-p.ctx.Done():
|
|
|
|
return
|
|
|
|
case <-time.After(p.syncInterval):
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(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
|
|
|
}
|