Merge pull request #6056 from ostcar/performance_assignment_poll
Performance assignment poll
This commit is contained in:
commit
382fcf4a67
1
performance/.gitignore
vendored
1
performance/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/performance
|
||||
.vscode
|
||||
|
@ -14,7 +14,7 @@ const pathLogin = "/apps/users/login/"
|
||||
|
||||
// Client can send requests to the server.
|
||||
type Client struct {
|
||||
domain string
|
||||
addr string
|
||||
hc *http.Client
|
||||
username, password string
|
||||
|
||||
@ -22,9 +22,9 @@ type Client struct {
|
||||
}
|
||||
|
||||
// New creates a client object. No requests are sent.
|
||||
func New(domain, username, password string, options ...Option) (*Client, error) {
|
||||
func New(addr, username, password string, options ...Option) (*Client, error) {
|
||||
c := &Client{
|
||||
domain: "https://" + domain,
|
||||
addr: addr,
|
||||
username: username,
|
||||
password: password,
|
||||
loginRetry: 1,
|
||||
@ -51,7 +51,7 @@ func New(domain, username, password string, options ...Option) (*Client, error)
|
||||
// Login uses the username and password to login the client. Sets the returned
|
||||
// cookie for later requests.
|
||||
func (c *Client) Login() error {
|
||||
url := c.domain + pathLogin
|
||||
url := c.addr + pathLogin
|
||||
payload := fmt.Sprintf(`{"username": "%s", "password": "%s"}`, c.username, c.password)
|
||||
|
||||
var err error
|
||||
@ -70,7 +70,7 @@ func (c *Client) Login() error {
|
||||
}
|
||||
|
||||
func (c *Client) get(ctx context.Context, path string) error {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", c.domain+path, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", c.addr+path, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating request: %w", err)
|
||||
|
||||
|
@ -47,7 +47,7 @@ func cmdBrowser(cfg *config) *cobra.Command {
|
||||
|
||||
clients := make([]*client.Client, clientCount)
|
||||
for i := range clients {
|
||||
c, err := client.New(cfg.domain, cfg.username, cfg.password)
|
||||
c, err := client.New(cfg.addr(), cfg.username, cfg.password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
@ -60,7 +60,7 @@ func cmdBrowser(cfg *config) *cobra.Command {
|
||||
wg.Add(1)
|
||||
go func(c *client.Client) {
|
||||
defer wg.Done()
|
||||
if err := browser(cfg.domain, c, bar); err != nil {
|
||||
if err := browser(cfg.addr(), c, bar); err != nil {
|
||||
log.Printf("Client failed: %v", err)
|
||||
}
|
||||
}(c)
|
||||
@ -76,7 +76,7 @@ func cmdBrowser(cfg *config) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func browser(domain string, c *client.Client, bar *mpb.Bar) error {
|
||||
func browser(url string, c *client.Client, bar *mpb.Bar) error {
|
||||
if err := c.Login(); err != nil {
|
||||
return fmt.Errorf("login client: %w", err)
|
||||
}
|
||||
@ -94,7 +94,7 @@ func browser(domain string, c *client.Client, bar *mpb.Bar) error {
|
||||
go func(path string) {
|
||||
defer wg.Done()
|
||||
|
||||
req, err := http.NewRequest("GET", "https://"+domain+path, nil)
|
||||
req, err := http.NewRequest("GET", url+path, nil)
|
||||
if err != nil {
|
||||
log.Printf("Error creating request: %v", err)
|
||||
return
|
||||
|
@ -48,7 +48,7 @@ func cmdConnect(cfg *config) *cobra.Command {
|
||||
|
||||
path := "/system/autoupdate"
|
||||
|
||||
c, err := client.New(cfg.domain, cfg.username, cfg.password)
|
||||
c, err := client.New(cfg.addr(), cfg.username, cfg.password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
@ -62,7 +62,7 @@ func cmdConnect(cfg *config) *cobra.Command {
|
||||
|
||||
for i := 0; i < connectionCount; i++ {
|
||||
go func() {
|
||||
r, err := keepOpen(cfg.domain, c, path)
|
||||
r, err := keepOpen(cfg.addr(), c, path)
|
||||
if err != nil {
|
||||
log.Println("Can not create connection: %w", err)
|
||||
return
|
||||
@ -70,7 +70,8 @@ func cmdConnect(cfg *config) *cobra.Command {
|
||||
defer r.Close()
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Buffer(make([]byte, 10), 1_000_000)
|
||||
const MB = 1 << 20
|
||||
scanner.Buffer(make([]byte, 10), 16*MB)
|
||||
for scanner.Scan() {
|
||||
msg, err := scannerAutoupdate(scanner.Text())
|
||||
if err != nil {
|
||||
@ -86,7 +87,7 @@ func cmdConnect(cfg *config) *cobra.Command {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return
|
||||
}
|
||||
log.Println("Can not read body: %w", err)
|
||||
log.Printf("Can not read body: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -115,8 +116,8 @@ func cmdConnect(cfg *config) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func keepOpen(domain string, c *client.Client, path string) (io.ReadCloser, error) {
|
||||
req, err := http.NewRequest("GET", "https://"+domain+path, nil)
|
||||
func keepOpen(url string, c *client.Client, path string) (io.ReadCloser, error) {
|
||||
req, err := http.NewRequest("GET", url+path, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating request: %w", err)
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func cmdCreateAmendments(cfg *config) *cobra.Command {
|
||||
Short: "Creates a motion with amendments.",
|
||||
Long: helpCreateAmendments,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := client.New(cfg.domain, cfg.username, cfg.password)
|
||||
c, err := client.New(cfg.addr(), cfg.username, cfg.password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
@ -31,15 +31,13 @@ func cmdCreateAmendments(cfg *config) *cobra.Command {
|
||||
return fmt.Errorf("login client: %w", err)
|
||||
}
|
||||
|
||||
addr := "https://" + cfg.domain
|
||||
|
||||
motionID, err := createMotion(c, addr, amendmentAmount)
|
||||
motionID, err := createMotion(c, cfg.addr(), amendmentAmount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create motion: %w", err)
|
||||
}
|
||||
|
||||
for i := 0; i < amendmentAmount; i++ {
|
||||
createAmendment(c, addr, motionID, i)
|
||||
createAmendment(c, cfg.addr(), motionID, i)
|
||||
}
|
||||
|
||||
fmt.Println(motionID)
|
||||
|
130
performance/cmd/create_candidates.go
Normal file
130
performance/cmd/create_candidates.go
Normal file
@ -0,0 +1,130 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenSlides/OpenSlides/performance/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const helpCreateCandidates = `Creates candidates to an assignment
|
||||
|
||||
This command can be used to test assignment votes.
|
||||
`
|
||||
|
||||
func cmdCreateCandidates(cfg *config) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "create_candidates",
|
||||
Short: "Creates candidates to an assignment",
|
||||
Long: helpCreateCandidates,
|
||||
}
|
||||
|
||||
amount := cmd.Flags().IntP("amount", "a", 10, "amount of candidates to add")
|
||||
assignmentID := cmd.Flags().Int("assignment_id", 0, "assignment where the candidates are created")
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
c, err := client.New(cfg.addr(), cfg.username, cfg.password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
|
||||
if err := c.Login(); err != nil {
|
||||
return fmt.Errorf("login client: %w", err)
|
||||
}
|
||||
|
||||
uids, err := userIDs(cfg, c, *amount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting userIDs: %w", err)
|
||||
}
|
||||
|
||||
for _, id := range uids {
|
||||
if err := createCandidate(c, cfg.addr(), *assignmentID, id); err != nil {
|
||||
return fmt.Errorf("create candidate for uid %d: %w", id, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func createCandidate(c *client.Client, addr string, assignmentID int, userID int) error {
|
||||
req, err := http.NewRequest(
|
||||
"POST",
|
||||
fmt.Sprintf("%s/rest/assignments/assignment/%d/candidature_other/", addr, assignmentID),
|
||||
strings.NewReader(fmt.Sprintf(`{"user":%d}`, userID)),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
if _, err := client.CheckStatus(c.Do(req)); err != nil {
|
||||
return fmt.Errorf("sending request: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func userIDs(cfg *config, c *client.Client, amount int) ([]int, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/system/autoupdate", cfg.addr()), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating fetching all request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sending fetch all request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
body = []byte(fmt.Sprintf("[can not read body: %v", err))
|
||||
}
|
||||
return nil, fmt.Errorf("got status %s: %s", resp.Status, body)
|
||||
}
|
||||
|
||||
// First message is a connection info. Throw it away.
|
||||
var devNull json.RawMessage
|
||||
if err := json.NewDecoder(resp.Body).Decode(&devNull); err != nil {
|
||||
return nil, fmt.Errorf("decoding response: %w", err)
|
||||
}
|
||||
|
||||
var content struct {
|
||||
Changed map[string][]json.RawMessage `json:"changed"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&content); err != nil {
|
||||
return nil, fmt.Errorf("decoding response: %w", err)
|
||||
}
|
||||
|
||||
users := content.Changed["users/user"]
|
||||
if len(users) == 0 {
|
||||
return nil, fmt.Errorf("no users found")
|
||||
}
|
||||
|
||||
var ids []int
|
||||
for i, u := range users {
|
||||
var user struct {
|
||||
ID int `json:"id"`
|
||||
UserName string `json:"username"`
|
||||
}
|
||||
if err := json.Unmarshal(u, &user); err != nil {
|
||||
return nil, fmt.Errorf("decoding %dth user: %w", i, err)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(user.UserName, "dummy") {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, user.ID)
|
||||
if len(ids) >= amount {
|
||||
return ids, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("could not find %d dummy users", amount)
|
||||
}
|
@ -31,7 +31,7 @@ func cmdCreateUsers(cfg *config) *cobra.Command {
|
||||
Short: "Create a lot of users.",
|
||||
Long: createUsersHelp,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := client.New(cfg.domain, cfg.username, cfg.password)
|
||||
c, err := client.New(cfg.addr(), cfg.username, cfg.password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
@ -57,7 +57,7 @@ func cmdCreateUsers(cfg *config) *cobra.Command {
|
||||
return fmt.Errorf("encoding users: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", "https://"+cfg.domain+"/rest/users/user/mass_import/", bytes.NewReader(bs))
|
||||
req, err := http.NewRequest("POST", cfg.addr()+"/rest/users/user/mass_import/", bytes.NewReader(bs))
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating mass import request: %w", err)
|
||||
}
|
||||
|
@ -12,18 +12,29 @@ type config struct {
|
||||
domain string
|
||||
username string
|
||||
password string
|
||||
http bool
|
||||
}
|
||||
|
||||
func (c *config) addr() string {
|
||||
proto := "https"
|
||||
if c.http {
|
||||
proto = "http"
|
||||
}
|
||||
return proto + "://" + c.domain
|
||||
}
|
||||
|
||||
func cmdRoot(cfg *config) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "performance",
|
||||
Short: "performance is a tool that brings OpenSlides to its limit.",
|
||||
Long: rootHelp,
|
||||
Use: "performance",
|
||||
Short: "performance is a tool that brings OpenSlides to its limit.",
|
||||
Long: rootHelp,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVarP(&cfg.domain, "domain", "d", "localhost:8000", "Domain where to send the requests")
|
||||
cmd.PersistentFlags().StringVarP(&cfg.username, "username", "u", "admin", "Username that can create the users.")
|
||||
cmd.PersistentFlags().StringVarP(&cfg.password, "password", "p", "admin", "Password to use.")
|
||||
cmd.PersistentFlags().BoolVar(&cfg.http, "http", false, "Use http instead of https. Default is https.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -38,6 +49,7 @@ func Execute() error {
|
||||
cmdCreateUsers(cfg),
|
||||
cmdVotes(cfg),
|
||||
cmdCreateAmendments(cfg),
|
||||
cmdCreateCandidates(cfg),
|
||||
)
|
||||
|
||||
return cmd.Execute()
|
||||
|
@ -2,10 +2,13 @@ package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -20,68 +23,153 @@ const voteHelp = `Sends many votes from different users.
|
||||
This command requires, that there are many user created at the
|
||||
backend. You can use the command "create_users" for this job.
|
||||
|
||||
Per default, the command uses the new url to the autoupdate-service.
|
||||
To test the url from the python-server, you can use the flag "old_url".`
|
||||
Example:
|
||||
|
||||
performance votes motion --amount 100 --poll_id 42
|
||||
|
||||
performance votes assignment --amount 100 --poll_id 42
|
||||
|
||||
`
|
||||
|
||||
func cmdVotes(cfg *config) *cobra.Command {
|
||||
var (
|
||||
count int
|
||||
pollID int
|
||||
oldURL bool
|
||||
interrupt bool
|
||||
loginRetry int
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "votes",
|
||||
Short: "Sends many votes from different users",
|
||||
Long: voteHelp,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
url := "https://%s/system/vote/motion/%d"
|
||||
if oldURL {
|
||||
url = "https://%s/rest/motions/motion-poll/%d/vote/"
|
||||
}
|
||||
url = fmt.Sprintf(url, cfg.domain, pollID)
|
||||
|
||||
return sendVotes(url, cfg.domain, count, interrupt, loginRetry)
|
||||
},
|
||||
Use: "votes",
|
||||
Short: "Sends many votes from different users",
|
||||
ValidArgs: []string{"motion", "assignment", "m", "a"},
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
Long: voteHelp,
|
||||
}
|
||||
|
||||
cmd.Flags().IntVarP(&count, "amount", "a", 10, "Amount of users to use.")
|
||||
cmd.Flags().IntVarP(&pollID, "poll_id", "i", 1, "ID of the poll to use.")
|
||||
cmd.Flags().BoolVarP(&oldURL, "old_url", "o", false, "Use old url to python.")
|
||||
cmd.Flags().BoolVar(&interrupt, "interrupt", false, "Wait for a user input after login.")
|
||||
cmd.Flags().IntVarP(&loginRetry, "login_retry", "r", 3, "Retries send login requests before returning an error.")
|
||||
amount := cmd.Flags().IntP("amount", "n", 10, "Amount of users to use.")
|
||||
pollID := cmd.Flags().IntP("poll_id", "i", 1, "ID of the poll to use.")
|
||||
interrupt := cmd.Flags().Bool("interrupt", false, "Wait for a user input after login.")
|
||||
loginRetry := cmd.Flags().IntP("login_retry", "r", 3, "Retries send login requests before returning an error.")
|
||||
choice := cmd.Flags().IntP("choice", "c", 0, "Amount of answers per vote.")
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
var assignment bool
|
||||
if args[0] == "assignment" || args[0] == "a" {
|
||||
assignment = true
|
||||
}
|
||||
|
||||
url := "%s/rest/motions/motion-poll/%d/vote/"
|
||||
vote := `{"data":"Y"}`
|
||||
if assignment {
|
||||
url = "%s/rest/assignments/assignment-poll/%d/vote/"
|
||||
options, err := assignmentPollOptions(cfg.addr(), *pollID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetch options: %w", err)
|
||||
}
|
||||
|
||||
votedata := make(map[string]int)
|
||||
for i, o := range options {
|
||||
if *choice != 0 && i >= *choice {
|
||||
break
|
||||
}
|
||||
votedata[strconv.Itoa(o)] = 1
|
||||
}
|
||||
|
||||
decoded, err := json.Marshal(votedata)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decoding assignment option data: %w", err)
|
||||
}
|
||||
|
||||
vote = fmt.Sprintf(`{"data":%s}`, decoded)
|
||||
}
|
||||
url = fmt.Sprintf(url, cfg.addr(), *pollID)
|
||||
|
||||
var clients []*client.Client
|
||||
for i := 0; i < *amount; i++ {
|
||||
c, err := client.New(cfg.addr(), fmt.Sprintf("dummy%d", i+1), "pass", client.WithLoginRetry(*loginRetry))
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
clients = append(clients, c)
|
||||
}
|
||||
|
||||
log.Printf("Login %d clients", *amount)
|
||||
start := time.Now()
|
||||
massLogin(clients, *loginRetry)
|
||||
log.Printf("All clients logged in %v", time.Now().Sub(start))
|
||||
|
||||
if *interrupt {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Println("Hit enter to continue")
|
||||
reader.ReadString('\n')
|
||||
log.Println("Starting voting")
|
||||
}
|
||||
|
||||
start = time.Now()
|
||||
massVotes(clients, url, vote)
|
||||
log.Printf("All Clients have voted in %v", time.Now().Sub(start))
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func sendVotes(url string, domain string, count int, interrupt bool, loginRetry int) error {
|
||||
var clients []*client.Client
|
||||
for i := 0; i < count; i++ {
|
||||
c, err := client.New(domain, fmt.Sprintf("dummy%d", i+1), "pass", client.WithLoginRetry(loginRetry))
|
||||
func assignmentPollOptions(addr string, pollID int) ([]int, error) {
|
||||
c, err := client.New(addr, "dummy1", "pass")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating admin client: %w", err)
|
||||
}
|
||||
|
||||
if err := c.Login(); err != nil {
|
||||
return nil, fmt.Errorf("login admin client: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/system/autoupdate", addr), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating fetching all request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sending fetch all request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating client: %w", err)
|
||||
body = []byte(fmt.Sprintf("[can not read body: %v", err))
|
||||
}
|
||||
clients = append(clients, c)
|
||||
return nil, fmt.Errorf("got status %s: %s", resp.Status, body)
|
||||
}
|
||||
|
||||
log.Printf("Login %d clients", count)
|
||||
start := time.Now()
|
||||
massLogin(clients, loginRetry)
|
||||
log.Printf("All clients logged in %v", time.Now().Sub(start))
|
||||
|
||||
if interrupt {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Println("Hit enter to continue")
|
||||
reader.ReadString('\n')
|
||||
log.Println("Starting voting")
|
||||
// First message is a connection info. Throw it away.
|
||||
var devNull json.RawMessage
|
||||
if err := json.NewDecoder(resp.Body).Decode(&devNull); err != nil {
|
||||
return nil, fmt.Errorf("decoding response: %w", err)
|
||||
}
|
||||
|
||||
start = time.Now()
|
||||
massVotes(clients, url)
|
||||
log.Printf("All Clients have voted in %v", time.Now().Sub(start))
|
||||
return nil
|
||||
var content struct {
|
||||
Changed map[string][]json.RawMessage `json:"changed"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&content); err != nil {
|
||||
return nil, fmt.Errorf("decoding response: %w", err)
|
||||
}
|
||||
|
||||
polls := content.Changed["assignments/assignment-poll"]
|
||||
if len(polls) == 0 {
|
||||
return nil, fmt.Errorf("no polls found")
|
||||
}
|
||||
|
||||
for i, p := range polls {
|
||||
var poll struct {
|
||||
ID int `json:"id"`
|
||||
OptionIDs []int `json:"options_id"`
|
||||
}
|
||||
if err := json.Unmarshal(p, &poll); err != nil {
|
||||
return nil, fmt.Errorf("decoding %dth poll: %w", i, err)
|
||||
}
|
||||
if poll.ID != pollID {
|
||||
continue
|
||||
}
|
||||
return poll.OptionIDs, nil
|
||||
}
|
||||
return nil, fmt.Errorf("no assignment-poll with id %d", pollID)
|
||||
}
|
||||
|
||||
func massLogin(clients []*client.Client, tries int) {
|
||||
@ -105,7 +193,7 @@ func massLogin(clients []*client.Client, tries int) {
|
||||
progress.Wait()
|
||||
}
|
||||
|
||||
func massVotes(clients []*client.Client, url string) {
|
||||
func massVotes(clients []*client.Client, url string, vote string) {
|
||||
var wgVote sync.WaitGroup
|
||||
progress := mpb.New(mpb.WithWaitGroup(&wgVote))
|
||||
voteBar := progress.AddBar(int64(len(clients)))
|
||||
@ -114,8 +202,7 @@ func massVotes(clients []*client.Client, url string) {
|
||||
go func(c *client.Client) {
|
||||
defer wgVote.Done()
|
||||
|
||||
body := `{"data":"Y"}`
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(body))
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(vote))
|
||||
if err != nil {
|
||||
log.Printf("Error creating request: %v", err)
|
||||
return
|
||||
@ -124,7 +211,7 @@ func massVotes(clients []*client.Client, url string) {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
if _, err := client.CheckStatus(c.Do(req)); err != nil {
|
||||
log.Printf("Error sending vote request: %v", err)
|
||||
log.Printf("Error sending vote request to %s: %v", url, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user