graphvent/context.go

172 lines
4.3 KiB
Go

2023-07-09 14:30:30 -06:00
package graphvent
import (
badger "github.com/dgraph-io/badger/v3"
"fmt"
)
2023-07-26 00:18:11 -06:00
//Function to load an extension from bytes
2023-07-25 21:43:15 -06:00
type ExtensionLoadFunc func(*Context, []byte) (Extension, error)
2023-07-26 00:18:11 -06:00
// Information about a loaded extension
2023-07-25 21:43:15 -06:00
type ExtensionInfo struct {
Load ExtensionLoadFunc
Type ExtType
Data interface{}
2023-07-09 14:30:30 -06:00
}
2023-07-26 00:18:11 -06:00
// Information about a loaded node type
type NodeInfo struct {
Type NodeType
Extensions []ExtType
2023-07-26 00:18:11 -06:00
}
2023-07-10 22:31:43 -06:00
// A Context is all the data needed to run a graphvent
2023-07-09 14:30:30 -06:00
type Context struct {
2023-07-10 22:31:43 -06:00
// DB is the database connection used to load and write nodes
2023-07-09 14:30:30 -06:00
DB * badger.DB
2023-07-10 22:31:43 -06:00
// Log is an interface used to record events happening
2023-07-09 14:30:30 -06:00
Log Logger
2023-07-25 21:43:15 -06:00
// A mapping between type hashes and their corresponding extension definitions
Extensions map[uint64]ExtensionInfo
2023-07-26 00:18:11 -06:00
// A mapping between type hashes and their corresponding node definitions
Types map[uint64]NodeInfo
2023-07-25 21:43:15 -06:00
// All loaded Nodes
Nodes map[NodeID]*Node
2023-07-10 21:15:01 -06:00
}
2023-07-26 11:56:10 -06:00
func (ctx *Context) ExtByType(ext_type ExtType) *ExtensionInfo {
2023-07-25 21:43:15 -06:00
type_hash := ext_type.Hash()
2023-07-26 11:56:10 -06:00
ext, ok := ctx.Extensions[type_hash]
if ok == true {
return &ext
} else {
return nil
}
2023-07-10 21:15:01 -06:00
}
func (ctx *Context) RegisterNodeType(node_type NodeType, extensions []ExtType) error {
2023-07-26 00:18:11 -06:00
type_hash := node_type.Hash()
_, exists := ctx.Types[type_hash]
if exists == true {
return fmt.Errorf("Cannot register node type %s, type already exists in context", node_type)
}
ext_found := map[ExtType]bool{}
for _, extension := range(extensions) {
_, in_ctx := ctx.Extensions[extension.Hash()]
if in_ctx == false {
return fmt.Errorf("Cannot register node type %s, required extension %s not in context", node_type, extension)
}
_, duplicate := ext_found[extension]
if duplicate == true {
return fmt.Errorf("Duplicate extension %s found in extension list", extension)
}
ext_found[extension] = true
}
2023-07-26 00:18:11 -06:00
ctx.Types[type_hash] = NodeInfo{
Type: node_type,
Extensions: extensions,
2023-07-26 00:18:11 -06:00
}
return nil
}
2023-07-10 22:31:43 -06:00
// Add a node to a context, returns an error if the def is invalid or already exists in the context
2023-07-26 00:18:11 -06:00
func (ctx *Context) RegisterExtension(ext_type ExtType, load_fn ExtensionLoadFunc, data interface{}) error {
2023-07-25 21:43:15 -06:00
if load_fn == nil {
return fmt.Errorf("def has no load function")
2023-07-09 14:30:30 -06:00
}
2023-07-25 21:43:15 -06:00
type_hash := ext_type.Hash()
_, exists := ctx.Extensions[type_hash]
2023-07-09 14:30:30 -06:00
if exists == true {
2023-07-25 21:43:15 -06:00
return fmt.Errorf("Cannot register extension of type %s, type already exists in context", ext_type)
2023-07-09 14:30:30 -06:00
}
2023-07-25 21:43:15 -06:00
ctx.Extensions[type_hash] = ExtensionInfo{
Load: load_fn,
Type: ext_type,
2023-07-26 00:18:11 -06:00
Data: data,
2023-07-10 21:15:01 -06:00
}
2023-07-09 14:30:30 -06:00
return nil
}
2023-07-10 22:31:43 -06:00
// Create a new Context with all the library content added
2023-07-25 21:43:15 -06:00
func NewContext(db * badger.DB, log Logger) (*Context, error) {
2023-07-09 14:30:30 -06:00
ctx := &Context{
DB: db,
Log: log,
2023-07-25 21:43:15 -06:00
Extensions: map[uint64]ExtensionInfo{},
2023-07-26 00:18:11 -06:00
Types: map[uint64]NodeInfo{},
2023-07-25 21:43:15 -06:00
Nodes: map[NodeID]*Node{},
2023-07-09 14:30:30 -06:00
}
2023-07-26 00:18:11 -06:00
err := ctx.RegisterExtension(ACLExtType, LoadACLExt, nil)
if err != nil {
return nil, err
}
err = ctx.RegisterExtension(ACLPolicyExtType, LoadACLPolicyExt, NewACLPolicyExtContext())
if err != nil {
return nil, err
}
err = ctx.RegisterExtension(LockableExtType, LoadLockableExt, nil)
if err != nil {
return nil, err
}
2023-07-26 11:56:10 -06:00
err = ctx.RegisterExtension(ListenerExtType, LoadListenerExt, nil)
if err != nil {
return nil, err
}
err = ctx.RegisterExtension(ECDHExtType, LoadECDHExt, nil)
2023-07-26 00:18:11 -06:00
if err != nil {
return nil, err
}
err = ctx.RegisterExtension(GroupExtType, LoadGroupExt, nil)
2023-07-26 00:18:11 -06:00
if err != nil {
return nil, err
}
gql_ctx := NewGQLExtContext()
err = ctx.RegisterExtension(GQLExtType, LoadGQLExt, gql_ctx)
2023-07-25 09:51:55 -06:00
if err != nil {
2023-07-25 21:43:15 -06:00
return nil, err
2023-07-25 09:51:55 -06:00
}
2023-07-10 21:15:01 -06:00
thread_ctx := NewThreadExtContext()
err = ctx.RegisterExtension(ThreadExtType, LoadThreadExt, thread_ctx)
2023-07-10 21:15:01 -06:00
if err != nil {
2023-07-25 21:43:15 -06:00
return nil, err
2023-07-09 14:30:30 -06:00
}
err = thread_ctx.RegisterThreadType(GQLThreadType, gql_actions, gql_handlers)
2023-07-26 11:56:10 -06:00
if err != nil {
return nil, err
}
err = ctx.RegisterNodeType(GQLNodeType, []ExtType{ACLExtType, ACLPolicyExtType, GroupExtType, GQLExtType, ThreadExtType, LockableExtType})
if err != nil {
return nil, err
}
err = gql_ctx.RegisterNodeType(GQLNodeType, GQLTypeGQLNode.Type)
if err != nil {
return nil, err
}
schema, err := BuildSchema(gql_ctx)
if err != nil {
return nil, err
}
gql_ctx.Schema = schema
2023-07-25 21:43:15 -06:00
return ctx, nil
2023-07-09 14:30:30 -06:00
}