-
Notifications
You must be signed in to change notification settings - Fork 1
/
election_background.go
91 lines (86 loc) · 2.73 KB
/
election_background.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main
import (
"context"
"encoding/hex"
"fmt"
"time"
"github.com/vocdoni/vote-frame/mongo"
"go.vocdoni.io/dvote/api"
"go.vocdoni.io/dvote/apiclient"
"go.vocdoni.io/dvote/log"
"go.vocdoni.io/dvote/types"
)
// createApiClientsForElectionRecovery creates a list of API clients that will be used to retrieve the election metadata.
func createApiClientsForElectionRecovery() []*apiclient.HTTPclient {
// Define the API clients that will be used to retrieve the election metadata
apiClientsHost := []string{"https://api.vocdoni.io/v2", "https://api-stg.vocdoni.net/v2", "https://api-dev.vocdoni.net/v2"}
var apiClients []*apiclient.HTTPclient
for _, apiClient := range apiClientsHost {
cli, err := apiclient.New(apiClient)
if err != nil {
log.Errorw(err, "failed to create API client")
continue
}
apiClients = append(apiClients, cli)
}
return apiClients
}
// recoverElectionFromMultipleEndpoints retrieves the election metadata from multiple API endpoints.
// If not found, it returns nil.
func recoverElectionFromMultipleEndpoints(electionID types.HexBytes, apiClients []*apiclient.HTTPclient) *api.Election {
var apiElection *api.Election
var err error
for _, cli := range apiClients {
apiElection, err = cli.Election(electionID)
if err != nil || apiElection == nil {
continue
}
break
}
return apiElection
}
// finalizeElectionsAtBackround checks for elections without results and finalizes them.
// Stores the final results as a static PNG image in the database. It must run in the background.
func finalizeElectionsAtBackround(ctx context.Context, v *vocdoniHandler) {
apiClients := createApiClientsForElectionRecovery()
if len(apiClients) == 0 {
log.Error("failed to create any API client, aborting")
return
}
for {
select {
case <-ctx.Done():
return
case <-time.After(60 * time.Second):
electionIDs, err := v.db.ElectionsWithoutResults()
if err != nil {
if mongo.IsDBClosed(err) {
log.Warn("database client is disconnected")
return
}
log.Errorw(err, "failed to get elections without results")
continue
}
for _, electionID := range electionIDs {
electionIDbytes, err := hex.DecodeString(electionID)
if err != nil {
log.Errorw(err, fmt.Sprintf("failed to decode electionID: %s", electionID))
continue
}
election := recoverElectionFromMultipleEndpoints(electionIDbytes, apiClients)
if election == nil {
continue
}
if election.FinalResults {
electiondb, err := v.db.Election(electionIDbytes)
if err != nil {
continue
}
if _, err = v.finalizeElectionResults(election, electiondb); err != nil {
log.Errorw(err, fmt.Sprintf("failed to finalize election results: %x", electionIDbytes))
}
}
}
}
}
}