R7: per-player transports + drop finished games in the load harness
Each virtual player now builds its own edge.Client (its own h2c connection carrying both the Subscribe stream and the Execute calls), instead of every player multiplexing over a single shared http2.Transport. The R2 trip report traced the ~14% transport_error on game.state at 500 players to that single shared transport; per-player connections mirror real clients and isolate the artifact. The assembly burst and the gateway-hammer each get their own client. playTurn now reports when a game has finished so playerLoop drops it from the rotation (slices.DeleteFunc); once no active game remains the player idles while still holding its stream. This stops secondary ops from hammering game_finished on already-ended games (the other R2 harness finding).
This commit is contained in:
@@ -37,6 +37,7 @@ func (d *Driver) assembleCohort(ctx context.Context, cohort []seed.Account, game
|
||||
if len(cohort) < 2 {
|
||||
return nil
|
||||
}
|
||||
c := edge.New(d.gateway) // one client for the assembly burst; players play on their own
|
||||
gamesOf := make(map[string]int, len(cohort))
|
||||
var games []*Game
|
||||
for i := range cohort {
|
||||
@@ -51,7 +52,7 @@ func (d *Driver) assembleCohort(ctx context.Context, cohort []seed.Account, game
|
||||
break
|
||||
}
|
||||
variant := moves.Variants()[rng.Intn(len(moves.Variants()))]
|
||||
g, err := d.assemble(ctx, members, variant)
|
||||
g, err := d.assemble(ctx, c, members, variant)
|
||||
if err != nil {
|
||||
d.log.Debug("assemble game", "err", err)
|
||||
break
|
||||
@@ -85,7 +86,7 @@ func pickMembers(cohort []seed.Account, inviter seed.Account, rng *rand.Rand) []
|
||||
// assemble runs the invitation flow for one game: the inviter (members[0]) invites
|
||||
// the rest, each invitee accepts the pending invitation, and the completing accept
|
||||
// starts the game, which is then located in the inviter's game list.
|
||||
func (d *Driver) assemble(ctx context.Context, members []seed.Account, variant string) (*Game, error) {
|
||||
func (d *Driver) assemble(ctx context.Context, c *edge.Client, members []seed.Account, variant string) (*Game, error) {
|
||||
inviter := members[0]
|
||||
inviteeIDs := make([]string, len(members)-1)
|
||||
for i, m := range members[1:] {
|
||||
@@ -93,7 +94,7 @@ func (d *Driver) assemble(ctx context.Context, members []seed.Account, variant s
|
||||
}
|
||||
|
||||
t0 := time.Now()
|
||||
code, err := d.edge.CreateInvitation(ctx, inviter.Token, inviteeIDs, variant)
|
||||
code, err := c.CreateInvitation(ctx, inviter.Token, inviteeIDs, variant)
|
||||
d.rec.Record("invitation.create", code, time.Since(t0))
|
||||
if err != nil || code != "ok" {
|
||||
return nil, fmt.Errorf("invitation.create: %s", code)
|
||||
@@ -101,7 +102,7 @@ func (d *Driver) assemble(ctx context.Context, members []seed.Account, variant s
|
||||
|
||||
for _, invitee := range members[1:] {
|
||||
t0 = time.Now()
|
||||
list, lc, err := d.edge.ListInvitations(ctx, invitee.Token)
|
||||
list, lc, err := c.ListInvitations(ctx, invitee.Token)
|
||||
d.rec.Record("invitation.list", lc, time.Since(t0))
|
||||
if err != nil || lc != "ok" {
|
||||
return nil, fmt.Errorf("invitation.list: %s", lc)
|
||||
@@ -111,7 +112,7 @@ func (d *Driver) assemble(ctx context.Context, members []seed.Account, variant s
|
||||
return nil, fmt.Errorf("no pending invitation from %s", inviter.ID)
|
||||
}
|
||||
t0 = time.Now()
|
||||
ac, err := d.edge.AcceptInvitation(ctx, invitee.Token, invID)
|
||||
ac, err := c.AcceptInvitation(ctx, invitee.Token, invID)
|
||||
d.rec.Record("invitation.accept", ac, time.Since(t0))
|
||||
if err != nil || ac != "ok" {
|
||||
return nil, fmt.Errorf("invitation.accept: %s", ac)
|
||||
@@ -119,7 +120,7 @@ func (d *Driver) assemble(ctx context.Context, members []seed.Account, variant s
|
||||
}
|
||||
|
||||
t0 = time.Now()
|
||||
games, gc, err := d.edge.GamesList(ctx, inviter.Token)
|
||||
games, gc, err := c.GamesList(ctx, inviter.Token)
|
||||
d.rec.Record("games.list", gc, time.Since(t0))
|
||||
if err != nil || gc != "ok" {
|
||||
return nil, fmt.Errorf("games.list: %s", gc)
|
||||
|
||||
Reference in New Issue
Block a user