feat: support verified bulk load-test setup
This commit is contained in:
@@ -29,6 +29,8 @@ type Config struct {
|
||||
P2PInterval string `json:"p2p_interval"`
|
||||
DrainP2P string `json:"drain_p2p"`
|
||||
DrainGroup string `json:"drain_group"`
|
||||
PhonePrefix string `json:"registration_phone_prefix"`
|
||||
VerifyCodeEnv string `json:"verification_code_env"`
|
||||
}
|
||||
|
||||
func loadConfig(path string) (*Config, error) {
|
||||
@@ -75,6 +77,14 @@ func loadConfig(path string) (*Config, error) {
|
||||
return nil, fmt.Errorf("at least one endpoint is required for machine %s", machine)
|
||||
}
|
||||
}
|
||||
if cfg.PhonePrefix != "" {
|
||||
if len(cfg.PhonePrefix) != 7 || strings.Trim(cfg.PhonePrefix, "0123456789") != "" {
|
||||
return nil, errors.New("registration_phone_prefix must contain exactly 7 digits")
|
||||
}
|
||||
if cfg.UsersPerMachine > 4999 {
|
||||
return nil, errors.New("registration phone suffix supports at most 4999 users per machine")
|
||||
}
|
||||
}
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
@@ -102,6 +112,18 @@ func (c *Config) password() (string, error) {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (c *Config) verificationCode() (string, error) {
|
||||
name := c.VerifyCodeEnv
|
||||
if name == "" {
|
||||
name = "IM_VERIFICATION_CODE"
|
||||
}
|
||||
value := strings.TrimSpace(os.Getenv(name))
|
||||
if c.PhonePrefix != "" && value == "" {
|
||||
return "", fmt.Errorf("environment variable %s is required", name)
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func configDuration(value string) (time.Duration, error) {
|
||||
d, err := time.ParseDuration(value)
|
||||
if err != nil || d <= 0 {
|
||||
@@ -122,6 +144,7 @@ type AccountRecord struct {
|
||||
Machine string `json:"machine"`
|
||||
Index int `json:"index"`
|
||||
Username string `json:"username"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
UserID string `json:"user_id"`
|
||||
Token string `json:"token"`
|
||||
TokenExpires time.Time `json:"token_expires,omitempty"`
|
||||
@@ -133,10 +156,12 @@ func newManifest(cfg *Config) *Manifest {
|
||||
m := &Manifest{Version: manifestVersion, Tenant: cfg.Tenant, CreatedAt: time.Now().UTC()}
|
||||
for _, machine := range []string{"a", "b"} {
|
||||
for i := 1; i <= cfg.UsersPerMachine; i++ {
|
||||
phone, _ := registrationPhone(cfg, machine, i)
|
||||
m.Accounts = append(m.Accounts, AccountRecord{
|
||||
Machine: machine,
|
||||
Index: i,
|
||||
Username: fmt.Sprintf("lt%s%04d", machine, i),
|
||||
Phone: phone,
|
||||
Endpoint: cfg.Endpoints[machine][(i-1)%len(cfg.Endpoints[machine])],
|
||||
})
|
||||
}
|
||||
@@ -158,10 +183,54 @@ func applyConfigEndpoints(cfg *Config, manifest *Manifest) error {
|
||||
return fmt.Errorf("invalid endpoint assignment for %s", accountKey(account.Machine, account.Index))
|
||||
}
|
||||
account.Endpoint = endpoints[(account.Index-1)%len(endpoints)]
|
||||
phone, err := registrationPhone(cfg, account.Machine, account.Index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
account.Phone = phone
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func reconcileManifest(cfg *Config, existing *Manifest) (*Manifest, error) {
|
||||
if existing.Tenant != cfg.Tenant {
|
||||
return nil, fmt.Errorf("manifest tenant=%s config tenant=%s", existing.Tenant, cfg.Tenant)
|
||||
}
|
||||
desired := newManifest(cfg)
|
||||
if len(existing.Accounts) > len(desired.Accounts) {
|
||||
return nil, fmt.Errorf("refusing to shrink manifest accounts from %d to %d", len(existing.Accounts), len(desired.Accounts))
|
||||
}
|
||||
desired.GroupTopic = existing.GroupTopic
|
||||
desired.CreatedAt = existing.CreatedAt
|
||||
old := manifestAccountMap(existing)
|
||||
for i := range desired.Accounts {
|
||||
account := &desired.Accounts[i]
|
||||
if previous := old[accountKey(account.Machine, account.Index)]; previous != nil {
|
||||
account.UserID = previous.UserID
|
||||
account.Token = previous.Token
|
||||
account.TokenExpires = previous.TokenExpires
|
||||
account.P2PTopic = previous.P2PTopic
|
||||
}
|
||||
}
|
||||
return desired, nil
|
||||
}
|
||||
|
||||
func registrationPhone(cfg *Config, machine string, index int) (string, error) {
|
||||
if cfg.PhonePrefix == "" {
|
||||
return "", nil
|
||||
}
|
||||
ordinal := index
|
||||
if machine == "b" {
|
||||
ordinal += 5000
|
||||
} else if machine != "a" {
|
||||
return "", fmt.Errorf("invalid machine %q", machine)
|
||||
}
|
||||
if index <= 0 || ordinal > 9999 {
|
||||
return "", fmt.Errorf("invalid phone ordinal %d", ordinal)
|
||||
}
|
||||
return fmt.Sprintf("%s%04d", cfg.PhonePrefix, ordinal), nil
|
||||
}
|
||||
|
||||
func loadManifest(path string) (*Manifest, error) {
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user