-
Notifications
You must be signed in to change notification settings - Fork 1
/
zanzi.go
190 lines (167 loc) · 4.67 KB
/
zanzi.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package zanzi
import (
"fmt"
"os/user"
"strings"
rcdb "github.com/sourcenetwork/raccoondb"
"go.uber.org/zap"
_ "google.golang.org/grpc"
"github.com/sourcenetwork/zanzi/internal/policy"
"github.com/sourcenetwork/zanzi/internal/relation_graph"
"github.com/sourcenetwork/zanzi/internal/store"
"github.com/sourcenetwork/zanzi/internal/store/kv_store"
"github.com/sourcenetwork/zanzi/pkg/api"
"github.com/sourcenetwork/zanzi/pkg/types"
)
const (
dataFile string = "zanzi.db"
dataDir string = "zanzi"
)
type option func(*Zanzi) error
// New builds a new instance of Zanzi with the given options.
//
// If opt is nil, initializes Zanzi with an INFO level logger
// and stores its data under DefaultDataDir.
func New(opt ...option) (Zanzi, error) {
zanzi := Zanzi{}
for _, o := range opt {
err := o(&zanzi)
if err != nil {
return Zanzi{}, fmt.Errorf("could not build Zanzi: %w", err)
}
}
zanzi.setDefaults()
zanzi.init()
return zanzi, nil
}
// setDefaults initializes required attributes if not supplied by the user.
func (z *Zanzi) setDefaults() {
if z.logger == nil {
WithDefaultLogger()(z)
}
if z.store == nil {
WithMemKVStore()(z)
}
}
// WithDevelopmentConfig configures zanzi to use a local in memory kv store and to output DEBUG level logging.
func WithDevelopmentConfig() option {
return func(z *Zanzi) error {
err := WithMemKVStore()(z)
if err != nil {
return err
}
return WithDevelopmentLogger()(z)
}
}
// WithLogger sets the logger which will be used by Zanzi.
// The Logger type is a zanzi defined logging facade.
// This approach gives clients the freedom to choose the
// logging level and logging implementation for Zanzi.
func WithLogger(logger types.Logger) option {
return func(z *Zanzi) error {
z.logger = logger
return nil
}
}
// WithDefaultLogger configures zanzi to use its default logger implementation (Zap).
// Logging level is set to INFO.
func WithDefaultLogger() option {
return func(z *Zanzi) error {
z.logger = zap.S()
return nil
}
}
// WithDevelopmentLogger configures zanzi to use Zap as its logger (writes to stderr).
// Logging level is set to DEBUG.
func WithDevelopmentLogger() option {
return func(z *Zanzi) error {
zapLogger, err := zap.NewDevelopment()
if err != nil {
return err
}
z.logger = zapLogger.Sugar()
return nil
}
}
// WithoutLogger configures zanzi to not produce any logs.
func WithoutLogger(logger types.Logger) option {
return func(z *Zanzi) error {
z.logger = &types.NoopLogger{}
return nil
}
}
// WithKVStore configures zanzi to use the given kv store as its
// data store
func WithKVStore(kv rcdb.KVStore) option {
return func(z *Zanzi) error {
kvStore, err := kv_store.NewKVStore(kv)
if err != nil {
return err
}
z.store = &kvStore
return nil
}
}
// WithMemKVStore configures zanzi to use an in memory kv store
func WithMemKVStore() option {
kv := rcdb.NewMemKV()
return WithKVStore(kv)
}
// Zanzi is a container type responsible for initializing the zanzi's internal types and any additional requirements.
// Clients should use the new function to use zanzi.
type Zanzi struct {
polService api.PolicyServiceServer
relGraphService api.RelationGraphServer
logger types.Logger
store store.Store
terminationFns []func() error
}
func (z *Zanzi) init() {
z.polService = policy.NewService(z.store.GetPolicyRepository())
z.relGraphService = relation_graph.NewService(
z.store.GetRelationNodeRepository(),
z.store.GetPolicyRepository(),
z.logger,
)
}
// GetRelationshipGraphService returns an implementation of the
// GRPC defined RelationGraph service type.
func (z *Zanzi) GetRelationGraphService() api.RelationGraphServer {
return z.relGraphService
}
// GetPolicyService returns an implementation of the
// GRPC defined RelationGraph service type.
func (z *Zanzi) GetPolicyService() api.PolicyServiceServer {
return z.polService
}
func (z *Zanzi) GetLogger() types.Logger {
return z.logger
}
func (z *Zanzi) Cleanup() error {
for _, fn := range z.terminationFns {
err := fn()
if err != nil {
return err
}
}
return nil
}
// WithDefaultKVStore configures Zanzi to use Raccoons default PersistentKV Store. Data will be stored in path
func WithDefaultKVStore(path string) option {
return func(z *Zanzi) error {
if strings.HasPrefix(path, "~") {
usr, err := user.Current()
if err != nil {
return fmt.Errorf("error identifying user: %w", err)
}
home := usr.HomeDir
path = strings.Replace(path, "~", home, 1)
}
kv, closeFn, err := rcdb.NewPersistentKV(path, dataFile)
if err != nil {
return fmt.Errorf("error initializing kv store: %v", err)
}
z.terminationFns = append(z.terminationFns, closeFn)
return WithKVStore(kv)(z)
}
}