Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions docs/contributors/contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,9 @@ We welcome anyone to contribute to the FireFly project! If you're interested, th

---

## 🚀 Connect with us on Rocket Chat
You can chat with maintainers and other contributors on Rocket Chat in the `firefly` channel:
[https://chat.hyperledger.org/channel/firefly](https://chat.hyperledger.org/channel/firefly)

If you don't have a Linux Foundation ID, you can sign up for a free account here:
[https://wiki.hyperledger.org/display/CA/Setting+up+an+LFID](https://wiki.hyperledger.org/display/CA/Setting+up+an+LFID)
## 🚀 Connect with us on Discord
You can chat with maintainers and other contributors on Discord in the `firefly` channel:
[https://discord.gg/hyperledger](https://discord.gg/hyperledger)

## 📅 Join our Community Calls
Community calls are a place to talk to other contributors, maintainers, and other people interested in FireFly. Maintainers often discuss upcoming changes and proposed new features on these calls. These calls are a great way for the community to give feedback on new ideas, ask questions about FireFly, and hear how others are using FireFly to solve real world problems.
Expand Down
17 changes: 13 additions & 4 deletions docs/gettingstarted/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,20 @@ in the event.
"transport": "websockets",
"name": "app1",
"filter": {
"author": ".*",
"blockchainevent": {
"listener": ".*",
"name": ".*"
},
"events": ".*",
"group": ".*",
"tag": ".*",
"topics": ".*"
"message": {
"author": ".*",
"group": ".*",
"tag": ".*",
"topics": ".*"
},
"transaction": {
"type": ".*"
}
},
"options": {
"firstEvent": "newest",
Expand Down
6 changes: 6 additions & 0 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3693,6 +3693,12 @@ paths:
schema:
example: default
type: string
- description: 'TODO: Description'
in: query
name: fetchreferences
schema:
example: "true"
type: string
- description: Server-side request timeout (millseconds, or set a custom suffix
like 10s)
in: header
Expand Down
8 changes: 7 additions & 1 deletion internal/apiserver/route_get_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package apiserver

import (
"net/http"
"strings"

"github.com/hyperledger/firefly/internal/config"
"github.com/hyperledger/firefly/internal/i18n"
Expand All @@ -33,13 +34,18 @@ var getEvents = &oapispec.Route{
PathParams: []*oapispec.PathParam{
{Name: "ns", ExampleFromConf: config.NamespacesDefault, Description: i18n.MsgTBD},
},
QueryParams: nil,
QueryParams: []*oapispec.QueryParam{
{Name: "fetchreferences", Example: "true", Description: i18n.MsgTBD, IsBool: true},
},
FilterFactory: database.EventQueryFactory,
Description: i18n.MsgTBD,
JSONInputValue: nil,
JSONOutputValue: func() interface{} { return []*fftypes.Event{} },
JSONOutputCodes: []int{http.StatusOK},
JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) {
if strings.EqualFold(r.QP["fetchreferences"], "true") {
return filterResult(getOr(r.Ctx).GetEventsWithReferences(r.Ctx, r.PP["ns"], r.Filter))
}
return filterResult(getOr(r.Ctx).GetEvents(r.Ctx, r.PP["ns"], r.Filter))
},
}
24 changes: 24 additions & 0 deletions internal/apiserver/route_get_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
package apiserver

import (
"encoding/json"
"net/http/httptest"
"testing"

"github.com/hyperledger/firefly/pkg/database"
"github.com/hyperledger/firefly/pkg/fftypes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
Expand All @@ -37,3 +39,25 @@ func TestGetEvents(t *testing.T) {

assert.Equal(t, 200, res.Result().StatusCode)
}

func TestGetEventsWithReferences(t *testing.T) {
o, r := newTestAPIServer()
req := httptest.NewRequest("GET", "/api/v1/namespaces/mynamespace/events?fetchreferences", nil)
req.Header.Set("Content-Type", "application/json; charset=utf-8")
res := httptest.NewRecorder()

var ten int64 = 10
o.On("GetEventsWithReferences", mock.Anything, "mynamespace", mock.Anything).
Return([]*fftypes.EnrichedEvent{}, &database.FilterResult{
TotalCount: &ten,
}, nil)
r.ServeHTTP(res, req)

assert.Equal(t, 200, res.Result().StatusCode)
var resWithCount filterResultsWithCount
err := json.NewDecoder(res.Body).Decode(&resWithCount)
assert.NoError(t, err)
assert.NotNil(t, resWithCount.Items)
assert.Equal(t, int64(0), resWithCount.Count)
assert.Equal(t, int64(10), resWithCount.Total)
}
18 changes: 18 additions & 0 deletions internal/orchestrator/data_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,21 @@ func (or *orchestrator) GetTransactionBlockchainEvents(ctx context.Context, ns,
)
return or.database.GetBlockchainEvents(ctx, filter)
}

func (or *orchestrator) GetEventsWithReferences(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.EnrichedEvent, *database.FilterResult, error) {
filter = or.scopeNS(ns, filter)
events, fr, err := or.database.GetEvents(ctx, filter)
if err != nil {
return nil, nil, err
}

enriched := make([]*fftypes.EnrichedEvent, len(events))
for i, event := range events {
enrichedEvent, err := or.txHelper.EnrichEvent(or.ctx, event)
if err != nil {
return nil, nil, err
}
enriched[i] = enrichedEvent
}
return enriched, fr, err
}
89 changes: 89 additions & 0 deletions internal/orchestrator/data_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,95 @@ func TestGetEvents(t *testing.T) {
assert.NoError(t, err)
}

func TestGetEventsWithReferencesFail(t *testing.T) {
or := newTestOrchestrator()
u := fftypes.NewUUID()
or.mdi.On("GetEvents", mock.Anything, mock.Anything).Return(nil, nil, fmt.Errorf("pop"))
fb := database.EventQueryFactory.NewFilter(context.Background())
f := fb.And(fb.Eq("id", u))
_, _, err := or.GetEventsWithReferences(context.Background(), "ns1", f)
assert.EqualError(t, err, "pop")
}

func TestGetEventsWithReferences(t *testing.T) {
or := newTestOrchestrator()
u := fftypes.NewUUID()

// Setup the IDs
ref1 := fftypes.NewUUID()
ev1 := fftypes.NewUUID()
ref2 := fftypes.NewUUID()
ev2 := fftypes.NewUUID()
ref3 := fftypes.NewUUID()
ev3 := fftypes.NewUUID()

blockchainEvent := &fftypes.Event{
ID: ev1,
Sequence: 10000001,
Reference: ref1,
Type: fftypes.EventTypeBlockchainEventReceived,
}

txEvent := &fftypes.Event{
ID: ev2,
Sequence: 10000002,
Reference: ref2,
Type: fftypes.EventTypeTransactionSubmitted,
}

msgEvent := &fftypes.Event{
ID: ev3,
Sequence: 10000003,
Reference: ref3,
Type: fftypes.EventTypeMessageConfirmed,
}

or.mth.On("EnrichEvent", mock.Anything, blockchainEvent).Return(&fftypes.EnrichedEvent{
Event: *blockchainEvent,
BlockchainEvent: &fftypes.BlockchainEvent{
ID: ref1,
},
}, nil)

or.mth.On("EnrichEvent", mock.Anything, txEvent).Return(&fftypes.EnrichedEvent{
Event: *txEvent,
Transaction: &fftypes.Transaction{
ID: ref2,
},
}, nil)

or.mth.On("EnrichEvent", mock.Anything, msgEvent).Return(&fftypes.EnrichedEvent{
Event: *msgEvent,
Message: &fftypes.Message{
Header: fftypes.MessageHeader{
ID: ref3,
},
},
}, nil)

or.mdi.On("GetEvents", mock.Anything, mock.Anything).Return([]*fftypes.Event{
blockchainEvent,
txEvent,
msgEvent,
}, nil, nil)
fb := database.EventQueryFactory.NewFilter(context.Background())
f := fb.And(fb.Eq("id", u))
_, _, err := or.GetEventsWithReferences(context.Background(), "ns1", f)
assert.NoError(t, err)
}

func TestGetEventsWithReferencesEnrichFail(t *testing.T) {
or := newTestOrchestrator()
u := fftypes.NewUUID()

or.mdi.On("GetEvents", mock.Anything, mock.Anything).Return([]*fftypes.Event{{ID: fftypes.NewUUID()}}, nil, nil)
or.mth.On("EnrichEvent", mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop"))
fb := database.EventQueryFactory.NewFilter(context.Background())
f := fb.And(fb.Eq("id", u))
_, _, err := or.GetEventsWithReferences(context.Background(), "ns1", f)
assert.EqualError(t, err, "pop")
}

func TestGetBlockchainEventByID(t *testing.T) {
or := newTestOrchestrator()

Expand Down
4 changes: 4 additions & 0 deletions internal/orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/hyperledger/firefly/internal/sharedstorage/ssfactory"
"github.com/hyperledger/firefly/internal/syncasync"
"github.com/hyperledger/firefly/internal/tokens/tifactory"
"github.com/hyperledger/firefly/internal/txcommon"
"github.com/hyperledger/firefly/pkg/blockchain"
"github.com/hyperledger/firefly/pkg/database"
"github.com/hyperledger/firefly/pkg/dataexchange"
Expand Down Expand Up @@ -118,6 +119,7 @@ type Orchestrator interface {
GetOperations(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Operation, *database.FilterResult, error)
GetEventByID(ctx context.Context, ns, id string) (*fftypes.Event, error)
GetEvents(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Event, *database.FilterResult, error)
GetEventsWithReferences(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.EnrichedEvent, *database.FilterResult, error)
GetBlockchainEventByID(ctx context.Context, id *fftypes.UUID) (*fftypes.BlockchainEvent, error)
GetBlockchainEvents(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.BlockchainEvent, *database.FilterResult, error)

Expand Down Expand Up @@ -163,6 +165,7 @@ type orchestrator struct {
node *fftypes.UUID
metrics metrics.Manager
operations operations.Manager
txHelper txcommon.Helper
}

func NewOrchestrator() Orchestrator {
Expand Down Expand Up @@ -193,6 +196,7 @@ func (or *orchestrator) Init(ctx context.Context, cancelCtx context.CancelFunc)
if err == nil {
err = or.initNamespaces(ctx)
}
or.txHelper = txcommon.NewTransactionHelper(or.database)
// Bind together the blockchain interface callbacks, with the events manager
or.bc.bi = or.blockchain
or.bc.ei = or.events
Expand Down
4 changes: 4 additions & 0 deletions internal/orchestrator/orchestrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/hyperledger/firefly/mocks/privatemessagingmocks"
"github.com/hyperledger/firefly/mocks/sharedstoragemocks"
"github.com/hyperledger/firefly/mocks/tokenmocks"
"github.com/hyperledger/firefly/mocks/txcommonmocks"
"github.com/hyperledger/firefly/pkg/fftypes"
"github.com/hyperledger/firefly/pkg/tokens"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -72,6 +73,7 @@ type testOrchestrator struct {
mmi *metricsmocks.Manager
mom *operationmocks.Manager
mbp *batchpinmocks.Submitter
mth *txcommonmocks.Helper
}

func newTestOrchestrator() *testOrchestrator {
Expand Down Expand Up @@ -100,6 +102,7 @@ func newTestOrchestrator() *testOrchestrator {
mmi: &metricsmocks.Manager{},
mom: &operationmocks.Manager{},
mbp: &batchpinmocks.Submitter{},
mth: &txcommonmocks.Helper{},
}
tor.orchestrator.database = tor.mdi
tor.orchestrator.data = tor.mdm
Expand All @@ -119,6 +122,7 @@ func newTestOrchestrator() *testOrchestrator {
tor.orchestrator.metrics = tor.mmi
tor.orchestrator.operations = tor.mom
tor.orchestrator.batchpin = tor.mbp
tor.orchestrator.txHelper = tor.mth
tor.mdi.On("Name").Return("mock-di").Maybe()
tor.mem.On("Name").Return("mock-ei").Maybe()
tor.mps.On("Name").Return("mock-ps").Maybe()
Expand Down
32 changes: 32 additions & 0 deletions mocks/orchestratormocks/orchestrator.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.