Handle events

- Adds interfaces for developers to build handlers that update data in
response to log events
- Resolves #29
This commit is contained in:
Matt Krump
2018-03-05 10:01:50 -06:00
parent ed907535e3
commit 06f78e0083
163 changed files with 586 additions and 22397 deletions
+27
View File
@@ -0,0 +1,27 @@
# Handlers
## Description
Handlers must be defined in order to define what events should trigger data updates and how those are performed.
## Interface
### Initializer
Accepts DB and Blockchain from Vulcanize and returns a new handler. E.g. for a new object "Cup":
`func NewCupHandler(db *postgres.DB, blockchain core.ContractDataFetcher) handlers.Handler`
### Execute
Triggers operations to take in response to a given log event.
Can persist data from logs, fetch and persist arbitrary data from outside services (e.g. contract state), or take any number of other actions. E.g.:
`func (cupHandler *CupHandler) Execute() error`
## Additional Requirements
Handlers must define log filters and create them so that relevant watched events can be identified and retrieved. E.g.:
```$xslt
{
Name: "CupsBite",
FromBlock: 0,
ToBlock: -1,
Address: "0x448a5065aebb8e423f0896e6c5d525c040f59af3",
Topics: core.Topics{"0x40cc885400000000000000000000000000000000000000000000000000000000"},
},
```
+23
View File
@@ -0,0 +1,23 @@
package shared
import (
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Handler interface {
Execute() error
}
type HandlerInitializer func(db *postgres.DB, blockchain core.ContractDataFetcher) Handler
func HexToInt64(byteString string) int64 {
intHash := common.HexToHash(byteString)
return intHash.Big().Int64()
}
func HexToString(byteString string) string {
value := common.HexToHash(byteString)
return value.Big().String()
}
+13
View File
@@ -0,0 +1,13 @@
package shared_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestShared(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Shared Suite")
}
+27
View File
@@ -0,0 +1,27 @@
package shared
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Watcher struct {
Handlers []Handler
DB postgres.DB
Blockchain core.ContractDataFetcher
}
func (watcher *Watcher) AddHandlers(us []HandlerInitializer) {
for _, handlerInitializer := range us {
handler := handlerInitializer(&watcher.DB, watcher.Blockchain)
watcher.Handlers = append(watcher.Handlers, handler)
}
}
func (watcher *Watcher) Execute() error {
var err error
for _, handler := range watcher.Handlers {
err = handler.Execute()
}
return err
}
+69
View File
@@ -0,0 +1,69 @@
package shared_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/libraries/shared"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type MockHandler struct {
executeWasCalled bool
executeError error
}
func (mh *MockHandler) Execute() error {
if mh.executeError != nil {
return mh.executeError
}
mh.executeWasCalled = true
return nil
}
func fakeHandlerInitializer(db *postgres.DB, blockchain core.ContractDataFetcher) shared.Handler {
return &MockHandler{}
}
var _ = Describe("Watcher", func() {
It("Adds handlers", func() {
watcher := shared.Watcher{}
watcher.AddHandlers([]shared.HandlerInitializer{fakeHandlerInitializer})
Expect(len(watcher.Handlers)).To(Equal(1))
Expect(watcher.Handlers).To(ConsistOf(&MockHandler{}))
})
It("Adds handlers from multiple sources", func() {
watcher := shared.Watcher{}
watcher.AddHandlers([]shared.HandlerInitializer{fakeHandlerInitializer})
watcher.AddHandlers([]shared.HandlerInitializer{fakeHandlerInitializer})
Expect(len(watcher.Handlers)).To(Equal(2))
})
It("Executes each handler", func() {
watcher := shared.Watcher{}
fakeHandler := &MockHandler{}
watcher.Handlers = []shared.Handler{fakeHandler}
watcher.Execute()
Expect(fakeHandler.executeWasCalled).To(BeTrue())
})
It("Returns an error if handler returns an error", func() {
watcher := shared.Watcher{}
fakeHandler := &MockHandler{executeError: errors.New("Something bad happened")}
watcher.Handlers = []shared.Handler{fakeHandler}
err := watcher.Execute()
Expect(err).To(HaveOccurred())
Expect(fakeHandler.executeWasCalled).To(BeFalse())
})
})