-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstore.go
136 lines (118 loc) · 3.63 KB
/
store.go
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
/*
* go-leia
* Copyright (C) 2021 Nuts community
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
package leia
import (
"os"
"path/filepath"
"github.com/piprate/json-gold/ld"
"go.etcd.io/bbolt"
)
// CollectionType defines if a Collection is a JSON collection or JSONLD collection.
type CollectionType int
const (
// JSONCollection defines a collection uses JSON search paths to index documents
JSONCollection CollectionType = iota
// JSONLDCollection defines a collection uses JSON-LD IRI search paths to index documents
JSONLDCollection
)
// Store is the main interface for storing/finding documents
type Store interface {
// Collection creates or returns a Collection of the specified type.
// On the db level it's a bucket for the documents and 1 bucket per index.
Collection(collectionType CollectionType, name string) Collection
// Close the bbolt DB
Close() error
}
// Store holds a reference to the bbolt data file and all collections.
type store struct {
db *bbolt.DB
collections map[string]*collection
documentLoader ld.DocumentLoader
// options is used during configuration
options bbolt.Options
}
// StoreOption is the function type for the Store Options
type StoreOption func(store *store)
// WithoutSync is a store option which signals the underlying bbolt db to skip syncing with disk
func WithoutSync() StoreOption {
return func(store *store) {
store.options.NoSync = true
}
}
// WithDocumentLoader overrides the default document loader
func WithDocumentLoader(documentLoader ld.DocumentLoader) StoreOption {
return func(store *store) {
store.documentLoader = documentLoader
}
}
// NewStore creates a new store.
// the noSync option disables flushing to disk, ideal for testing and bulk loading
func NewStore(dbFile string, options ...StoreOption) (Store, error) {
err := os.MkdirAll(filepath.Dir(dbFile), os.ModePerm)
if err != nil {
return nil, err
}
// store with defaults
st := &store{
options: *bbolt.DefaultOptions,
collections: map[string]*collection{},
documentLoader: ld.NewDefaultDocumentLoader(nil),
}
// apply options
for _, option := range options {
option(st)
}
st.db, err = bbolt.Open(dbFile, boltDBFileMode, &st.options)
if err != nil {
return nil, err
}
return st, nil
}
func (s *store) Collection(collectionType CollectionType, name string) Collection {
c, ok := s.collections[name]
if !ok {
var vCollector valueCollector
switch collectionType {
case JSONCollection:
vCollector = JSONPathValueCollector
case JSONLDCollection:
vCollector = JSONLDValueCollector
default:
panic("unknown collection type")
}
c = &collection{
name: name,
collectionType: collectionType,
db: s.db,
documentLoader: s.documentLoader,
refMake: defaultReferenceCreator,
valueCollector: vCollector,
}
s.collections[name] = c
} else if c.collectionType != collectionType {
panic("collection already exists with different type")
}
return c
}
func (s *store) Close() error {
if s.db != nil {
return s.db.Close()
}
return nil
}