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