-
Notifications
You must be signed in to change notification settings - Fork 1
/
mget_todo.go
129 lines (116 loc) · 2.99 KB
/
mget_todo.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package todo
import (
"context"
"github.com/borntodie-new/todo-list-backup/constant"
"github.com/borntodie-new/todo-list-backup/model"
"gorm.io/gorm"
"sync"
"time"
)
type DetailUser struct {
ID int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Avatar string `json:"avatar"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type UserAndTodoDetail struct {
*DetailUser
Todos []*model.Todo `json:"todos,omitempty"`
}
type MGetTodoFlow struct {
// global data
ctx context.Context
db *gorm.DB
// request data
UserIds []int64
// temporary data
usersMapping map[int64]*model.User
todosMapping map[int64][]*model.Todo
// response data
UserAndTodo []*UserAndTodoDetail
}
func NewMGetTodoFlow(userIds []int64, ctx context.Context, db *gorm.DB) *MGetTodoFlow {
return &MGetTodoFlow{
ctx: ctx,
db: db,
UserIds: userIds,
usersMapping: make(map[int64]*model.User),
todosMapping: make(map[int64][]*model.Todo),
UserAndTodo: make([]*UserAndTodoDetail, 0),
}
}
func MGetTodo(UserIds []int64, ctx context.Context, db *gorm.DB) ([]*UserAndTodoDetail, error) {
return NewMGetTodoFlow(UserIds, ctx, db).Do()
}
func (f *MGetTodoFlow) Do() ([]*UserAndTodoDetail, error) {
if err := f.checkData(); err != nil {
return nil, err
}
if err := f.prepareData(); err != nil {
return nil, err
}
if err := f.packageData(); err != nil {
return nil, err
}
return f.UserAndTodo, nil
}
func (f *MGetTodoFlow) checkData() error {
if len(f.UserIds) == 0 {
return constant.ParamErr
}
return nil
}
func (f *MGetTodoFlow) prepareData() error {
wg := sync.WaitGroup{}
wg.Add(2)
var err error
// 1. 获取用户列表
go func() {
defer wg.Done()
var users []*model.User
users, err = model.NewUserDao(f.ctx, f.db).RetrieveInstances(f.UserIds)
for _, user := range users {
f.usersMapping[user.ID] = user
}
}()
// 2. 获取todo列表
go func() {
defer wg.Done()
var todos []*model.Todo
todos, err = model.NewTodoDao(f.ctx, f.db).RetrieveInstances(f.UserIds)
for _, todo := range todos {
if _, ok := f.todosMapping[todo.UserId]; ok {
f.todosMapping[todo.UserId] = append(f.todosMapping[todo.UserId], todo)
} else {
f.todosMapping[todo.UserId] = make([]*model.Todo, 0)
f.todosMapping[todo.UserId] = append(f.todosMapping[todo.UserId], todo)
}
}
}()
wg.Wait()
return err
}
func (f *MGetTodoFlow) packageData() error {
userAndTodoDetails := make([]*UserAndTodoDetail, 0)
for _, user := range f.usersMapping {
temp := &UserAndTodoDetail{
DetailUser: &DetailUser{
ID: user.ID,
Username: user.Username,
Email: user.Email,
Avatar: user.Avatar,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
},
Todos: make([]*model.Todo, 0),
}
if todos, ok := f.todosMapping[user.ID]; ok {
temp.Todos = todos
}
userAndTodoDetails = append(userAndTodoDetails, temp)
}
f.UserAndTodo = userAndTodoDetails
return nil
}