internal/index/meta/meta.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | package meta
import (
"encoding/json"
"time"
"alin.ovh/searchix/internal/file"
"alin.ovh/x/log"
"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fmsg"
)
const (
CurrentSchemaVersion = 11
BaseName = "meta.json"
)
type SourceMeta struct {
StoredAt time.Time
UpdatedAt time.Time
Path string
}
type data struct {
SchemaVersion int
LastImport struct {
StartedAt time.Time
FinishedAt time.Time
}
Sources map[string]*SourceMeta
}
type Meta struct {
root *file.Root
log *log.Logger
exists bool
data
}
func (i *Meta) IsSchemaOutdated() bool {
return i.SchemaVersion < CurrentSchemaVersion
}
func (i *Meta) Exists() bool {
return i.exists
}
func (i *Meta) Save() error {
i.SchemaVersion = CurrentSchemaVersion
j, err := json.MarshalIndent(i.data, "", " ")
if err != nil {
return fault.Wrap(err, fmsg.With("could not prepare index metadata for saving"))
}
i.log.Debug("saving index metadata", "path", BaseName)
err = i.root.WriteFile(BaseName, j, 0o600)
if err != nil {
return fault.Wrap(err, fmsg.With("could not save index metadata"))
}
i.exists = true
return nil
}
func (i *Meta) GetSourceMeta(source string) *SourceMeta {
sourceMeta := i.Sources[source]
if sourceMeta == nil {
return &SourceMeta{}
}
return sourceMeta
}
func (i *Meta) SetSourceMeta(source string, meta *SourceMeta) {
i.Sources[source] = meta
}
func (i *Meta) LastImported() time.Time {
var last time.Time
for _, sourceMeta := range i.Sources {
if sourceMeta.StoredAt.After(last) {
last = sourceMeta.StoredAt
}
}
return last
}
func (i *Meta) LastUpdated() time.Time {
var last time.Time
for _, sourceMeta := range i.Sources {
if sourceMeta.UpdatedAt.After(last) {
last = sourceMeta.UpdatedAt
}
}
return last
}
func Create(root *file.Root, log *log.Logger) (*Meta, error) {
exists, err := root.Exists(BaseName)
if err != nil {
return nil, fault.Wrap(err, fmsg.With("could not check for existence of index metadata"))
}
if exists {
return nil, fault.New("index metadata already exists")
}
return &Meta{
root: root,
log: log,
data: data{
SchemaVersion: CurrentSchemaVersion,
Sources: make(map[string]*SourceMeta),
},
}, nil
}
func OpenOrCreate(root *file.Root, log *log.Logger) (*Meta, error) {
exists, err := root.Exists(BaseName)
if err != nil {
return nil, fault.Wrap(err, fmsg.With("could not check for existence of index metadata"))
}
if !exists {
return Create(root, log)
}
j, baseErr := root.ReadFile(BaseName)
if baseErr != nil {
return nil, fault.Wrap(baseErr, fmsg.With("could not open index metadata file"))
}
meta := Meta{
root: root,
log: log,
exists: exists,
}
if err := json.Unmarshal(j, &meta.data); err != nil {
return nil, fault.Wrap(err, fmsg.With("index metadata is corrupt, try replacing the index"))
}
return &meta, nil
}
|