~edwargix/tallyard

08d1d6012558051744ad169c2229cb1ceaf596a7 — David Florness 4 years ago abd5ff0
Retrieve create election event if we haven't seen it yet

Order with /sync can be pretty unpredictable
3 files changed, 62 insertions(+), 22 deletions(-)

M cmd/tallyard/main.go
M election/map.go
M election/msg.go
M cmd/tallyard/main.go => cmd/tallyard/main.go +6 -6
@@ 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() {

M election/map.go => election/map.go +13 -0
@@ 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 {

M election/msg.go => election/msg.go +43 -16
@@ 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
}