From 08d1d6012558051744ad169c2229cb1ceaf596a7 Mon Sep 17 00:00:00 2001 From: David Florness Date: Sun, 17 Jan 2021 19:16:34 -0500 Subject: [PATCH] Retrieve create election event if we haven't seen it yet Order with /sync can be pretty unpredictable --- cmd/tallyard/main.go | 12 ++++----- election/map.go | 13 ++++++++++ election/msg.go | 59 ++++++++++++++++++++++++++++++++------------ 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/cmd/tallyard/main.go b/cmd/tallyard/main.go index 9b9bfbc..c992627 100644 --- a/cmd/tallyard/main.go +++ b/cmd/tallyard/main.go @@ -60,27 +60,27 @@ func main() { syncer.OnEvent(client.Store.(*mautrix.InMemoryStore).UpdateState) syncer.OnEventType(election.CreateElectionMessage, func(source mautrix.EventSource, evt *event.Event) { DebugCB(source, evt) - election.OnCreateElectionMessage(source, evt, elections) + election.OnCreateElectionMessage(evt, elections) }) syncer.OnEventType(election.JoinElectionMessage, func(source mautrix.EventSource, evt *event.Event) { DebugCB(source, evt) - election.OnJoinElectionMessage(source, evt, elections) + election.OnJoinElectionMessage(client, evt, elections) }) syncer.OnEventType(election.StartElectionMessage, func(source mautrix.EventSource, evt *event.Event) { DebugCB(source, evt) - election.OnStartElectionMessage(source, evt, elections) + election.OnStartElectionMessage(client, evt, elections) }) syncer.OnEventType(election.EvalMessage, func(source mautrix.EventSource, evt *event.Event) { DebugCB(source, evt) - election.OnEvalMessage(source, evt, elections, data.LocalVoter) + election.OnEvalMessage(client, evt, elections, data.LocalVoter) }) syncer.OnEventType(election.SumMessage, func(source mautrix.EventSource, evt *event.Event) { DebugCB(source, evt) - election.OnSumMessage(source, evt, elections) + election.OnSumMessage(client, evt, elections) }) syncer.OnEventType(election.ResultMessage, func(source mautrix.EventSource, evt *event.Event) { DebugCB(source, evt) - election.OnResultMessage(source, evt, elections) + election.OnResultMessage(client, evt, elections) }) go func() { diff --git a/election/map.go b/election/map.go index ad23435..1eff491 100644 --- a/election/map.go +++ b/election/map.go @@ -36,7 +36,20 @@ func (em *ElectionsMap) GetOk(eventID id.EventID) (*Election, bool) { func (em *ElectionsMap) Set(eventID id.EventID, el *Election) { em.Lock() defer em.Unlock() + em.set(eventID, el) +} + +func (em *ElectionsMap) SetIfNotExists(eventID id.EventID, el *Election) { + em.Lock() + defer em.Unlock() + _, exists := em.M[eventID] + if exists { + return + } + em.set(eventID, el) +} +func (em *ElectionsMap) set(eventID id.EventID, el *Election) { em.M[eventID] = el i := sort.Search(len(em.L), func(i int) bool { diff --git a/election/msg.go b/election/msg.go index dbf7194..47c4807 100644 --- a/election/msg.go +++ b/election/msg.go @@ -87,18 +87,37 @@ func init() { event.TypeMap[ResultMessage] = reflect.TypeOf(ResultMessageContent{}) } -func OnCreateElectionMessage(source mautrix.EventSource, evt *event.Event, elections *ElectionsMap) { +func OnCreateElectionMessage(evt *event.Event, elections *ElectionsMap) { // TODO: check version content, ok := evt.Content.Parsed.(*CreateElectionContent) if !ok { log.Warnf("ignoring %s's create since we couldn't cast message content to CreateElectionContent", evt.Sender) return } - elections.Set(evt.ID, NewElection(content.Candidates, evt.ID, + elections.SetIfNotExists(evt.ID, NewElection(content.Candidates, evt.ID, evt.Timestamp, evt.Sender, evt.RoomID, false, content.Title)) } -func OnJoinElectionMessage(source mautrix.EventSource, evt *event.Event, elections *ElectionsMap) { +func getElection(client *mautrix.Client, roomID id.RoomID, createEventId id.EventID, elections *ElectionsMap) *Election { + el, exists := elections.GetOk(createEventId) + if exists { + return el + } + createEvent, err := client.GetEvent(roomID, createEventId) + if err != nil { + log.Warnf("couldn't retrieve election create event: %s", err) + return nil + } + OnCreateElectionMessage(createEvent, elections) + el, exists = elections.GetOk(createEventId) + if !exists { + log.Warnf("couldn't create election") + return nil + } + return el +} + +func OnJoinElectionMessage(client *mautrix.Client, evt *event.Event, elections *ElectionsMap) { content, ok := evt.Content.Parsed.(*JoinElectionContent) if !ok { log.Warnf("ignoring %s's join since we couldn't cast message content to JoinElectionContent", evt.Sender) @@ -110,8 +129,8 @@ func OnJoinElectionMessage(source mautrix.EventSource, evt *event.Event, electio return } input := new(big.Int).SetBytes(bytes) - el, exists := elections.GetOk(content.CreateEventId) - if !exists { + el := getElection(client, evt.RoomID, content.CreateEventId, elections) + if el == nil { log.Warnf("ignoring %s's join since the election doesn't exist", evt.Sender) return } @@ -132,15 +151,14 @@ func OnJoinElectionMessage(source mautrix.EventSource, evt *event.Event, electio el.Voters[evt.Sender] = NewVoter(evt.Sender, input, &pubKey) } -func OnStartElectionMessage(source mautrix.EventSource, evt *event.Event, elections *ElectionsMap) { +func OnStartElectionMessage(client *mautrix.Client, evt *event.Event, elections *ElectionsMap) { content, ok := evt.Content.Parsed.(*StartElectionContent) if !ok { log.Warnf("ignoring %s's election start since we couldn't cast message content to StartElectionContent", evt.Sender) return } - // TODO ensure election exists - el, exists := elections.GetOk(content.CreateEventId) - if !exists { + el := getElection(client, evt.RoomID, content.CreateEventId, elections) + if el == nil { log.Warnf("ignoring %s's election start since the election doesn't exist", evt.Sender) return } @@ -154,7 +172,7 @@ func OnStartElectionMessage(source mautrix.EventSource, evt *event.Event, electi el.Started = true } -func OnEvalMessage(source mautrix.EventSource, evt *event.Event, elections *ElectionsMap, localVoter *LocalVoter) { +func OnEvalMessage(client *mautrix.Client, evt *event.Event, elections *ElectionsMap, localVoter *LocalVoter) { content, ok := evt.Content.Parsed.(*EvalMessageContent) if !ok { log.Warn("ignoring %s's eval message since we couldn't cast message content to EvalMessageContent", evt.Sender) @@ -170,8 +188,8 @@ func OnEvalMessage(source mautrix.EventSource, evt *event.Event, elections *Elec log.Errorf("couldn't decode %s's encrypted output: %s", evt.Sender, err) return } - el, exists := elections.GetOk(content.CreateEventId) - if !exists { + el := getElection(client, evt.RoomID, content.CreateEventId, elections) + if el == nil { log.Warnf("ignoring %s's eval message since the election doesn't exist", evt.Sender) return } @@ -195,7 +213,7 @@ func OnEvalMessage(source mautrix.EventSource, evt *event.Event, elections *Elec voter.Output = new(big.Int).SetBytes(decryptedOutput) } -func OnSumMessage(source mautrix.EventSource, evt *event.Event, elections *ElectionsMap) { +func OnSumMessage(client *mautrix.Client, evt *event.Event, elections *ElectionsMap) { content, ok := evt.Content.Parsed.(*SumMessageContent) if !ok { log.Warnf("ignoring %s's sum since we couldn't cast message content to SumMessageContent", evt.Sender) @@ -206,14 +224,18 @@ func OnSumMessage(source mautrix.EventSource, evt *event.Event, elections *Elect log.Warnf("ignoring %s's sum since we couldn't base64 decode the sum", evt.Sender) return } - el := elections.Get(content.CreateEventId) + el := getElection(client, evt.RoomID, content.CreateEventId, elections) + if el == nil { + log.Warnf("ignoring %s's sum since the election does not exist", evt.Sender) + return + } el.Lock() defer el.Unlock() voter := el.Voters[evt.Sender] voter.Sum = sum } -func OnResultMessage(source mautrix.EventSource, evt *event.Event, elections *ElectionsMap) { +func OnResultMessage(client *mautrix.Client, evt *event.Event, elections *ElectionsMap) { content, ok := evt.Content.Parsed.(*ResultMessageContent) if !ok { log.Warnf("ignoring %s's result since we couldn't cast message content to ResultMessageContent", evt.Sender) @@ -224,9 +246,14 @@ func OnResultMessage(source mautrix.EventSource, evt *event.Event, elections *El log.Warnf("ignoring %s's result since we couldn't base64 decode the result", evt.Sender) return } - el := elections.Get(content.CreateEventId) + el := getElection(client, evt.RoomID, content.CreateEventId, elections) + if el == nil { + log.Warnf("ignoring %s's result since the election does not exist", evt.Sender) + return + } el.Lock() defer el.Unlock() + // TODO check that voter exists voter := el.Voters[evt.Sender] voter.Result = result } -- 2.38.4