4
4
"context"
5
5
"errors"
6
6
"fmt"
7
-
8
7
"github.com/go-feature-flag/app-api/dao/dbmodel"
8
+ daoErr "github.com/go-feature-flag/app-api/dao/err"
9
9
"github.com/go-feature-flag/app-api/model"
10
10
"github.com/google/uuid"
11
11
"github.com/jackc/pgx/v5"
@@ -35,38 +35,38 @@ type pgFlagImpl struct {
35
35
}
36
36
37
37
// GetFlags return all the flags
38
- func (m * pgFlagImpl ) GetFlags (ctx context.Context ) ([]model.FeatureFlag , error ) {
38
+ func (m * pgFlagImpl ) GetFlags (ctx context.Context ) ([]model.FeatureFlag , daoErr. DaoError ) {
39
39
var f []dbmodel.FeatureFlag
40
- err := m .conn .SelectContext (ctx , & f , "SELECT * FROM feature_flags" )
40
+ err := m .conn .SelectContext (ctx , & f , "SELECT * FROM feature_flags ORDER BY last_updated_date DESC " )
41
41
if err != nil {
42
42
if errors .Is (err , pgx .ErrNoRows ) {
43
43
return []model.FeatureFlag {}, nil
44
44
}
45
- return []model.FeatureFlag {}, err
45
+ return []model.FeatureFlag {}, daoErr . WrapPostgresError ( err )
46
46
}
47
47
res := make ([]model.FeatureFlag , 0 , len (f ))
48
48
for _ , flag := range f {
49
49
var rules []dbmodel.Rule
50
50
err := m .conn .SelectContext (ctx , & rules , `SELECT * FROM rules WHERE feature_flag_id = $1` , flag .ID )
51
51
if err != nil {
52
- return []model.FeatureFlag {}, err
52
+ return []model.FeatureFlag {}, daoErr . WrapPostgresError ( err )
53
53
}
54
54
55
55
convertedFlag , err := flag .ToModelFeatureFlag (rules )
56
56
if err != nil {
57
- return []model.FeatureFlag {}, err
57
+ return []model.FeatureFlag {}, daoErr . WrapPostgresError ( err )
58
58
}
59
59
res = append (res , convertedFlag )
60
60
}
61
61
return res , nil
62
62
}
63
63
64
64
// GetFlagByID return a flag by its ID
65
- func (m * pgFlagImpl ) GetFlagByID (ctx context.Context , id string ) (model.FeatureFlag , error ) {
65
+ func (m * pgFlagImpl ) GetFlagByID (ctx context.Context , id string ) (model.FeatureFlag , daoErr. DaoError ) {
66
66
var f dbmodel.FeatureFlag
67
67
err := m .conn .GetContext (ctx , & f , `SELECT * FROM feature_flags WHERE id = $1` , id )
68
68
if err != nil {
69
- return model.FeatureFlag {}, err
69
+ return model.FeatureFlag {}, daoErr . WrapPostgresError ( err )
70
70
}
71
71
72
72
var rules []dbmodel.Rule
@@ -76,48 +76,48 @@ func (m *pgFlagImpl) GetFlagByID(ctx context.Context, id string) (model.FeatureF
76
76
`SELECT * FROM rules WHERE feature_flag_id = $1 ORDER BY order_index` , f .ID )
77
77
78
78
if errRule != nil {
79
- return model.FeatureFlag {}, errRule
79
+ return model.FeatureFlag {}, daoErr . WrapPostgresError ( errRule )
80
80
}
81
81
82
82
convertedFlag , err := f .ToModelFeatureFlag (rules )
83
83
if err != nil {
84
- return model.FeatureFlag {}, err
84
+ return model.FeatureFlag {}, daoErr . NewDaoError ( daoErr . ConversionError , err )
85
85
}
86
86
return convertedFlag , nil
87
87
}
88
88
89
89
// GetFlagByName return a flag by its name
90
- func (m * pgFlagImpl ) GetFlagByName (ctx context.Context , name string ) (model.FeatureFlag , error ) {
90
+ func (m * pgFlagImpl ) GetFlagByName (ctx context.Context , name string ) (model.FeatureFlag , daoErr. DaoError ) {
91
91
var f dbmodel.FeatureFlag
92
92
err := m .conn .GetContext (ctx , & f , `SELECT * FROM feature_flags WHERE name = $1` , name )
93
93
if err != nil {
94
- return model.FeatureFlag {}, err
94
+ return model.FeatureFlag {}, daoErr . WrapPostgresError ( err )
95
95
}
96
96
97
97
var rules []dbmodel.Rule
98
98
errRule := m .conn .SelectContext (ctx , & rules ,
99
99
`SELECT * FROM rules WHERE feature_flag_id = $1 ORDER BY order_index DESC` , f .ID )
100
100
if errRule != nil {
101
- return model.FeatureFlag {}, errRule
101
+ return model.FeatureFlag {}, daoErr . WrapPostgresError ( errRule )
102
102
}
103
103
104
104
convertedFlag , err := f .ToModelFeatureFlag (rules )
105
105
if err != nil {
106
- return model.FeatureFlag {}, err
106
+ return model.FeatureFlag {}, daoErr . NewDaoError ( daoErr . ConversionError , err )
107
107
}
108
108
return convertedFlag , nil
109
109
}
110
110
111
111
// CreateFlag create a new flag, return the id of the flag
112
- func (m * pgFlagImpl ) CreateFlag (ctx context.Context , flag model.FeatureFlag ) (string , error ) {
112
+ func (m * pgFlagImpl ) CreateFlag (ctx context.Context , flag model.FeatureFlag ) (string , daoErr. DaoError ) {
113
113
dbFeatureFlag , err := dbmodel .FromModelFeatureFlag (flag )
114
114
if err != nil {
115
- return "" , err
115
+ return "" , daoErr . NewDaoError ( daoErr . ConversionError , err )
116
116
}
117
117
118
118
tx , err := m .conn .Beginx ()
119
119
if err != nil {
120
- return "" , err
120
+ return "" , daoErr . WrapPostgresError ( err )
121
121
}
122
122
defer func () { _ = tx .Commit () }()
123
123
_ , err = tx .NamedExecContext (
@@ -153,64 +153,64 @@ func (m *pgFlagImpl) CreateFlag(ctx context.Context, flag model.FeatureFlag) (st
153
153
dbFeatureFlag )
154
154
if err != nil {
155
155
_ = tx .Rollback ()
156
- return "" , err
156
+ return "" , daoErr . WrapPostgresError ( err )
157
157
}
158
158
159
159
if flag .DefaultRule == nil {
160
- return "" , fmt .Errorf ("default rule is required" )
160
+ return "" , daoErr . NewDaoError ( daoErr . DefaultRuleRequired , fmt .Errorf ("default rule is required" ) )
161
161
}
162
162
err = m .insertRule (ctx , * flag .DefaultRule , true , dbFeatureFlag .ID , tx , - 1 )
163
163
if err != nil {
164
164
_ = tx .Rollback ()
165
- return "" , err
165
+ return "" , daoErr . WrapPostgresError ( err )
166
166
}
167
167
168
168
if flag .Rules != nil {
169
169
for index , rule := range * flag .Rules {
170
170
err = m .insertRule (ctx , rule , false , dbFeatureFlag .ID , tx , index )
171
171
if err != nil {
172
172
_ = tx .Rollback ()
173
- return "" , err
173
+ return "" , daoErr . WrapPostgresError ( err )
174
174
}
175
175
}
176
176
}
177
177
178
178
err = tx .Commit ()
179
179
if err != nil {
180
180
_ = tx .Rollback ()
181
- return "" , err
181
+ return "" , daoErr . WrapPostgresError ( err )
182
182
}
183
183
return dbFeatureFlag .ID .String (), nil
184
184
}
185
185
186
- func (m * pgFlagImpl ) UpdateFlag (ctx context.Context , flag model.FeatureFlag ) error {
187
- dbQuery , err := dbmodel .FromModelFeatureFlag (flag )
188
- if err != nil {
189
- return err
186
+ func (m * pgFlagImpl ) UpdateFlag (ctx context.Context , flag model.FeatureFlag ) daoErr. DaoError {
187
+ dbQuery , errConv := dbmodel .FromModelFeatureFlag (flag )
188
+ if errConv != nil {
189
+ return daoErr . NewDaoError ( daoErr . ConversionError , errConv )
190
190
}
191
191
tx , err := m .conn .Beginx ()
192
192
if err != nil {
193
- return err
193
+ return daoErr . WrapPostgresError ( err )
194
194
}
195
195
196
196
flagOrder := map [string ]int {}
197
197
for i , rule := range flag .GetRules () {
198
198
flagOrder [rule .ID ] = i
199
199
}
200
200
201
- dbFF , err := m .GetFlagByID (ctx , flag .ID )
202
- if err != nil {
203
- return err
201
+ dbFF , getFlagErr := m .GetFlagByID (ctx , flag .ID )
202
+ if getFlagErr != nil {
203
+ return getFlagErr
204
204
}
205
205
206
206
// update default rule
207
207
if flag .DefaultRule == nil {
208
- return fmt .Errorf ("default rule is required" )
208
+ return daoErr . NewDaoError ( daoErr . DefaultRuleRequired , fmt .Errorf ("default rule is required" ) )
209
209
}
210
210
211
211
if err := m .updateRule (ctx , flag .GetDefaultRule (), true , dbQuery .ID , tx , - 1 ); err != nil {
212
212
_ = tx .Rollback
213
- return err
213
+ return daoErr . WrapPostgresError ( err )
214
214
}
215
215
216
216
listExistingRuleIDs := make (map [string ]model.Rule )
@@ -241,23 +241,23 @@ func (m *pgFlagImpl) UpdateFlag(ctx context.Context, flag model.FeatureFlag) err
241
241
for _ , id := range toDelete {
242
242
if _ , err := tx .ExecContext (ctx , `DELETE FROM rules WHERE id = $1` , id ); err != nil {
243
243
_ = tx .Rollback
244
- return err
244
+ return daoErr . WrapPostgresError ( err )
245
245
}
246
246
}
247
247
248
248
for _ , id := range toCreate {
249
249
rule := listNewRuleIDs [id ]
250
250
if err := m .insertRule (ctx , rule , false , dbQuery .ID , tx , flagOrder [dbQuery .ID .String ()]); err != nil {
251
251
_ = tx .Rollback
252
- return err
252
+ return daoErr . WrapPostgresError ( err )
253
253
}
254
254
}
255
255
256
256
for _ , id := range toUpdate {
257
257
rule := listNewRuleIDs [id ]
258
258
if err = m .updateRule (ctx , rule , false , dbQuery .ID , tx , flagOrder [dbQuery .ID .String ()]); err != nil {
259
259
_ = tx .Rollback
260
- return err
260
+ return daoErr . WrapPostgresError ( err )
261
261
}
262
262
}
263
263
@@ -278,30 +278,40 @@ func (m *pgFlagImpl) UpdateFlag(ctx context.Context, flag model.FeatureFlag) err
278
278
WHERE id = :id` ,
279
279
dbQuery ); err != nil {
280
280
_ = tx .Rollback
281
- return errTx
281
+ return daoErr . WrapPostgresError ( errTx )
282
282
}
283
283
284
- return tx .Commit ()
284
+ commitErr := tx .Commit ()
285
+ if commitErr != nil {
286
+ _ = tx .Rollback
287
+ return daoErr .WrapPostgresError (commitErr )
288
+ }
289
+ return nil
285
290
}
286
291
287
- func (m * pgFlagImpl ) DeleteFlagByID (ctx context.Context , id string ) error {
292
+ func (m * pgFlagImpl ) DeleteFlagByID (ctx context.Context , id string ) daoErr. DaoError {
288
293
tx , err := m .conn .Beginx ()
289
294
if err != nil {
290
- return err
295
+ return daoErr . WrapPostgresError ( err )
291
296
}
292
297
293
298
_ , err = tx .ExecContext (ctx , `DELETE FROM rules WHERE feature_flag_id = $1` , id )
294
299
if err != nil {
295
300
_ = tx .Rollback ()
296
- return err
301
+ return daoErr . WrapPostgresError ( err )
297
302
}
298
303
299
304
_ , err = tx .ExecContext (ctx , `DELETE FROM feature_flags WHERE id = $1` , id )
300
305
if err != nil {
301
306
_ = tx .Rollback ()
302
- return err
307
+ return daoErr . WrapPostgresError ( err )
303
308
}
304
- return tx .Commit ()
309
+ commitErr := tx .Commit ()
310
+ if commitErr != nil {
311
+ _ = tx .Rollback
312
+ return daoErr .WrapPostgresError (commitErr )
313
+ }
314
+ return nil
305
315
}
306
316
307
317
func (m * pgFlagImpl ) insertRule (
@@ -383,9 +393,13 @@ func (m *pgFlagImpl) updateRule(
383
393
return errTx
384
394
}
385
395
386
- func (m * pgFlagImpl ) Ping () error {
396
+ func (m * pgFlagImpl ) Ping () daoErr. DaoError {
387
397
if m .conn == nil {
388
- return errors .New ("database connection is nil" )
398
+ return daoErr .NewDaoError (daoErr .DatabaseNotInitialized , errors .New ("database connection is nil" ))
399
+ }
400
+ err := m .conn .Ping ()
401
+ if err != nil {
402
+ return daoErr .WrapPostgresError (err )
389
403
}
390
- return m . conn . Ping ()
404
+ return nil
391
405
}
0 commit comments