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