Skip to content

Commit

Permalink
Add db transaction to distributed clans write and fix lint errors (#51)
Browse files Browse the repository at this point in the history
* Fix lint errors

* revert

* unnest & use transaction

* add transaction to missing case
  • Loading branch information
cmyui authored Jul 9, 2024
1 parent 9ddad1d commit 7c724d0
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 80 deletions.
115 changes: 64 additions & 51 deletions app/v1/clan.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func ClanLeaderboardGET(md common.MethodData) common.CodeMessager {
for i := 1; rows.Next(); i++ {
clan := clanLbData{}
var pp float64
rows.Scan(&pp, &clan.ChosenMode.RankedScore, &clan.ChosenMode.TotalScore, &clan.ChosenMode.PlayCount, &clan.ChosenMode.Accuracy, &clan.Name, &clan.ID)
err = rows.Scan(&pp, &clan.ChosenMode.RankedScore, &clan.ChosenMode.TotalScore, &clan.ChosenMode.PlayCount, &clan.ChosenMode.Accuracy, &clan.Name, &clan.ID)
if err != nil {
md.Err(err)
return Err500
Expand All @@ -134,8 +134,6 @@ func ClanLeaderboardGET(md common.MethodData) common.CodeMessager {
return r
}

var dbmode = [...]string{"std", "taiko", "ctb", "mania"}

func ClanStatsGET(md common.MethodData) common.CodeMessager {
if md.Query("id") == "" {
return ErrMissingField("id")
Expand Down Expand Up @@ -232,13 +230,6 @@ func ResolveInviteGET(md common.MethodData) common.CodeMessager {
return r
}

func resolveInvite(c string, md *common.MethodData) (id int, err error) {
row := md.DB.QueryRow("SELECT id FROM clans where invite = ?", c)
err = row.Scan(&id)

return
}

func ClanJoinPOST(md common.MethodData) common.CodeMessager {
if md.ID() == 0 {
return common.SimpleResponse(401, "not authorised")
Expand Down Expand Up @@ -272,7 +263,8 @@ func ClanJoinPOST(md common.MethodData) common.CodeMessager {
var hasInvite bool

if u.Invite != "" {
u.ID, err = resolveInvite(u.Invite, &md)
row := md.DB.QueryRow("SELECT id FROM clans where invite = ?", u.Invite)
err = row.Scan(&u.ID)

if err != nil {
if err == sql.ErrNoRows {
Expand All @@ -285,45 +277,65 @@ func ClanJoinPOST(md common.MethodData) common.CodeMessager {
hasInvite = true
}

if u.ID > 0 {
c, err := getClan(u.ID, md)
if err != nil {
if err == sql.ErrNoRows {
return common.SimpleResponse(404, "clan not found")
}
md.Err(err)
return Err500
}
if u.ID <= 0 {
return common.SimpleResponse(400, "invalid id parameter")
}

if c.Status == 0 || (c.Status == 2 && !hasInvite) {
return common.SimpleResponse(403, "closed")
c, err := getClan(u.ID, md)
if err != nil {
if err == sql.ErrNoRows {
return common.SimpleResponse(404, "clan not found")
}
md.Err(err)
return Err500
}

if c.Status == 0 || (c.Status == 2 && !hasInvite) {
return common.SimpleResponse(403, "closed")
}

var count int
err = md.DB.QueryRow("SELECT COUNT(id) FROM users WHERE clan_id = ?", c.ID).Scan(&count)
if err != nil {
md.Err(err)
return Err500
}

if count >= clanMemberLimit {
return common.SimpleResponse(403, "clan is full")
}

tx, err := md.DB.Begin()
if err != nil {
md.Err(err)
return Err500
}

var count int
err = md.DB.QueryRow("SELECT COUNT(id) FROM users WHERE clan_id = ?", c.ID).Scan(&count)
if c.Status == 3 {
_, err = tx.Exec("INSERT INTO clan_requests VALUES (?, ?, DEFAULT) ON DUPLICATE KEY UPDATE time = NOW()", c.ID, md.ID())
if err != nil {
tx.Rollback()
md.Err(err)
return Err500
}

if count >= clanMemberLimit {
return common.SimpleResponse(403, "clan is full")
}
return common.SimpleResponse(200, "join request sent")
}
_, err = tx.Exec("UPDATE users SET clan_id = ? WHERE id = ?", c.ID, md.ID())
if err != nil {
tx.Rollback()
md.Err(err)
return Err500
}

if c.Status == 3 {
_, err = md.DB.Exec("INSERT INTO clan_requests VALUES (?, ?, DEFAULT) ON DUPLICATE KEY UPDATE time = NOW()", c.ID, md.ID())
return common.SimpleResponse(200, "join request sent")
}
_, err = md.DB.Exec("UPDATE users SET clan_id = ? WHERE id = ?", c.ID, md.ID())
r.Clan = c
r.Code = 200
tx.Commit()

md.R.Publish("api:update_user_clan", strconv.Itoa(md.ID()))
r.Clan = c
r.Code = 200

return r
} else {
return common.SimpleResponse(400, "invalid id parameter")
}
md.R.Publish("api:update_user_clan", strconv.Itoa(md.ID()))

return r
}

func ClanLeavePOST(md common.MethodData) common.CodeMessager {
Expand All @@ -346,28 +358,39 @@ func ClanLeavePOST(md common.MethodData) common.CodeMessager {
return Err500
}

tx, err := md.DB.Begin()
if err != nil {
md.Err(err)
return Err500
}

disbanded := false
if clan.Owner == md.ID() {
_, err = md.DB.Exec("UPDATE users SET clan_id = 0 WHERE clan_id = ?", clan.ID)
_, err = tx.Exec("UPDATE users SET clan_id = 0 WHERE clan_id = ?", clan.ID)
if err != nil {
tx.Rollback()
md.Err(err)
return Err500
}

err := disbandClan(clan.ID, md)
if err != nil {
tx.Rollback()
md.Err(err)
return Err500
}
disbanded = true
} else {
_, err := md.DB.Exec("UPDATE users SET clan_id = 0 WHERE id = ?", md.ID())
_, err := tx.Exec("UPDATE users SET clan_id = 0 WHERE id = ?", md.ID())
if err != nil {
tx.Rollback()
md.Err(err)
return Err500
}
}

tx.Commit()

md.R.Publish("api:update_user_clan", strconv.Itoa(md.ID()))

message := "success"
Expand Down Expand Up @@ -597,13 +620,3 @@ func getClan(id int, md common.MethodData) (Clan, error) {

return c, err
}

func getUserData(id int, md common.MethodData) (userData, error) {
u := userData{}
if id == 0 {
return u, nil
}
err := md.DB.QueryRow("SELECT id, username, register_datetime, privileges, latest_activity, username_aka, country FROM users WHERE id = ?", id).Scan(&u.ID, &u.Username, &u.RegisteredOn, &u.Privileges, &u.LatestActivity, &u.UsernameAKA, &u.Country)

return u, err
}
5 changes: 1 addition & 4 deletions app/v1/friend.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,11 @@ AND privileges & 1
}

func friendPuts(md common.MethodData, row *sql.Rows) (user friendData) {
var err error

err = row.Scan(&user.ID, &user.Username, &user.RegisteredOn, &user.Privileges, &user.LatestActivity, &user.UsernameAKA, &user.Country)
err := row.Scan(&user.ID, &user.Username, &user.RegisteredOn, &user.Privileges, &user.LatestActivity, &user.UsernameAKA, &user.Country)
if err != nil {
md.Err(err)
return
}

return
}

Expand Down
24 changes: 0 additions & 24 deletions app/v1/rap.go

This file was deleted.

2 changes: 1 addition & 1 deletion app/v1/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (o *oauthClient) Scan(src interface{}) error {
case []byte:
s = x
default:
return errors.New("Can't scan non-string")
return errors.New("can't scan non-string")
}

var vals [3]string
Expand Down

0 comments on commit 7c724d0

Please sign in to comment.