1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package schedule
17
18 import (
19 "context"
20 "time"
21
22 "github.com/jinzhu/gorm"
23 ctrl "sigs.k8s.io/controller-runtime"
24
25 "github.com/chaos-mesh/chaos-mesh/pkg/dashboard/core"
26 )
27
28 var log = ctrl.Log.WithName("store/schedule")
29
30
31 func NewStore(db *gorm.DB) core.ScheduleStore {
32 db.AutoMigrate(&core.Schedule{})
33
34 return &ScheduleStore{db}
35 }
36
37
38 func DeleteIncompleteSchedules(es core.ScheduleStore, _ core.EventStore) {
39 if err := es.DeleteIncompleteSchedules(context.Background()); err != nil && !gorm.IsRecordNotFoundError(err) {
40 log.Error(err, "failed to delete all incomplete schedules")
41 }
42 }
43
44 type ScheduleStore struct {
45 db *gorm.DB
46 }
47
48
49 func (e *ScheduleStore) ListMeta(_ context.Context, namespace, name string, archived bool) ([]*core.ScheduleMeta, error) {
50 db := e.db.Table("schedules")
51 sches := make([]*core.ScheduleMeta, 0)
52 query, args := constructQueryArgs("", namespace, name, "")
53
54 if err := db.Where(query, args).Where("archived = ?", archived).Find(&sches).Error; err != nil && !gorm.IsRecordNotFoundError(err) {
55 return nil, err
56 }
57
58 return sches, nil
59 }
60
61
62 func (e *ScheduleStore) FindByUID(_ context.Context, uid string) (*core.Schedule, error) {
63 sch := new(core.Schedule)
64
65 if err := e.db.Where("uid = ?", uid).First(sch).Error; err != nil {
66 return nil, err
67 }
68
69 return sch, nil
70 }
71
72
73 func (e *ScheduleStore) FindMetaByUID(_ context.Context, uid string) (*core.ScheduleMeta, error) {
74 db := e.db.Table("schedules")
75 sch := new(core.ScheduleMeta)
76
77 if err := db.Where("uid = ?", uid).First(sch).Error; err != nil {
78 return nil, err
79 }
80
81 return sch, nil
82 }
83
84
85 func (e *ScheduleStore) Set(_ context.Context, schedule *core.Schedule) error {
86 return e.db.Model(core.Schedule{}).Save(schedule).Error
87 }
88
89
90 func (e *ScheduleStore) Archive(_ context.Context, ns, name string) error {
91 if err := e.db.Model(core.Schedule{}).
92 Where("namespace = ? AND name = ? AND archived = ?", ns, name, false).
93 Updates(map[string]interface{}{"archived": true, "finish_time": time.Now()}).Error; err != nil && !gorm.IsRecordNotFoundError(err) {
94 return err
95 }
96
97 return nil
98 }
99
100
101 func (e *ScheduleStore) Delete(_ context.Context, exp *core.Schedule) error {
102 err := e.db.Table("schedules").Unscoped().Delete(*exp).Error
103 return err
104 }
105
106
107 func (e *ScheduleStore) DeleteByFinishTime(_ context.Context, ttl time.Duration) error {
108 sches, err := e.ListMeta(context.Background(), "", "", true)
109 if err != nil {
110 return err
111 }
112
113 nowTime := time.Now()
114 for _, sch := range sches {
115 if sch.FinishTime == nil {
116 log.Error(nil, "finish time is nil when deleting archived schedule records, skip it", "schedule", sch)
117 continue
118 }
119 if sch.FinishTime.Add(ttl).Before(nowTime) {
120 if err := e.db.Table("schedules").Unscoped().Delete(*sch).Error; err != nil {
121 return err
122 }
123 }
124 }
125
126 return nil
127 }
128
129
130 func (e *ScheduleStore) DeleteByUIDs(_ context.Context, uids []string) error {
131 return e.db.Table("schedules").Where("uid IN (?)", uids).Unscoped().Delete(core.Schedule{}).Error
132 }
133
134
135 func (e *ScheduleStore) DeleteIncompleteSchedules(_ context.Context) error {
136 return e.db.Where("finish_time IS NULL").Unscoped().Delete(core.Schedule{}).Error
137 }
138
139 func constructQueryArgs(kind, ns, name, uid string) (string, []string) {
140 query := ""
141 args := make([]string, 0)
142
143 if kind != "" {
144 query += "kind = ?"
145 args = append(args, kind)
146 }
147
148 if ns != "" {
149 if len(args) > 0 {
150 query += " AND namespace = ?"
151 } else {
152 query += "namespace = ?"
153 }
154 args = append(args, ns)
155 }
156
157 if name != "" {
158 if len(args) > 0 {
159 query += " AND name = ?"
160 } else {
161 query += "name = ?"
162 }
163 args = append(args, name)
164 }
165
166 if uid != "" {
167 if len(args) > 0 {
168 query += " AND uid = ?"
169 } else {
170 query += "uid = ?"
171 }
172 args = append(args, uid)
173 }
174
175 return query, args
176 }
177