Skip to content

Commit eed9536

Browse files
committed
refactor(cli): improve performance for seed_users
1 parent 3a4c8b5 commit eed9536

1 file changed

Lines changed: 37 additions & 15 deletions

File tree

cli/seed_users.go

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,53 @@ import (
1010
"github.com/database-playground/backend-v2/ent/group"
1111
"github.com/database-playground/backend-v2/ent/user"
1212
"github.com/database-playground/backend-v2/internal/useraccount"
13+
"github.com/samber/lo"
1314
)
1415

16+
// SeedUsers creates users from the provided seed records.
17+
//
18+
// Each record must contain a valid email and an optional group slug.
19+
// If the referenced group does not exist, an error is returned.
20+
// If a user with the same email already exists, it is skipped without error.
21+
//
22+
// SeedUsers returns an error if validation, group lookup, or user creation fails.
1523
func (c *Context) SeedUsers(ctx context.Context, userSeedRecords []UserSeedRecord) error {
1624
// validate records
25+
if len(userSeedRecords) == 0 {
26+
return nil
27+
}
28+
1729
for i, record := range userSeedRecords {
1830
if err := record.Validate(); err != nil {
1931
return fmt.Errorf("user seed record #%d: %w", i, err)
2032
}
2133
}
2234

23-
// query groups for the records
24-
groups := make(map[string]*ent.Group)
25-
for _, record := range userSeedRecords {
26-
group, err := c.entClient.Group.Query().Where(group.NameEQ(record.GetGroup())).Only(ctx)
27-
if err != nil {
28-
if ent.IsNotFound(err) {
29-
return fmt.Errorf("group %q not found", record.GetGroup())
30-
}
35+
// collect unique group names
36+
uniqueGroupName := lo.Uniq(lo.Map(userSeedRecords, func(record UserSeedRecord, _ int) string {
37+
return record.GetGroup()
38+
}))
3139

32-
return fmt.Errorf("query group %q: %w", record.GetGroup(), err)
33-
}
34-
groups[record.GetGroup()] = group
40+
// query all required groups in a single batch
41+
entGroups, err := c.entClient.Group.Query().Where(group.NameIn(uniqueGroupName...)).All(ctx)
42+
if err != nil {
43+
return fmt.Errorf("query groups: %w", err)
3544
}
3645

46+
groups := make(map[string]*ent.Group, len(entGroups))
47+
for _, g := range entGroups {
48+
groups[g.Name] = g
49+
}
50+
51+
// ensure all requested groups were found
52+
for _, name := range uniqueGroupName {
53+
if _, ok := groups[name]; !ok {
54+
return fmt.Errorf("group %q not found", name)
55+
}
56+
}
3757
// create users
3858
for _, record := range userSeedRecords {
39-
group, ok := groups[record.GetGroup()]
40-
if !ok {
41-
return fmt.Errorf("user record %q: group %q not found", record.GetEmail(), record.GetGroup())
42-
}
59+
group := groups[record.GetGroup()]
4360

4461
// check if user already exists
4562
user, err := c.entClient.User.Query().Where(user.EmailEQ(record.Email)).First(ctx)
@@ -63,15 +80,19 @@ func (c *Context) SeedUsers(ctx context.Context, userSeedRecords []UserSeedRecor
6380
return nil
6481
}
6582

83+
// UserSeedRecord represents a user seed record.
6684
type UserSeedRecord struct {
6785
Email string `json:"email"`
6886
Group string `json:"group"`
6987
}
7088

89+
// GetEmail returns the email of the user seed record.
7190
func (r UserSeedRecord) GetEmail() string {
7291
return r.Email
7392
}
7493

94+
// GetGroup returns the group of the user seed record.
95+
// If the group slug is omitted, the user will be added to the `student` group.
7596
func (r UserSeedRecord) GetGroup() string {
7697
if r.Group == "" {
7798
return useraccount.StudentGroupSlug
@@ -80,6 +101,7 @@ func (r UserSeedRecord) GetGroup() string {
80101
return r.Group
81102
}
82103

104+
// Validate validates the user seed record.
83105
func (r UserSeedRecord) Validate() error {
84106
if r.Email == "" {
85107
return errors.New("email is required")

0 commit comments

Comments
 (0)