From 8e62ab074835fbb5ce9adf057c4ebedfb1585b15 Mon Sep 17 00:00:00 2001 From: Levente Pap <levente.pap@iota.org> Date: Tue, 16 Jun 2020 17:28:25 +0200 Subject: [PATCH] OpinionEvent struct for calling Finalized and Failed vote events --- dapps/valuetransfers/dapp.go | 4 ++-- dapps/valuetransfers/fpc.go | 1 + dapps/valuetransfers/packages/consensus/fcob.go | 6 +++--- packages/vote/fpc/fpc.go | 4 ++-- packages/vote/fpc/fpc_test.go | 12 ++++++------ packages/vote/net/server.go | 1 + packages/vote/voter.go | 14 ++++++++++++-- 7 files changed, 27 insertions(+), 15 deletions(-) diff --git a/dapps/valuetransfers/dapp.go b/dapps/valuetransfers/dapp.go index 7964e471..ef584abf 100644 --- a/dapps/valuetransfers/dapp.go +++ b/dapps/valuetransfers/dapp.go @@ -89,8 +89,8 @@ func configure(_ *node.Plugin) { // configure FPC + link to consensus configureFPC() voter.Events().Finalized.Attach(events.NewClosure(FCOB.ProcessVoteResult)) - voter.Events().Failed.Attach(events.NewClosure(func(id string, lastOpinion vote.Opinion) { - log.Errorf("FPC failed for transaction with id '%s' - last opinion: '%s'", id, lastOpinion) + voter.Events().Failed.Attach(events.NewClosure(func(ev *vote.OpinionEvent) { + log.Errorf("FPC failed for transaction with id '%s' - last opinion: '%s'", ev.ID, ev.Opinion) })) // subscribe to message-layer diff --git a/dapps/valuetransfers/fpc.go b/dapps/valuetransfers/fpc.go index 78ab441c..3c96930f 100644 --- a/dapps/valuetransfers/fpc.go +++ b/dapps/valuetransfers/fpc.go @@ -185,6 +185,7 @@ func (pog *PeerOpinionGiver) Query(ctx context.Context, ids []string) (vote.Opin query := &votenet.QueryRequest{Id: ids} reply, err := client.Opinion(ctx, query) if err != nil { + // TODO: add an event QueryErrorEvent (metrics) return nil, fmt.Errorf("unable to query opinions: %w", err) } diff --git a/dapps/valuetransfers/packages/consensus/fcob.go b/dapps/valuetransfers/packages/consensus/fcob.go index 00722a7d..3d43f4d6 100644 --- a/dapps/valuetransfers/packages/consensus/fcob.go +++ b/dapps/valuetransfers/packages/consensus/fcob.go @@ -41,15 +41,15 @@ func NewFCOB(tangle *tangle.Tangle, averageNetworkDelay time.Duration) (fcob *FC } // ProcessVoteResult allows an external voter to hand in the results of the voting process. -func (fcob *FCOB) ProcessVoteResult(id string, opinion vote.Opinion) { - transactionID, err := transaction.IDFromBase58(id) +func (fcob *FCOB) ProcessVoteResult(ev *vote.OpinionEvent) { + transactionID, err := transaction.IDFromBase58(ev.ID) if err != nil { fcob.Events.Error.Trigger(err) return } - if _, err := fcob.tangle.SetTransactionPreferred(transactionID, opinion == vote.Like); err != nil { + if _, err := fcob.tangle.SetTransactionPreferred(transactionID, ev.Opinion == vote.Like); err != nil { fcob.Events.Error.Trigger(err) } } diff --git a/packages/vote/fpc/fpc.go b/packages/vote/fpc/fpc.go index 63deecd3..62571445 100644 --- a/packages/vote/fpc/fpc.go +++ b/packages/vote/fpc/fpc.go @@ -170,12 +170,12 @@ func (f *FPC) finalizeOpinions() { defer f.ctxsMu.Unlock() for id, voteCtx := range f.ctxs { if voteCtx.IsFinalized(f.paras.CoolingOffPeriod, f.paras.FinalizationThreshold) { - f.events.Finalized.Trigger(id, voteCtx.LastOpinion()) + f.events.Finalized.Trigger(&vote.OpinionEvent{ID: id, Opinion: voteCtx.LastOpinion(), Ctx: *voteCtx}) delete(f.ctxs, id) continue } if voteCtx.Rounds >= f.paras.MaxRoundsPerVoteContext { - f.events.Failed.Trigger(id, voteCtx.LastOpinion()) + f.events.Failed.Trigger(&vote.OpinionEvent{ID: id, Opinion: voteCtx.LastOpinion(), Ctx: *voteCtx}) delete(f.ctxs, id) } } diff --git a/packages/vote/fpc/fpc_test.go b/packages/vote/fpc/fpc_test.go index 3fe0d7f4..58488bdc 100644 --- a/packages/vote/fpc/fpc_test.go +++ b/packages/vote/fpc/fpc_test.go @@ -96,8 +96,8 @@ func TestFPCFinalizedEvent(t *testing.T) { paras.QuerySampleSize = 1 voter := fpc.New(opinionGiverFunc, paras) var finalizedOpinion *vote.Opinion - voter.Events().Finalized.Attach(events.NewClosure(func(id string, opinion vote.Opinion) { - finalizedOpinion = &opinion + voter.Events().Finalized.Attach(events.NewClosure(func(ev *vote.OpinionEvent) { + finalizedOpinion = &ev.Opinion })) assert.NoError(t, voter.Vote(id, vote.Like)) @@ -129,8 +129,8 @@ func TestFPCFailedEvent(t *testing.T) { paras.FinalizationThreshold = 4 voter := fpc.New(opinionGiverFunc, paras) var failedOpinion *vote.Opinion - voter.Events().Failed.Attach(events.NewClosure(func(id string, opinion vote.Opinion) { - failedOpinion = &opinion + voter.Events().Failed.Attach(events.NewClosure(func(ev *vote.OpinionEvent) { + failedOpinion = &ev.Opinion })) assert.NoError(t, voter.Vote(id, vote.Like)) @@ -170,8 +170,8 @@ func TestFPCVotingMultipleOpinionGivers(t *testing.T) { paras.CoolingOffPeriod = 2 voter := fpc.New(opinionGiverFunc, paras) var finalOpinion *vote.Opinion - voter.Events().Finalized.Attach(events.NewClosure(func(id string, finalizedOpinion vote.Opinion) { - finalOpinion = &finalizedOpinion + voter.Events().Finalized.Attach(events.NewClosure(func(ev *vote.OpinionEvent) { + finalOpinion = &ev.Opinion })) assert.NoError(t, voter.Vote(test.id, test.initOpinion)) diff --git a/packages/vote/net/server.go b/packages/vote/net/server.go index 6a0f34ba..3e9c621a 100644 --- a/packages/vote/net/server.go +++ b/packages/vote/net/server.go @@ -46,6 +46,7 @@ func (vs *VoterServer) Opinion(ctx context.Context, req *QueryRequest) (*QueryRe reply.Opinion[i] = int32(vs.opnRetriever(id)) } + // trigger metrics event metrics.Events().FPCInboundBytes.Trigger(proto.Size(req)) metrics.Events().FPCOutboundBytes.Trigger(proto.Size(reply)) return reply, nil diff --git a/packages/vote/voter.go b/packages/vote/voter.go index af77cbe1..cceda87b 100644 --- a/packages/vote/voter.go +++ b/packages/vote/voter.go @@ -57,9 +57,19 @@ type RoundStats struct { QueriedOpinions []QueriedOpinions `json:"queried_opinions"` } -// OpinionCaller calls the given handler with an Opinion and its associated ID. +// OpinionEvent is the struct containing data to be passed around with Finalized and Failed events. +type OpinionEvent struct { + // ID is the of the conflict + ID string + // Opinion is an opinion about a conflict + Opinion Opinion + // Ctx contains all relevant infos regarding the conflict. + Ctx Context +} + +// OpinionCaller calls the given handler with an OpinionEvent (containing its opinions, its associated ID and context). func OpinionCaller(handler interface{}, params ...interface{}) { - handler.(func(id string, opinion Opinion))(params[0].(string), params[1].(Opinion)) + handler.(func(ev *OpinionEvent))(params[0].(*OpinionEvent)) } // RoundStats calls the given handler with a RoundStats. -- GitLab