watcher configuration; super node versioning

This commit is contained in:
Ian Norden
2020-02-25 16:38:46 -06:00
parent 25aa4634e9
commit 330a083749
13 changed files with 381 additions and 77 deletions
+102 -4
View File
@@ -17,10 +17,24 @@
package watcher
import (
"context"
"errors"
"fmt"
"github.com/vulcanize/vulcanizedb/pkg/wasm"
"github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/viper"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/eth/client"
"github.com/vulcanize/vulcanizedb/pkg/eth/core"
"github.com/vulcanize/vulcanizedb/pkg/postgres"
"github.com/vulcanize/vulcanizedb/pkg/super_node/btc"
"github.com/vulcanize/vulcanizedb/pkg/super_node/eth"
"github.com/vulcanize/vulcanizedb/pkg/super_node/shared"
shared2 "github.com/vulcanize/vulcanizedb/pkg/watcher/shared"
"github.com/vulcanize/vulcanizedb/utils"
)
// Config holds all of the parameters necessary for defining and running an instance of a watcher
@@ -32,9 +46,93 @@ type Config struct {
// DB itself
DB *postgres.DB
// Subscription client
Client core.RPCClient
Client interface{}
// WASM instantiation paths and namespaces
WASMInstances [][2]string
// Path and names for trigger functions (sql files) that (can) use the instantiated wasm namespaces
TriggerFunctions [][2]string
WASMFunctions []wasm.WasmFunction
// File paths for trigger functions (sql files) that (can) use the instantiated wasm namespaces
TriggerFunctions []string
// Chain type used to specify what type of raw data we will be processing
Chain shared.ChainType
// Source type used to specify which streamer to use based on what API we will be interfacing with
Source shared2.SourceType
// Info for the node
NodeInfo core.Node
}
func NewWatcherConfig() (*Config, error) {
c := new(Config)
var err error
chain := viper.GetString("watcher.chain")
c.Chain, err = shared.NewChainType(chain)
if err != nil {
return nil, err
}
switch c.Chain {
case shared.Ethereum:
c.SubscriptionConfig, err = eth.NewEthSubscriptionConfig()
if err != nil {
return nil, err
}
case shared.Bitcoin:
c.SubscriptionConfig, err = btc.NewEthSubscriptionConfig()
if err != nil {
return nil, err
}
case shared.Omni:
return nil, errors.New("omni chain type currently not supported")
default:
return nil, fmt.Errorf("unexpected chain type %s", c.Chain.String())
}
sourcePath := viper.GetString("watcher.dataSource")
if sourcePath == "" {
sourcePath = "ws://127.0.0.1:8080" // default to and try the default ws url if no path is provided
}
sourceType := viper.GetString("watcher.dataPath")
c.Source, err = shared2.NewSourceType(sourceType)
if err != nil {
return nil, err
}
switch c.Source {
case shared2.Ethereum:
return nil, errors.New("ethereum data source currently not supported")
case shared2.Bitcoin:
return nil, errors.New("bitcoin data source currently not supported")
case shared2.VulcanizeDB:
rawRPCClient, err := rpc.Dial(sourcePath)
if err != nil {
return nil, err
}
cli := client.NewRPCClient(rawRPCClient, sourcePath)
var nodeInfo core.Node
if err := cli.CallContext(context.Background(), &nodeInfo, "vdb_node"); err != nil {
return nil, err
}
c.NodeInfo = nodeInfo
c.Client = cli
default:
return nil, fmt.Errorf("unexpected data source type %s", c.Source.String())
}
wasmBinaries := viper.GetStringSlice("watcher.wasmBinaries")
wasmNamespaces := viper.GetStringSlice("watcher.wasmNamespaces")
if len(wasmBinaries) != len(wasmNamespaces) {
return nil, fmt.Errorf("watcher config needs a namespace for every wasm binary\r\nhave %d binaries and %d namespaces", len(wasmBinaries), len(wasmNamespaces))
}
c.WASMFunctions = make([]wasm.WasmFunction, len(wasmBinaries))
for i, bin := range wasmBinaries {
c.WASMFunctions[i] = wasm.WasmFunction{
BinaryPath: bin,
Namespace: wasmNamespaces[i],
}
}
c.TriggerFunctions = viper.GetStringSlice("watcher.triggerFunctions")
c.DBConfig = config.Database{
Name: viper.GetString("watcher.database.name"),
Hostname: viper.GetString("watcher.database.hostname"),
Port: viper.GetInt("watcher.database.port"),
User: viper.GetString("watcher.database.user"),
Password: viper.GetString("watcher.database.password"),
}
db := utils.LoadPostgres(c.DBConfig, c.NodeInfo)
c.DB = &db
return c, nil
}
+13 -3
View File
@@ -28,12 +28,22 @@ import (
)
// NewSuperNodeStreamer returns a new shared.SuperNodeStreamer
func NewSuperNodeStreamer(client core.RPCClient) shared.SuperNodeStreamer {
return streamer.NewSuperNodeStreamer(client)
func NewSuperNodeStreamer(source shared.SourceType, client interface{}) (shared.SuperNodeStreamer, error) {
switch source {
case shared.VulcanizeDB:
cli, ok := client.(core.RPCClient)
if !ok {
var expectedClientType core.RPCClient
return nil, fmt.Errorf("vulcanizedb NewSuperNodeStreamer construct expects client type %T got %T", expectedClientType, client)
}
return streamer.NewSuperNodeStreamer(cli), nil
default:
return nil, fmt.Errorf("NewSuperNodeStreamer constructor unexpected souce type %s", source.String())
}
}
// NewRepository constructs and returns a new Repository that satisfies the shared.Repository interface for the specified chain
func NewRepository(chain shared2.ChainType, db *postgres.DB, triggerFuncs [][2]string) (shared.Repository, error) {
func NewRepository(chain shared2.ChainType, db *postgres.DB, triggerFuncs []string) (shared.Repository, error) {
switch chain {
case shared2.Ethereum:
return eth.NewRepository(db, triggerFuncs), nil
+2 -2
View File
@@ -32,12 +32,12 @@ var (
// Repository is the underlying struct for satisfying the shared.Repository interface for eth
type Repository struct {
db *postgres.DB
triggerFunctions [][2]string
triggerFunctions []string
deleteCalls int64
}
// NewRepository returns a new eth.Repository that satisfies the shared.Repository interface
func NewRepository(db *postgres.DB, triggerFunctions [][2]string) shared.Repository {
func NewRepository(db *postgres.DB, triggerFunctions []string) shared.Repository {
return &Repository{
db: db,
triggerFunctions: triggerFunctions,
+9 -5
View File
@@ -40,7 +40,7 @@ type Watcher interface {
// Service is the underlying struct for the SuperNodeWatcher
type Service struct {
// Config
WatcherConfig Config
WatcherConfig *Config
// Interface for streaming data from super node
SuperNodeStreamer shared.SuperNodeStreamer
// Interface for db operations
@@ -60,16 +60,20 @@ type Service struct {
}
// NewWatcher returns a new Service which satisfies the Watcher interface
func NewWatcher(c Config, quitChan chan bool) (Watcher, error) {
func NewWatcher(c *Config, quitChan chan bool) (Watcher, error) {
repo, err := NewRepository(c.SubscriptionConfig.ChainType(), c.DB, c.TriggerFunctions)
if err != nil {
return nil, err
}
streamer, err := NewSuperNodeStreamer(c.Source, c.Client)
if err != nil {
return nil, err
}
return &Service{
WatcherConfig: c,
SuperNodeStreamer: NewSuperNodeStreamer(c.Client),
SuperNodeStreamer: streamer,
Repository: repo,
WASMIniter: wasm.NewWASMInstantiator(c.DB, c.WASMInstances),
WASMIniter: wasm.NewWASMInstantiator(c.DB, c.WASMFunctions),
PayloadChan: make(chan super_node.SubscriptionPayload, super_node.PayloadChanBufferSize),
QuitChan: quitChan,
}, nil
@@ -85,7 +89,7 @@ func (s *Service) Init() error {
return s.Repository.LoadTriggers()
}
// Watch is the top level loop for watching super node
// Watch is the top level loop for watching
func (s *Service) Watch(wg *sync.WaitGroup) error {
rlpConfig, err := rlp.EncodeToBytes(s.WatcherConfig.SubscriptionConfig)
if err != nil {
+58
View File
@@ -0,0 +1,58 @@
// VulcanizeDB
// Copyright © 2019 Vulcanize
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package shared
import (
"errors"
"strings"
)
// SourceType enum for specifying source type for raw chain data
type SourceType int
const (
Unknown SourceType = iota
VulcanizeDB
Ethereum
Bitcoin
)
func (c SourceType) String() string {
switch c {
case Ethereum:
return "Ethereum"
case Bitcoin:
return "Bitcoin"
case VulcanizeDB:
return "VulcanizeDB"
default:
return ""
}
}
func NewSourceType(name string) (SourceType, error) {
switch strings.ToLower(name) {
case "ethereum", "eth":
return Ethereum, nil
case "bitcoin", "btc", "xbt":
return Bitcoin, nil
case "vulcanizedb", "vdb":
return VulcanizeDB, nil
default:
return Unknown, errors.New("invalid name for data source")
}
}