From d1225d325817a5842542c760105e5b2537e3a918 Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 13 Jan 2025 20:06:55 +0100 Subject: [PATCH] Fix slow-ass code --- cmd/web/handlers.go | 10 +++++----- cmd/web/handlers_test.go | 8 ++++---- cmd/web/main.go | 2 +- cmd/web/testutils_test.go | 6 +++--- internal/models/voters.go | 38 ++++++++++++++++++++++++++++---------- 5 files changed, 41 insertions(+), 23 deletions(-) diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go index 299def8..5e4e574 100644 --- a/cmd/web/handlers.go +++ b/cmd/web/handlers.go @@ -90,12 +90,12 @@ func (app *application) CreateElection(w http.ResponseWriter, r *http.Request) { voterIdentities := make([]string, 0, request.MaxVoters) // TODO: this is way too slow for i := 0; i < request.MaxVoters; i++ { randomIdentity := randomVoterIdentity() - _, err := app.voters.Insert(randomIdentity, electionId) - if err != nil { - app.serverError(w, r, err) - } voterIdentities = append(voterIdentities, randomIdentity) } + _, err := app.voters.InsertMultiple(voterIdentities, electionId) + if err != nil { + app.serverError(w, r, err) + } res, err = json.Marshal(api.CreateElectionResponse{VoterIdentities: &voterIdentities}) if err != nil { @@ -248,7 +248,7 @@ func (app *application) createVotesHandleUnknownVotersElection(w http.ResponseWr return "", fmt.Errorf(message) } - _, err = app.voters.Insert(voterIdentity, election.ID) + _, err = app.voters.InsertMultiple([]string{voterIdentity}, election.ID) if err != nil { app.serverError(w, r, err) return "", err diff --git a/cmd/web/handlers_test.go b/cmd/web/handlers_test.go index 8089c5f..532436e 100644 --- a/cmd/web/handlers_test.go +++ b/cmd/web/handlers_test.go @@ -243,8 +243,8 @@ func TestCreateVotes_UnknownVotersElection(t *testing.T) { On("Exists", mock.Anything, mock.Anything). Return(false, nil) mockVoters. - On("Insert", mock.Anything, mock.Anything). - Return(1, nil) + On("InsertMultiple", mock.Anything, mock.Anything). + Return([]int{1}, nil) mockVoters. On("CountByElection", mock.Anything). Return(0, nil) @@ -634,8 +634,8 @@ func TestCreateVotes_UnknownVotersElectionMaxVotersReached(t *testing.T) { On("Exists", mock.Anything, mock.Anything). Return(false, nil) mockVoters. - On("Insert", mock.Anything, mock.Anything). - Return(1, nil) + On("InsertMultiple", mock.Anything, mock.Anything). + Return([]int{1}, nil) mockVoters. On("CountByElection", mock.Anything). Return(10, nil) diff --git a/cmd/web/main.go b/cmd/web/main.go index 48dc8bc..4ef94cf 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -48,7 +48,7 @@ func main() { Addr: addr, Handler: app.routes(), ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError), - IdleTimeout: 6 * time.Minute, + IdleTimeout: time.Minute, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } diff --git a/cmd/web/testutils_test.go b/cmd/web/testutils_test.go index 9683202..0f1a0d7 100644 --- a/cmd/web/testutils_test.go +++ b/cmd/web/testutils_test.go @@ -62,9 +62,9 @@ type mockVoterModel struct { mock.Mock } -func (v *mockVoterModel) Insert(identity string, electionID int) (int, error) { - args := v.Called(identity, electionID) - return args.Int(0), args.Error(1) +func (v *mockVoterModel) InsertMultiple(identities []string, electionID int) ([]int, error) { + args := v.Called(identities, electionID) + return args.Get(0).([]int), args.Error(1) } func (v *mockVoterModel) CountByElection(electionID int) (int, error) { diff --git a/internal/models/voters.go b/internal/models/voters.go index 6a760a0..48ec18e 100644 --- a/internal/models/voters.go +++ b/internal/models/voters.go @@ -6,7 +6,7 @@ import ( ) type VoterModelInterface interface { - Insert(identity string, electionID int) (int, error) + InsertMultiple(identities []string, electionID int) ([]int, error) CountByElection(electionID int) (int, error) Exists(voterIdentity string, electionID int) (bool, error) } @@ -15,27 +15,45 @@ type VoterModel struct { DB *sql.DB } -func (v *VoterModel) Insert(identity string, electionID int) (int, error) { +func (v *VoterModel) InsertMultiple(identities []string, electionID int) ([]int, error) { tx, err := v.DB.Begin() if err != nil { - return 0, err + return nil, err } defer tx.Rollback() - result, err := tx.Exec(` + // Prepare the statement once to reuse + stmt, err := tx.Prepare(` INSERT INTO voters (identity, election_id) - VALUES (?, ?)`, - identity, electionID) + VALUES (?, ?)`) if err != nil { - return 0, err + return nil, err + } + defer stmt.Close() + + // Store all voter IDs + voterIDs := make([]int, 0, len(identities)) + + // Execute statement for each identity + for _, identity := range identities { + result, err := stmt.Exec(identity, electionID) + if err != nil { + return nil, err + } + + voterID, err := result.LastInsertId() + if err != nil { + return nil, err + } + + voterIDs = append(voterIDs, int(voterID)) } if err = tx.Commit(); err != nil { - return 0, err + return nil, err } - voterId, err := result.LastInsertId() - return int(voterId), nil + return voterIDs, nil } func (v *VoterModel) CountByElection(electionID int) (int, error) {