github.com/go-generalize/volcago@v1.7.0/generator/testfiles/auto/different_dir/lock_meta_gen.go (about) 1 // Code generated by volcago. DO NOT EDIT. 2 // generated version: (devel) 3 package model 4 5 import ( 6 "context" 7 "time" 8 9 "cloud.google.com/go/firestore" 10 "golang.org/x/xerrors" 11 "google.golang.org/api/iterator" 12 "google.golang.org/grpc/codes" 13 "google.golang.org/grpc/status" 14 15 model "github.com/go-generalize/volcago/generator/testfiles/auto" 16 ) 17 18 //go:generate mockgen -source $GOFILE -destination mock/mock_lock_meta_gen/mock_lock_meta_gen.go 19 20 // LockMetaRepository - Repository of LockMeta 21 type LockMetaRepository interface { 22 // Single 23 Get(ctx context.Context, id string, opts ...GetOption) (*model.LockMeta, error) 24 GetWithDoc(ctx context.Context, doc *firestore.DocumentRef, opts ...GetOption) (*model.LockMeta, error) 25 Insert(ctx context.Context, subject *model.LockMeta) (_ string, err error) 26 Update(ctx context.Context, subject *model.LockMeta) (err error) 27 StrictUpdate(ctx context.Context, id string, param *LockMetaUpdateParam, opts ...firestore.Precondition) error 28 Delete(ctx context.Context, subject *model.LockMeta, opts ...DeleteOption) (err error) 29 DeleteByID(ctx context.Context, id string, opts ...DeleteOption) (err error) 30 // Multiple 31 GetMulti(ctx context.Context, ids []string, opts ...GetOption) ([]*model.LockMeta, error) 32 InsertMulti(ctx context.Context, subjects []*model.LockMeta) (_ []string, er error) 33 UpdateMulti(ctx context.Context, subjects []*model.LockMeta) (er error) 34 DeleteMulti(ctx context.Context, subjects []*model.LockMeta, opts ...DeleteOption) (er error) 35 DeleteMultiByIDs(ctx context.Context, ids []string, opts ...DeleteOption) (er error) 36 // Single(Transaction) 37 GetWithTx(tx *firestore.Transaction, id string, opts ...GetOption) (*model.LockMeta, error) 38 GetWithDocWithTx(tx *firestore.Transaction, doc *firestore.DocumentRef, opts ...GetOption) (*model.LockMeta, error) 39 InsertWithTx(ctx context.Context, tx *firestore.Transaction, subject *model.LockMeta) (_ string, err error) 40 UpdateWithTx(ctx context.Context, tx *firestore.Transaction, subject *model.LockMeta) (err error) 41 StrictUpdateWithTx(tx *firestore.Transaction, id string, param *LockMetaUpdateParam, opts ...firestore.Precondition) error 42 DeleteWithTx(ctx context.Context, tx *firestore.Transaction, subject *model.LockMeta, opts ...DeleteOption) (err error) 43 DeleteByIDWithTx(ctx context.Context, tx *firestore.Transaction, id string, opts ...DeleteOption) (err error) 44 // Multiple(Transaction) 45 GetMultiWithTx(tx *firestore.Transaction, ids []string, opts ...GetOption) ([]*model.LockMeta, error) 46 InsertMultiWithTx(ctx context.Context, tx *firestore.Transaction, subjects []*model.LockMeta) (_ []string, er error) 47 UpdateMultiWithTx(ctx context.Context, tx *firestore.Transaction, subjects []*model.LockMeta) (er error) 48 DeleteMultiWithTx(ctx context.Context, tx *firestore.Transaction, subjects []*model.LockMeta, opts ...DeleteOption) (er error) 49 DeleteMultiByIDsWithTx(ctx context.Context, tx *firestore.Transaction, ids []string, opts ...DeleteOption) (er error) 50 // Search 51 Search(ctx context.Context, param *LockMetaSearchParam, q *firestore.Query) ([]*model.LockMeta, error) 52 SearchWithTx(tx *firestore.Transaction, param *LockMetaSearchParam, q *firestore.Query) ([]*model.LockMeta, error) 53 SearchByParam(ctx context.Context, param *LockMetaSearchParam) ([]*model.LockMeta, *PagingResult, error) 54 SearchByParamWithTx(tx *firestore.Transaction, param *LockMetaSearchParam) ([]*model.LockMeta, *PagingResult, error) 55 // misc 56 GetCollection() *firestore.CollectionRef 57 GetCollectionName() string 58 GetDocRef(id string) *firestore.DocumentRef 59 RunInTransaction() func(ctx context.Context, f func(context.Context, *firestore.Transaction) error, opts ...firestore.TransactionOption) (err error) 60 } 61 62 // LockMetaRepositoryMiddleware - middleware of LockMetaRepository 63 type LockMetaRepositoryMiddleware interface { 64 BeforeInsert(ctx context.Context, subject *model.LockMeta) (bool, error) 65 BeforeUpdate(ctx context.Context, old, subject *model.LockMeta) (bool, error) 66 BeforeDelete(ctx context.Context, subject *model.LockMeta, opts ...DeleteOption) (bool, error) 67 BeforeDeleteByID(ctx context.Context, ids []string, opts ...DeleteOption) (bool, error) 68 } 69 70 type lockMetaRepository struct { 71 collectionName string 72 firestoreClient *firestore.Client 73 middleware []LockMetaRepositoryMiddleware 74 uniqueRepository *uniqueRepository 75 } 76 77 // NewLockMetaRepository - constructor 78 func NewLockMetaRepository(firestoreClient *firestore.Client, middleware ...LockMetaRepositoryMiddleware) LockMetaRepository { 79 return &lockMetaRepository{ 80 collectionName: "LockMeta", 81 firestoreClient: firestoreClient, 82 middleware: middleware, 83 uniqueRepository: newUniqueRepository(firestoreClient, "LockMeta"), 84 } 85 } 86 87 func (repo *lockMetaRepository) setMeta(subject *model.LockMeta, isInsert bool) { 88 now := time.Now() 89 90 if isInsert { 91 subject.CreatedAt = now 92 } 93 subject.UpdatedAt = now 94 subject.Version++ 95 } 96 97 func (repo *lockMetaRepository) setMetaWithStrictUpdate(param *LockMetaUpdateParam) { 98 param.UpdatedAt = firestore.ServerTimestamp 99 param.Version = firestore.Increment(1) 100 } 101 102 func (repo *lockMetaRepository) beforeInsert(ctx context.Context, subject *model.LockMeta) error { 103 if subject.Version != 0 { 104 return xerrors.Errorf("insert data must be Version == 0 %+v: %w", subject, ErrVersionConflict) 105 } 106 if subject.DeletedAt != nil { 107 return xerrors.Errorf("insert data must be DeletedAt == nil: %+v", subject) 108 } 109 repo.setMeta(subject, true) 110 repo.uniqueRepository.setMiddleware(ctx) 111 err := repo.uniqueRepository.CheckUnique(ctx, nil, subject) 112 if err != nil { 113 return xerrors.Errorf("unique.middleware error: %w", err) 114 } 115 116 for _, m := range repo.middleware { 117 c, err := m.BeforeInsert(ctx, subject) 118 if err != nil { 119 return xerrors.Errorf("beforeInsert.middleware error: %w", err) 120 } 121 if !c { 122 continue 123 } 124 } 125 126 return nil 127 } 128 129 func (repo *lockMetaRepository) beforeUpdate(ctx context.Context, old, subject *model.LockMeta) error { 130 if ctx.Value(transactionInProgressKey{}) != nil && old == nil { 131 var err error 132 doc := repo.GetDocRef(subject.ID) 133 old, err = repo.get(context.Background(), doc) 134 if err != nil { 135 if status.Code(err) == codes.NotFound { 136 return ErrNotFound 137 } 138 return xerrors.Errorf("error in Get method: %w", err) 139 } 140 } 141 if old.Version > subject.Version { 142 return xerrors.Errorf( 143 "The data in the database is newer: (db version: %d, target version: %d) %+v: %w", 144 old.Version, subject.Version, subject, ErrVersionConflict, 145 ) 146 } 147 if subject.DeletedAt != nil { 148 return xerrors.Errorf("update data must be DeletedAt == nil: %+v", subject) 149 } 150 repo.setMeta(subject, false) 151 repo.uniqueRepository.setMiddleware(ctx) 152 err := repo.uniqueRepository.CheckUnique(ctx, old, subject) 153 if err != nil { 154 return xerrors.Errorf("unique.middleware error: %w", err) 155 } 156 157 for _, m := range repo.middleware { 158 c, err := m.BeforeUpdate(ctx, old, subject) 159 if err != nil { 160 return xerrors.Errorf("beforeUpdate.middleware error: %w", err) 161 } 162 if !c { 163 continue 164 } 165 } 166 167 return nil 168 } 169 170 func (repo *lockMetaRepository) beforeDelete(ctx context.Context, subject *model.LockMeta, opts ...DeleteOption) error { 171 repo.setMeta(subject, false) 172 repo.uniqueRepository.setMiddleware(ctx) 173 err := repo.uniqueRepository.DeleteUnique(ctx, subject) 174 if err != nil { 175 return xerrors.Errorf("unique.middleware error: %w", err) 176 } 177 178 for _, m := range repo.middleware { 179 c, err := m.BeforeDelete(ctx, subject, opts...) 180 if err != nil { 181 return xerrors.Errorf("beforeDelete.middleware error: %w", err) 182 } 183 if !c { 184 continue 185 } 186 } 187 188 return nil 189 } 190 191 // GetCollection - *firestore.CollectionRef getter 192 func (repo *lockMetaRepository) GetCollection() *firestore.CollectionRef { 193 return repo.firestoreClient.Collection(repo.collectionName) 194 } 195 196 // GetCollectionName - CollectionName getter 197 func (repo *lockMetaRepository) GetCollectionName() string { 198 return repo.collectionName 199 } 200 201 // GetDocRef - *firestore.DocumentRef getter 202 func (repo *lockMetaRepository) GetDocRef(id string) *firestore.DocumentRef { 203 return repo.GetCollection().Doc(id) 204 } 205 206 // RunInTransaction - (*firestore.Client).RunTransaction getter 207 func (repo *lockMetaRepository) RunInTransaction() func(ctx context.Context, f func(context.Context, *firestore.Transaction) error, opts ...firestore.TransactionOption) (err error) { 208 return repo.firestoreClient.RunTransaction 209 } 210 211 // LockMetaSearchParam - params for search 212 type LockMetaSearchParam struct { 213 ID *QueryChainer 214 Text *QueryChainer 215 Flag *QueryChainer 216 CreatedAt *QueryChainer 217 CreatedBy *QueryChainer 218 UpdatedAt *QueryChainer 219 UpdatedBy *QueryChainer 220 DeletedAt *QueryChainer 221 DeletedBy *QueryChainer 222 Version *QueryChainer 223 224 IncludeSoftDeleted bool 225 CursorKey string 226 CursorLimit int 227 } 228 229 // LockMetaUpdateParam - params for strict updates 230 type LockMetaUpdateParam struct { 231 Text interface{} 232 Flag interface{} 233 CreatedAt interface{} 234 CreatedBy interface{} 235 UpdatedAt interface{} 236 UpdatedBy interface{} 237 DeletedAt interface{} 238 DeletedBy interface{} 239 Version interface{} 240 } 241 242 // Search - search documents 243 // The third argument is firestore.Query, basically you can pass nil 244 func (repo *lockMetaRepository) Search(ctx context.Context, param *LockMetaSearchParam, q *firestore.Query) ([]*model.LockMeta, error) { 245 return repo.search(ctx, param, q) 246 } 247 248 // SearchByParam - search documents by search param 249 func (repo *lockMetaRepository) SearchByParam(ctx context.Context, param *LockMetaSearchParam) ([]*model.LockMeta, *PagingResult, error) { 250 return repo.searchByParam(ctx, param) 251 } 252 253 // Get - get `LockMeta` by `LockMeta.ID` 254 func (repo *lockMetaRepository) Get(ctx context.Context, id string, opts ...GetOption) (*model.LockMeta, error) { 255 doc := repo.GetDocRef(id) 256 return repo.get(ctx, doc, opts...) 257 } 258 259 // GetWithDoc - get `LockMeta` by *firestore.DocumentRef 260 func (repo *lockMetaRepository) GetWithDoc(ctx context.Context, doc *firestore.DocumentRef, opts ...GetOption) (*model.LockMeta, error) { 261 return repo.get(ctx, doc, opts...) 262 } 263 264 // Insert - insert of `LockMeta` 265 func (repo *lockMetaRepository) Insert(ctx context.Context, subject *model.LockMeta) (_ string, err error) { 266 if err := repo.beforeInsert(ctx, subject); err != nil { 267 return "", xerrors.Errorf("before insert error: %w", err) 268 } 269 270 return repo.insert(ctx, subject) 271 } 272 273 // Update - update of `LockMeta` 274 func (repo *lockMetaRepository) Update(ctx context.Context, subject *model.LockMeta) (err error) { 275 doc := repo.GetDocRef(subject.ID) 276 277 old, err := repo.get(ctx, doc) 278 if err != nil { 279 if status.Code(err) == codes.NotFound { 280 return ErrNotFound 281 } 282 return xerrors.Errorf("error in Get method: %w", err) 283 } 284 285 if err := repo.beforeUpdate(ctx, old, subject); err != nil { 286 return xerrors.Errorf("before update error: %w", err) 287 } 288 289 return repo.update(ctx, subject) 290 } 291 292 // StrictUpdate - strict update of `LockMeta` 293 func (repo *lockMetaRepository) StrictUpdate(ctx context.Context, id string, param *LockMetaUpdateParam, opts ...firestore.Precondition) error { 294 return repo.strictUpdate(ctx, id, param, opts...) 295 } 296 297 // Delete - delete of `LockMeta` 298 func (repo *lockMetaRepository) Delete(ctx context.Context, subject *model.LockMeta, opts ...DeleteOption) (err error) { 299 if err := repo.beforeDelete(ctx, subject, opts...); err != nil { 300 return xerrors.Errorf("before delete error: %w", err) 301 } 302 303 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 304 t := time.Now() 305 subject.DeletedAt = &t 306 if err := repo.update(ctx, subject); err != nil { 307 return xerrors.Errorf("error in update method: %w", err) 308 } 309 return nil 310 } 311 312 return repo.deleteByID(ctx, subject.ID) 313 } 314 315 // DeleteByID - delete `LockMeta` by `LockMeta.ID` 316 func (repo *lockMetaRepository) DeleteByID(ctx context.Context, id string, opts ...DeleteOption) (err error) { 317 subject, err := repo.Get(ctx, id) 318 if err != nil { 319 return xerrors.Errorf("error in Get method: %w", err) 320 } 321 322 if err := repo.beforeDelete(ctx, subject, opts...); err != nil { 323 return xerrors.Errorf("before delete error: %w", err) 324 } 325 326 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 327 t := time.Now() 328 subject.DeletedAt = &t 329 if err := repo.update(ctx, subject); err != nil { 330 return xerrors.Errorf("error in update method: %w", err) 331 } 332 return nil 333 } 334 335 return repo.Delete(ctx, subject, opts...) 336 } 337 338 // GetMulti - get `LockMeta` in bulk by array of `LockMeta.ID` 339 func (repo *lockMetaRepository) GetMulti(ctx context.Context, ids []string, opts ...GetOption) ([]*model.LockMeta, error) { 340 return repo.getMulti(ctx, ids, opts...) 341 } 342 343 // InsertMulti - bulk insert of `LockMeta` 344 func (repo *lockMetaRepository) InsertMulti(ctx context.Context, subjects []*model.LockMeta) (_ []string, er error) { 345 346 ids := make([]string, 0, len(subjects)) 347 batches := make([]*firestore.WriteBatch, 0) 348 batch := repo.firestoreClient.Batch() 349 collect := repo.GetCollection() 350 351 for i, subject := range subjects { 352 var ref *firestore.DocumentRef 353 if subject.ID == "" { 354 ref = collect.NewDoc() 355 subject.ID = ref.ID 356 } else { 357 ref = collect.Doc(subject.ID) 358 if s, err := ref.Get(ctx); err == nil { 359 return nil, xerrors.Errorf("already exists [%v]: %#v", subject.ID, s) 360 } 361 } 362 363 if err := repo.beforeInsert(ctx, subject); err != nil { 364 return nil, xerrors.Errorf("before insert error(%d) [%v]: %w", i, subject.ID, err) 365 } 366 367 batch.Set(ref, subject) 368 ids = append(ids, ref.ID) 369 i++ 370 if (i%500) == 0 && len(subjects) != i { 371 batches = append(batches, batch) 372 batch = repo.firestoreClient.Batch() 373 } 374 } 375 batches = append(batches, batch) 376 377 for _, b := range batches { 378 if _, err := b.Commit(ctx); err != nil { 379 return nil, xerrors.Errorf("error in Commit method: %w", err) 380 } 381 } 382 383 return ids, nil 384 } 385 386 // UpdateMulti - bulk update of `LockMeta` 387 func (repo *lockMetaRepository) UpdateMulti(ctx context.Context, subjects []*model.LockMeta) (er error) { 388 389 batches := make([]*firestore.WriteBatch, 0) 390 batch := repo.firestoreClient.Batch() 391 collect := repo.GetCollection() 392 393 for i, subject := range subjects { 394 ref := collect.Doc(subject.ID) 395 snapShot, err := ref.Get(ctx) 396 if err != nil { 397 if status.Code(err) == codes.NotFound { 398 return xerrors.Errorf("not found [%v]: %w", subject.ID, err) 399 } 400 return xerrors.Errorf("error in Get method [%v]: %w", subject.ID, err) 401 } 402 403 old := new(model.LockMeta) 404 if err = snapShot.DataTo(&old); err != nil { 405 return xerrors.Errorf("error in DataTo method: %w", err) 406 } 407 408 if err := repo.beforeUpdate(ctx, old, subject); err != nil { 409 return xerrors.Errorf("before update error(%d) [%v]: %w", i, subject.ID, err) 410 } 411 412 batch.Set(ref, subject) 413 i++ 414 if (i%500) == 0 && len(subjects) != i { 415 batches = append(batches, batch) 416 batch = repo.firestoreClient.Batch() 417 } 418 } 419 batches = append(batches, batch) 420 421 for _, b := range batches { 422 if _, err := b.Commit(ctx); err != nil { 423 return xerrors.Errorf("error in Commit method: %w", err) 424 } 425 } 426 427 return nil 428 } 429 430 // DeleteMulti - bulk delete of `LockMeta` 431 func (repo *lockMetaRepository) DeleteMulti(ctx context.Context, subjects []*model.LockMeta, opts ...DeleteOption) (er error) { 432 433 batches := make([]*firestore.WriteBatch, 0) 434 batch := repo.firestoreClient.Batch() 435 collect := repo.GetCollection() 436 437 for i, subject := range subjects { 438 ref := collect.Doc(subject.ID) 439 if _, err := ref.Get(ctx); err != nil { 440 if status.Code(err) == codes.NotFound { 441 return xerrors.Errorf("not found [%v]: %w", subject.ID, err) 442 } 443 return xerrors.Errorf("error in Get method [%v]: %w", subject.ID, err) 444 } 445 446 if err := repo.beforeDelete(ctx, subject, opts...); err != nil { 447 return xerrors.Errorf("before delete error(%d) [%v]: %w", i, subject.ID, err) 448 } 449 450 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 451 t := time.Now() 452 subject.DeletedAt = &t 453 batch.Set(ref, subject) 454 } else { 455 batch.Delete(ref) 456 } 457 458 i++ 459 if (i%500) == 0 && len(subjects) != i { 460 batches = append(batches, batch) 461 batch = repo.firestoreClient.Batch() 462 } 463 } 464 batches = append(batches, batch) 465 466 for _, b := range batches { 467 if _, err := b.Commit(ctx); err != nil { 468 return xerrors.Errorf("error in Commit method: %w", err) 469 } 470 } 471 472 return nil 473 } 474 475 // DeleteMultiByIDs - delete `LockMeta` in bulk by array of `LockMeta.ID` 476 func (repo *lockMetaRepository) DeleteMultiByIDs(ctx context.Context, ids []string, opts ...DeleteOption) (er error) { 477 subjects := make([]*model.LockMeta, len(ids)) 478 479 opt := GetOption{} 480 if len(opts) > 0 { 481 opt.IncludeSoftDeleted = opts[0].Mode == DeleteModeHard 482 } 483 for i, id := range ids { 484 subject, err := repo.Get(ctx, id, opt) 485 if err != nil { 486 return xerrors.Errorf("error in Get method: %w", err) 487 } 488 subjects[i] = subject 489 } 490 491 return repo.DeleteMulti(ctx, subjects, opts...) 492 } 493 494 // SearchWithTx - search documents in transaction 495 func (repo *lockMetaRepository) SearchWithTx(tx *firestore.Transaction, param *LockMetaSearchParam, q *firestore.Query) ([]*model.LockMeta, error) { 496 return repo.search(tx, param, q) 497 } 498 499 // SearchByParamWithTx - search documents by search param in transaction 500 func (repo *lockMetaRepository) SearchByParamWithTx(tx *firestore.Transaction, param *LockMetaSearchParam) ([]*model.LockMeta, *PagingResult, error) { 501 return repo.searchByParam(tx, param) 502 } 503 504 // GetWithTx - get `LockMeta` by `LockMeta.ID` in transaction 505 func (repo *lockMetaRepository) GetWithTx(tx *firestore.Transaction, id string, opts ...GetOption) (*model.LockMeta, error) { 506 doc := repo.GetDocRef(id) 507 return repo.get(tx, doc, opts...) 508 } 509 510 // GetWithDocWithTx - get `LockMeta` by *firestore.DocumentRef in transaction 511 func (repo *lockMetaRepository) GetWithDocWithTx(tx *firestore.Transaction, doc *firestore.DocumentRef, opts ...GetOption) (*model.LockMeta, error) { 512 return repo.get(tx, doc, opts...) 513 } 514 515 // InsertWithTx - insert of `LockMeta` in transaction 516 func (repo *lockMetaRepository) InsertWithTx(ctx context.Context, tx *firestore.Transaction, subject *model.LockMeta) (_ string, err error) { 517 if err := repo.beforeInsert(context.WithValue(ctx, transactionInProgressKey{}, tx), subject); err != nil { 518 return "", xerrors.Errorf("before insert error: %w", err) 519 } 520 521 return repo.insert(tx, subject) 522 } 523 524 // UpdateWithTx - update of `LockMeta` in transaction 525 func (repo *lockMetaRepository) UpdateWithTx(ctx context.Context, tx *firestore.Transaction, subject *model.LockMeta) (err error) { 526 if err := repo.beforeUpdate(context.WithValue(ctx, transactionInProgressKey{}, tx), nil, subject); err != nil { 527 return xerrors.Errorf("before update error: %w", err) 528 } 529 530 return repo.update(tx, subject) 531 } 532 533 // StrictUpdateWithTx - strict update of `LockMeta` in transaction 534 func (repo *lockMetaRepository) StrictUpdateWithTx(tx *firestore.Transaction, id string, param *LockMetaUpdateParam, opts ...firestore.Precondition) error { 535 return repo.strictUpdate(tx, id, param, opts...) 536 } 537 538 // DeleteWithTx - delete of `LockMeta` in transaction 539 func (repo *lockMetaRepository) DeleteWithTx(ctx context.Context, tx *firestore.Transaction, subject *model.LockMeta, opts ...DeleteOption) (err error) { 540 if err := repo.beforeDelete(context.WithValue(ctx, transactionInProgressKey{}, tx), subject, opts...); err != nil { 541 return xerrors.Errorf("before delete error: %w", err) 542 } 543 544 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 545 t := time.Now() 546 subject.DeletedAt = &t 547 if err := repo.update(tx, subject); err != nil { 548 return xerrors.Errorf("error in update method: %w", err) 549 } 550 return nil 551 } 552 553 return repo.deleteByID(tx, subject.ID) 554 } 555 556 // DeleteByIDWithTx - delete `LockMeta` by `LockMeta.ID` in transaction 557 func (repo *lockMetaRepository) DeleteByIDWithTx(ctx context.Context, tx *firestore.Transaction, id string, opts ...DeleteOption) (err error) { 558 subject, err := repo.Get(context.Background(), id) 559 if err != nil { 560 return xerrors.Errorf("error in Get method: %w", err) 561 } 562 563 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 564 t := time.Now() 565 subject.DeletedAt = &t 566 if err := repo.update(tx, subject); err != nil { 567 return xerrors.Errorf("error in update method: %w", err) 568 } 569 return nil 570 } 571 572 if err := repo.beforeDelete(context.WithValue(ctx, transactionInProgressKey{}, tx), subject, opts...); err != nil { 573 return xerrors.Errorf("before delete error: %w", err) 574 } 575 576 return repo.deleteByID(tx, id) 577 } 578 579 // GetMultiWithTx - get `LockMeta` in bulk by array of `LockMeta.ID` in transaction 580 func (repo *lockMetaRepository) GetMultiWithTx(tx *firestore.Transaction, ids []string, opts ...GetOption) ([]*model.LockMeta, error) { 581 return repo.getMulti(tx, ids, opts...) 582 } 583 584 // InsertMultiWithTx - bulk insert of `LockMeta` in transaction 585 func (repo *lockMetaRepository) InsertMultiWithTx(ctx context.Context, tx *firestore.Transaction, subjects []*model.LockMeta) (_ []string, er error) { 586 587 ids := make([]string, len(subjects)) 588 589 for i := range subjects { 590 if err := repo.beforeInsert(ctx, subjects[i]); err != nil { 591 return nil, xerrors.Errorf("before insert error(%d) [%v]: %w", i, subjects[i].ID, err) 592 } 593 594 id, err := repo.insert(tx, subjects[i]) 595 if err != nil { 596 return nil, xerrors.Errorf("error in insert method(%d) [%v]: %w", i, subjects[i].ID, err) 597 } 598 ids[i] = id 599 } 600 601 return ids, nil 602 } 603 604 // UpdateMultiWithTx - bulk update of `LockMeta` in transaction 605 func (repo *lockMetaRepository) UpdateMultiWithTx(ctx context.Context, tx *firestore.Transaction, subjects []*model.LockMeta) (er error) { 606 ctx = context.WithValue(ctx, transactionInProgressKey{}, tx) 607 608 for i := range subjects { 609 if err := repo.beforeUpdate(ctx, nil, subjects[i]); err != nil { 610 return xerrors.Errorf("before update error(%d) [%v]: %w", i, subjects[i].ID, err) 611 } 612 } 613 614 for i := range subjects { 615 if err := repo.update(tx, subjects[i]); err != nil { 616 return xerrors.Errorf("error in update method(%d) [%v]: %w", i, subjects[i].ID, err) 617 } 618 } 619 620 return nil 621 } 622 623 // DeleteMultiWithTx - bulk delete of `LockMeta` in transaction 624 func (repo *lockMetaRepository) DeleteMultiWithTx(ctx context.Context, tx *firestore.Transaction, subjects []*model.LockMeta, opts ...DeleteOption) (er error) { 625 626 t := time.Now() 627 var isHardDeleteMode bool 628 if len(opts) > 0 { 629 isHardDeleteMode = opts[0].Mode == DeleteModeHard 630 } 631 opt := GetOption{ 632 IncludeSoftDeleted: isHardDeleteMode, 633 } 634 for i := range subjects { 635 dr := repo.GetDocRef(subjects[i].ID) 636 if _, err := repo.get(context.Background(), dr, opt); err != nil { 637 if status.Code(err) == codes.NotFound { 638 return xerrors.Errorf("not found(%d) [%v]", i, subjects[i].ID) 639 } 640 return xerrors.Errorf("error in get method(%d) [%v]: %w", i, subjects[i].ID, err) 641 } 642 643 if err := repo.beforeDelete(context.WithValue(ctx, transactionInProgressKey{}, tx), subjects[i], opts...); err != nil { 644 return xerrors.Errorf("before delete error(%d) [%v]: %w", i, subjects[i].ID, err) 645 } 646 647 if !isHardDeleteMode { 648 subjects[i].DeletedAt = &t 649 if err := repo.update(tx, subjects[i]); err != nil { 650 return xerrors.Errorf("error in update method(%d) [%v]: %w", i, subjects[i].ID, err) 651 } 652 } 653 } 654 655 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 656 return nil 657 } 658 659 for i := range subjects { 660 if err := repo.deleteByID(tx, subjects[i].ID); err != nil { 661 return xerrors.Errorf("error in delete method(%d) [%v]: %w", i, subjects[i].ID, err) 662 } 663 } 664 665 return nil 666 } 667 668 // DeleteMultiByIDWithTx - delete `LockMeta` in bulk by array of `LockMeta.ID` in transaction 669 func (repo *lockMetaRepository) DeleteMultiByIDsWithTx(ctx context.Context, tx *firestore.Transaction, ids []string, opts ...DeleteOption) (er error) { 670 671 t := time.Now() 672 for i := range ids { 673 dr := repo.GetDocRef(ids[i]) 674 subject, err := repo.get(context.Background(), dr) 675 if err != nil { 676 if status.Code(err) == codes.NotFound { 677 return xerrors.Errorf("not found(%d) [%v]", i, ids[i]) 678 } 679 return xerrors.Errorf("error in get method(%d) [%v]: %w", i, ids[i], err) 680 } 681 682 if err := repo.beforeDelete(context.WithValue(ctx, transactionInProgressKey{}, tx), subject, opts...); err != nil { 683 return xerrors.Errorf("before delete error(%d) [%v]: %w", i, subject.ID, err) 684 } 685 686 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 687 subject.DeletedAt = &t 688 if err := repo.update(tx, subject); err != nil { 689 return xerrors.Errorf("error in update method(%d) [%v]: %w", i, ids[i], err) 690 } 691 } 692 } 693 694 if len(opts) > 0 && opts[0].Mode == DeleteModeSoft { 695 return nil 696 } 697 698 for i := range ids { 699 if err := repo.deleteByID(tx, ids[i]); err != nil { 700 return xerrors.Errorf("error in delete method(%d) [%v]: %w", i, ids[i], err) 701 } 702 } 703 704 return nil 705 } 706 707 func (repo *lockMetaRepository) get(v interface{}, doc *firestore.DocumentRef, opts ...GetOption) (*model.LockMeta, error) { 708 var ( 709 snapShot *firestore.DocumentSnapshot 710 err error 711 ) 712 713 switch x := v.(type) { 714 case *firestore.Transaction: 715 snapShot, err = x.Get(doc) 716 case context.Context: 717 snapShot, err = doc.Get(x) 718 default: 719 return nil, xerrors.Errorf("invalid type: %v", x) 720 } 721 722 if err != nil { 723 if status.Code(err) == codes.NotFound { 724 return nil, ErrNotFound 725 } 726 return nil, xerrors.Errorf("error in Get method: %w", err) 727 } 728 729 subject := new(model.LockMeta) 730 if err := snapShot.DataTo(&subject); err != nil { 731 return nil, xerrors.Errorf("error in DataTo method: %w", err) 732 } 733 734 if len(opts) == 0 || !opts[0].IncludeSoftDeleted { 735 if subject.DeletedAt != nil { 736 return nil, ErrAlreadyDeleted 737 } 738 } 739 subject.ID = snapShot.Ref.ID 740 741 return subject, nil 742 } 743 744 func (repo *lockMetaRepository) getMulti(v interface{}, ids []string, opts ...GetOption) ([]*model.LockMeta, error) { 745 var ( 746 snapShots []*firestore.DocumentSnapshot 747 err error 748 collect = repo.GetCollection() 749 drs = make([]*firestore.DocumentRef, len(ids)) 750 ) 751 752 for i, id := range ids { 753 ref := collect.Doc(id) 754 drs[i] = ref 755 } 756 757 switch x := v.(type) { 758 case *firestore.Transaction: 759 snapShots, err = x.GetAll(drs) 760 case context.Context: 761 snapShots, err = repo.firestoreClient.GetAll(x, drs) 762 default: 763 return nil, xerrors.Errorf("invalid type: %v", v) 764 } 765 766 if err != nil { 767 return nil, xerrors.Errorf("error in GetAll method: %w", err) 768 } 769 770 subjects := make([]*model.LockMeta, 0, len(ids)) 771 mErr := NewMultiErrors() 772 for i, snapShot := range snapShots { 773 if !snapShot.Exists() { 774 mErr = append(mErr, NewMultiError(i, ErrNotFound)) 775 continue 776 } 777 778 subject := new(model.LockMeta) 779 if err = snapShot.DataTo(&subject); err != nil { 780 return nil, xerrors.Errorf("error in DataTo method: %w", err) 781 } 782 783 if len(opts) == 0 || !opts[0].IncludeSoftDeleted { 784 if subject.DeletedAt != nil { 785 mErr = append(mErr, NewMultiError(i, ErrLogicallyDeletedData)) 786 continue 787 } 788 } 789 subject.ID = snapShot.Ref.ID 790 subjects = append(subjects, subject) 791 } 792 793 if len(mErr) == 0 { 794 return subjects, nil 795 } 796 797 return subjects, mErr 798 } 799 800 func (repo *lockMetaRepository) insert(v interface{}, subject *model.LockMeta) (string, error) { 801 var ( 802 dr = repo.GetCollection().NewDoc() 803 err error 804 ) 805 806 switch x := v.(type) { 807 case *firestore.Transaction: 808 err = x.Create(dr, subject) 809 case context.Context: 810 _, err = dr.Create(x, subject) 811 default: 812 return "", xerrors.Errorf("invalid type: %v", v) 813 } 814 815 if err != nil { 816 if status.Code(err) == codes.AlreadyExists { 817 return "", xerrors.Errorf("error in Create method: err=%+v: %w", err, ErrAlreadyExists) 818 } 819 return "", xerrors.Errorf("error in Create method: %w", err) 820 } 821 822 subject.ID = dr.ID 823 824 return dr.ID, nil 825 } 826 827 func (repo *lockMetaRepository) update(v interface{}, subject *model.LockMeta) error { 828 var ( 829 dr = repo.GetDocRef(subject.ID) 830 err error 831 ) 832 833 switch x := v.(type) { 834 case *firestore.Transaction: 835 err = x.Set(dr, subject) 836 case context.Context: 837 _, err = dr.Set(x, subject) 838 default: 839 return xerrors.Errorf("invalid type: %v", v) 840 } 841 842 if err != nil { 843 return xerrors.Errorf("error in Set method: %w", err) 844 } 845 846 return nil 847 } 848 849 func (repo *lockMetaRepository) strictUpdate(v interface{}, id string, param *LockMetaUpdateParam, opts ...firestore.Precondition) error { 850 var ( 851 dr = repo.GetDocRef(id) 852 err error 853 ) 854 855 repo.setMetaWithStrictUpdate(param) 856 857 updates := updater(model.LockMeta{}, param) 858 859 switch x := v.(type) { 860 case *firestore.Transaction: 861 err = x.Update(dr, updates, opts...) 862 case context.Context: 863 _, err = dr.Update(x, updates, opts...) 864 default: 865 return xerrors.Errorf("invalid type: %v", v) 866 } 867 868 if err != nil { 869 return xerrors.Errorf("error in Update method: %w", err) 870 } 871 872 return nil 873 } 874 875 func (repo *lockMetaRepository) deleteByID(v interface{}, id string) error { 876 dr := repo.GetDocRef(id) 877 var err error 878 879 switch x := v.(type) { 880 case *firestore.Transaction: 881 err = x.Delete(dr, firestore.Exists) 882 case context.Context: 883 _, err = dr.Delete(x, firestore.Exists) 884 default: 885 return xerrors.Errorf("invalid type: %v", v) 886 } 887 888 if err != nil { 889 return xerrors.Errorf("error in Delete method: %w", err) 890 } 891 892 return nil 893 } 894 895 func (repo *lockMetaRepository) runQuery(v interface{}, query firestore.Query) ([]*model.LockMeta, error) { 896 var iter *firestore.DocumentIterator 897 898 switch x := v.(type) { 899 case *firestore.Transaction: 900 iter = x.Documents(query) 901 case context.Context: 902 iter = query.Documents(x) 903 default: 904 return nil, xerrors.Errorf("invalid type: %v", v) 905 } 906 907 defer iter.Stop() 908 909 subjects := make([]*model.LockMeta, 0) 910 911 for { 912 doc, err := iter.Next() 913 if err == iterator.Done { 914 break 915 } 916 if err != nil { 917 return nil, xerrors.Errorf("error in Next method: %w", err) 918 } 919 920 subject := new(model.LockMeta) 921 922 if err = doc.DataTo(&subject); err != nil { 923 return nil, xerrors.Errorf("error in DataTo method: %w", err) 924 } 925 926 subject.ID = doc.Ref.ID 927 subjects = append(subjects, subject) 928 } 929 930 return subjects, nil 931 } 932 933 // BUG(54m): there may be potential bugs 934 func (repo *lockMetaRepository) searchByParam(v interface{}, param *LockMetaSearchParam) ([]*model.LockMeta, *PagingResult, error) { 935 query := func() firestore.Query { 936 return repo.GetCollection().Query 937 }() 938 if param.ID != nil { 939 for _, chain := range param.ID.QueryGroup { 940 var value interface{} 941 switch val := chain.Value.(type) { 942 case string: 943 value = repo.GetDocRef(val) 944 case []string: 945 docRefs := make([]*firestore.DocumentRef, len(val)) 946 for i := range val { 947 docRefs[i] = repo.GetDocRef(val[i]) 948 } 949 value = docRefs 950 default: 951 return nil, nil, xerrors.Errorf("document id can only be of type `string` and `[]string`. value: %#v", chain.Value) 952 } 953 query = query.Where(firestore.DocumentID, chain.Operator, value) 954 } 955 if direction := param.ID.OrderByDirection; direction > 0 { 956 query = query.OrderBy(firestore.DocumentID, direction) 957 query = param.ID.BuildCursorQuery(query) 958 } 959 } 960 if param.Text != nil { 961 for _, chain := range param.Text.QueryGroup { 962 query = query.Where("text", chain.Operator, chain.Value) 963 } 964 if direction := param.Text.OrderByDirection; direction > 0 { 965 query = query.OrderBy("text", direction) 966 query = param.Text.BuildCursorQuery(query) 967 } 968 } 969 if param.Flag != nil { 970 for _, chain := range param.Flag.QueryGroup { 971 items, ok := chain.Value.(map[string]float64) 972 if !ok { 973 continue 974 } 975 for key, value := range items { 976 query = query.WherePath(firestore.FieldPath{"flag", key}, chain.Operator, value) 977 } 978 } 979 } 980 if param.CreatedAt != nil { 981 for _, chain := range param.CreatedAt.QueryGroup { 982 query = query.Where("createdAt", chain.Operator, chain.Value) 983 } 984 if direction := param.CreatedAt.OrderByDirection; direction > 0 { 985 query = query.OrderBy("createdAt", direction) 986 query = param.CreatedAt.BuildCursorQuery(query) 987 } 988 } 989 if param.CreatedBy != nil { 990 for _, chain := range param.CreatedBy.QueryGroup { 991 query = query.Where("createdBy", chain.Operator, chain.Value) 992 } 993 if direction := param.CreatedBy.OrderByDirection; direction > 0 { 994 query = query.OrderBy("createdBy", direction) 995 query = param.CreatedBy.BuildCursorQuery(query) 996 } 997 } 998 if param.UpdatedAt != nil { 999 for _, chain := range param.UpdatedAt.QueryGroup { 1000 query = query.Where("updatedAt", chain.Operator, chain.Value) 1001 } 1002 if direction := param.UpdatedAt.OrderByDirection; direction > 0 { 1003 query = query.OrderBy("updatedAt", direction) 1004 query = param.UpdatedAt.BuildCursorQuery(query) 1005 } 1006 } 1007 if param.UpdatedBy != nil { 1008 for _, chain := range param.UpdatedBy.QueryGroup { 1009 query = query.Where("updatedBy", chain.Operator, chain.Value) 1010 } 1011 if direction := param.UpdatedBy.OrderByDirection; direction > 0 { 1012 query = query.OrderBy("updatedBy", direction) 1013 query = param.UpdatedBy.BuildCursorQuery(query) 1014 } 1015 } 1016 if param.DeletedAt != nil { 1017 for _, chain := range param.DeletedAt.QueryGroup { 1018 query = query.Where("deletedAt", chain.Operator, chain.Value) 1019 } 1020 if direction := param.DeletedAt.OrderByDirection; direction > 0 { 1021 query = query.OrderBy("deletedAt", direction) 1022 query = param.DeletedAt.BuildCursorQuery(query) 1023 } 1024 } 1025 if param.DeletedBy != nil { 1026 for _, chain := range param.DeletedBy.QueryGroup { 1027 query = query.Where("deletedBy", chain.Operator, chain.Value) 1028 } 1029 if direction := param.DeletedBy.OrderByDirection; direction > 0 { 1030 query = query.OrderBy("deletedBy", direction) 1031 query = param.DeletedBy.BuildCursorQuery(query) 1032 } 1033 } 1034 if param.Version != nil { 1035 for _, chain := range param.Version.QueryGroup { 1036 query = query.Where("version", chain.Operator, chain.Value) 1037 } 1038 if direction := param.Version.OrderByDirection; direction > 0 { 1039 query = query.OrderBy("version", direction) 1040 query = param.Version.BuildCursorQuery(query) 1041 } 1042 } 1043 if !param.IncludeSoftDeleted { 1044 query = query.Where("deletedAt", OpTypeEqual, nil) 1045 } 1046 1047 limit := param.CursorLimit + 1 1048 1049 if param.CursorKey != "" { 1050 var ( 1051 ds *firestore.DocumentSnapshot 1052 err error 1053 ) 1054 switch x := v.(type) { 1055 case *firestore.Transaction: 1056 ds, err = x.Get(repo.GetDocRef(param.CursorKey)) 1057 case context.Context: 1058 ds, err = repo.GetDocRef(param.CursorKey).Get(x) 1059 default: 1060 return nil, nil, xerrors.Errorf("invalid x type: %v", v) 1061 } 1062 if err != nil { 1063 if status.Code(err) == codes.NotFound { 1064 return nil, nil, ErrNotFound 1065 } 1066 return nil, nil, xerrors.Errorf("error in Get method: %w", err) 1067 } 1068 query = query.StartAt(ds) 1069 } 1070 1071 if limit > 1 { 1072 query = query.Limit(limit) 1073 } 1074 1075 subjects, err := repo.runQuery(v, query) 1076 if err != nil { 1077 return nil, nil, xerrors.Errorf("error in runQuery method: %w", err) 1078 } 1079 1080 pagingResult := &PagingResult{ 1081 Length: len(subjects), 1082 } 1083 if limit > 1 && limit == pagingResult.Length { 1084 next := pagingResult.Length - 1 1085 pagingResult.NextCursorKey = subjects[next].ID 1086 subjects = subjects[:next] 1087 pagingResult.Length-- 1088 } 1089 1090 return subjects, pagingResult, nil 1091 } 1092 1093 func (repo *lockMetaRepository) search(v interface{}, param *LockMetaSearchParam, q *firestore.Query) ([]*model.LockMeta, error) { 1094 if (param == nil && q == nil) || (param != nil && q != nil) { 1095 return nil, xerrors.New("either one should be nil") 1096 } 1097 1098 query := func() firestore.Query { 1099 if q != nil { 1100 return *q 1101 } 1102 return repo.GetCollection().Query 1103 }() 1104 1105 if q == nil { 1106 subjects, _, err := repo.searchByParam(v, param) 1107 if err != nil { 1108 return nil, xerrors.Errorf("error in searchByParam method: %w", err) 1109 } 1110 1111 return subjects, nil 1112 } 1113 1114 return repo.runQuery(v, query) 1115 }