Compare commits

..

2 Commits

Author SHA1 Message Date
dd999b9355 refacto: refacto repo layer code while adding new usecase methods
All checks were successful
Build and test / Build (push) Successful in 2m19s
2024-10-26 17:27:33 +02:00
14ee642aab refacto: add db tx as a possible input for repo methods
All checks were successful
Build and test / Build (push) Successful in 2m22s
2024-10-25 23:52:43 +02:00
14 changed files with 359 additions and 77 deletions

View File

@ -577,3 +577,8 @@ But between `[]*T` and `[]T`, the only difference that I see (pointed out by
`ChatGPT`) is how the memory is allocated. With `[]T` it might be better for
the GC to deal with the memory free. I thing for my project I will stick to
`[]T`.
### 2024/10/25
Read this [article](https://konradreiche.com/blog/two-common-go-interface-misuses/)
today, maybe I am abusing the usage of interfaces?

View File

@ -25,7 +25,9 @@ package repo
import (
"context"
"database/sql"
"time"
"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/adapter/repo/sqlc"
"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/usecase/repo"
"git.vinchent.xyz/vinchent/howmuch/internal/pkg/log"
)
@ -34,6 +36,8 @@ type dbRepository struct {
db *sql.DB
}
const queryTimeout = 3 * time.Second
func NewDBRepository(db *sql.DB) repo.DBRepository {
return &dbRepository{
db: db,
@ -66,3 +70,11 @@ func (dr *dbRepository) Transaction(
data, err := txFunc(ctx, tx)
return data, err
}
func getQueries(queries *sqlc.Queries, tx any) *sqlc.Queries {
transaction, ok := tx.(*sql.Tx)
if ok {
return sqlc.New(transaction)
}
return queries
}

View File

@ -26,6 +26,7 @@ import (
"context"
"database/sql"
"encoding/json"
"errors"
"time"
"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/adapter/repo/sqlc"
@ -48,8 +49,35 @@ func NewEventRepository(db *sql.DB) repo.EventRepository {
func (e *eventRepository) Create(
ctx context.Context,
evEntity *model.EventEntity,
tx any,
) (*model.EventEntity, error) {
panic("unimplemented")
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
event, err := queries.InsertEvent(timeoutCtx, sqlc.InsertEventParams{
Name: evEntity.Name,
Description: sql.NullString{String: evEntity.Description, Valid: true},
TotalAmount: sql.NullInt32{Int32: int32(evEntity.TotalAmount), Valid: true},
DefaultCurrency: evEntity.DefaultCurrency,
OwnerID: int32(evEntity.OwnerID),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
})
if err != nil {
return nil, err
}
return &model.EventEntity{
ID: int(event.ID),
Name: event.Name,
Description: event.Description.String,
TotalAmount: int(event.TotalAmount.Int32),
DefaultCurrency: event.DefaultCurrency,
OwnerID: int(event.OwnerID),
CreatedAt: event.CreatedAt,
UpdatedAt: event.UpdatedAt,
}, nil
}
func convToEventRetrieved(eventDTO *sqlc.GetEventByIDRow) (*model.EventRetrieved, error) {
@ -89,8 +117,17 @@ func convToEventRetrieved(eventDTO *sqlc.GetEventByIDRow) (*model.EventRetrieved
}
// GetByID implements repo.EventRepository.
func (e *eventRepository) GetByID(ctx context.Context, eventID int) (*model.EventRetrieved, error) {
eventDTO, err := e.queries.GetEventByID(ctx, int32(eventID))
func (e *eventRepository) GetByID(
ctx context.Context,
eventID int,
tx any,
) (*model.EventRetrieved, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
eventDTO, err := queries.GetEventByID(timeoutCtx, int32(eventID))
if err != nil {
log.ErrorLog("query error", "err", err)
return nil, err
@ -100,9 +137,9 @@ func (e *eventRepository) GetByID(ctx context.Context, eventID int) (*model.Even
}
func convToEventList(eventsDTO []sqlc.ListEventsByUserIDRow) ([]model.EventListRetrieved, error) {
var events []model.EventListRetrieved
events := make([]model.EventListRetrieved, len(eventsDTO))
for _, evDTO := range eventsDTO {
for i, evDTO := range eventsDTO {
var owner model.UserBaseRetrieved
err := json.Unmarshal(evDTO.Owner, &owner)
if err != nil {
@ -118,7 +155,7 @@ func convToEventList(eventsDTO []sqlc.ListEventsByUserIDRow) ([]model.EventListR
CreatedAt: evDTO.CreatedAt,
}
events = append(events, ev)
events[i] = ev
}
return events, nil
@ -128,8 +165,14 @@ func convToEventList(eventsDTO []sqlc.ListEventsByUserIDRow) ([]model.EventListR
func (e *eventRepository) ListEventsByUserID(
ctx context.Context,
userID int,
tx any,
) ([]model.EventListRetrieved, error) {
eventsDTO, err := e.queries.ListEventsByUserID(ctx, int32(userID))
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
eventsDTO, err := queries.ListEventsByUserID(timeoutCtx, int32(userID))
if err != nil {
log.ErrorLog("query error", "err", err)
return nil, err
@ -142,8 +185,14 @@ func (e *eventRepository) ListEventsByUserID(
func (e *eventRepository) UpdateEventByID(
ctx context.Context,
event *model.EventUpdateEntity,
tx any,
) error {
err := e.queries.UpdateEventByID(ctx, sqlc.UpdateEventByIDParams{
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
err := queries.UpdateEventByID(timeoutCtx, sqlc.UpdateEventByIDParams{
ID: int32(event.ID),
Name: event.Name,
Description: sql.NullString{String: event.Description, Valid: true},
@ -151,3 +200,77 @@ func (e *eventRepository) UpdateEventByID(
})
return err
}
// GetParticipation implements repo.EventRepository.
func (e *eventRepository) GetParticipation(
ctx context.Context,
userID, eventID int,
tx any,
) (*model.ParticipationEntity, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
partDTO, err := queries.GetParticipation(timeoutCtx, sqlc.GetParticipationParams{
UserID: int32(userID),
EventID: int32(eventID),
})
if errors.Is(err, sql.ErrNoRows) {
// No error, but participation not found
return nil, nil
}
if err != nil {
return nil, err
}
return &model.ParticipationEntity{
ID: int(partDTO.ID),
UserID: int(partDTO.UserID),
EventID: int(partDTO.EventID),
InvitedByUserID: int(partDTO.InvitedByUserID.Int32),
CreatedAt: partDTO.CreatedAt,
UpdatedAt: partDTO.UpdatedAt,
}, nil
}
// InsertParticipation implements repo.EventRepository.
func (e *eventRepository) InsertParticipation(
ctx context.Context,
userID int,
eventID int,
invitedByUserID int,
tx any,
) (*model.ParticipationEntity, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
var invitedBy sql.NullInt32
if invitedByUserID == 0 {
invitedBy = sql.NullInt32{Int32: 0, Valid: false}
} else {
invitedBy = sql.NullInt32{Int32: int32(invitedByUserID), Valid: true}
}
participationDTO, err := queries.InsertParticipation(timeoutCtx, sqlc.InsertParticipationParams{
UserID: int32(userID),
EventID: int32(eventID),
InvitedByUserID: invitedBy,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
})
if err != nil {
return nil, err
}
return &model.ParticipationEntity{
ID: int(participationDTO.ID),
UserID: int(participationDTO.UserID),
EventID: int(participationDTO.EventID),
InvitedByUserID: int(participationDTO.InvitedByUserID.Int32),
CreatedAt: participationDTO.CreatedAt,
UpdatedAt: participationDTO.UpdatedAt,
}, nil
}

View File

@ -45,21 +45,39 @@ func NewExpenseRepository(db *sql.DB) repo.ExpenseRepository {
}
// DeleteExpense implements repo.ExpenseRepository.
func (e *expenseRepository) DeleteExpense(ctx context.Context, expenseID int) error {
return e.queries.DeleteExpense(ctx, int32(expenseID))
func (e *expenseRepository) DeleteExpense(ctx context.Context, expenseID int, tx any) error {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
return queries.DeleteExpense(timeoutCtx, int32(expenseID))
}
// DeleteTransactionsOfExpense implements repo.ExpenseRepository.
func (e *expenseRepository) DeleteTransactionsOfExpense(ctx context.Context, expenseID int) error {
return e.queries.DeleteTransactionsOfExpenseID(ctx, int32(expenseID))
func (e *expenseRepository) DeleteTransactionsOfExpense(
ctx context.Context,
expenseID int,
tx any,
) error {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
return queries.DeleteTransactionsOfExpenseID(timeoutCtx, int32(expenseID))
}
// GetExpenseByID implements repo.ExpenseRepository.
func (e *expenseRepository) GetExpenseByID(
ctx context.Context,
expenseID int,
tx any,
) (*model.ExpenseRetrieved, error) {
expenseDTO, err := e.queries.GetExpenseByID(ctx, int32(expenseID))
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
expenseDTO, err := queries.GetExpenseByID(timeoutCtx, int32(expenseID))
if err != nil {
return nil, err
}
@ -79,15 +97,15 @@ func convToPayments(raw json.RawMessage) ([]model.Payment, error) {
return nil, err
}
var payments []model.Payment
for _, p := range paymentsRetrieved {
payments := make([]model.Payment, len(paymentsRetrieved))
for i, p := range paymentsRetrieved {
payment := model.Payment{
PayerID: p.PayerID,
PayerFirstName: p.PayerFirstName,
PayerLastName: p.PayerLastName,
Amount: model.MakeMoney(p.Amount, model.Currency(p.Currency)),
}
payments = append(payments, payment)
payments[i] = payment
}
return payments, nil
@ -102,15 +120,15 @@ func convToBenefits(raw json.RawMessage) ([]model.Benefit, error) {
return nil, err
}
var benefits []model.Benefit
for _, b := range benefitsRetrieved {
benefits := make([]model.Benefit, len(benefitsRetrieved))
for i, b := range benefitsRetrieved {
benefit := model.Benefit{
RecipientID: b.RecipientID,
RecipientFirstName: b.RecipientFirstName,
RecipientLastName: b.RecipientLastName,
Amount: model.MakeMoney(b.Amount, model.Currency(b.Currency)),
}
benefits = append(benefits, benefit)
benefits[i] = benefit
}
return benefits, nil
@ -150,8 +168,14 @@ func convToExpenseRetrieved(expenseDTO *sqlc.GetExpenseByIDRow) (*model.ExpenseR
func (e *expenseRepository) InsertExpense(
ctx context.Context,
expenseEntity *model.ExpenseEntity,
tx any,
) (*model.ExpenseEntity, error) {
expenseDTO, err := e.queries.InsertExpense(ctx, sqlc.InsertExpenseParams{
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
expenseDTO, err := queries.InsertExpense(timeoutCtx, sqlc.InsertExpenseParams{
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Amount: int32(expenseEntity.Amount),
@ -179,13 +203,19 @@ func (e *expenseRepository) InsertExpense(
func (e *expenseRepository) ListExpensesByEventID(
ctx context.Context,
id int,
tx any,
) ([]model.ExpensesListRetrieved, error) {
listDTO, err := e.queries.ListExpensesByEventID(ctx, int32(id))
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
listDTO, err := queries.ListExpensesByEventID(timeoutCtx, int32(id))
if err != nil {
return nil, err
}
var res []model.ExpensesListRetrieved
for _, dto := range listDTO {
res := make([]model.ExpensesListRetrieved, len(listDTO))
for i, dto := range listDTO {
elem := model.ExpensesListRetrieved{
ID: int(dto.ID),
CreatedAt: dto.CreatedAt,
@ -197,7 +227,7 @@ func (e *expenseRepository) ListExpensesByEventID(
Place: dto.Place.String,
},
}
res = append(res, elem)
res[i] = elem
}
return res, nil
}
@ -206,8 +236,14 @@ func (e *expenseRepository) ListExpensesByEventID(
func (e *expenseRepository) UpdateExpenseByID(
ctx context.Context,
expenseUpdate *model.ExpenseUpdateEntity,
tx any,
) (*model.ExpenseEntity, error) {
expenseDTO, err := e.queries.UpdateExpenseByID(ctx, sqlc.UpdateExpenseByIDParams{
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(e.queries, tx)
expenseDTO, err := queries.UpdateExpenseByID(timeoutCtx, sqlc.UpdateExpenseByIDParams{
ID: int32(expenseUpdate.ID),
UpdatedAt: time.Now(),
Amount: int32(expenseUpdate.Amount),

View File

@ -3,3 +3,8 @@ INSERT INTO participation (
user_id, event_id, invited_by_user_id, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5)
RETURNING *;
-- name: GetParticipation :one
SELECT id, user_id, event_id, invited_by_user_id, created_at, updated_at
FROM "participation"
WHERE user_id = $1 AND event_id = $2;

View File

@ -11,6 +11,31 @@ import (
"time"
)
const getParticipation = `-- name: GetParticipation :one
SELECT id, user_id, event_id, invited_by_user_id, created_at, updated_at
FROM "participation"
WHERE user_id = $1 AND event_id = $2
`
type GetParticipationParams struct {
UserID int32
EventID int32
}
func (q *Queries) GetParticipation(ctx context.Context, arg GetParticipationParams) (Participation, error) {
row := q.db.QueryRowContext(ctx, getParticipation, arg.UserID, arg.EventID)
var i Participation
err := row.Scan(
&i.ID,
&i.UserID,
&i.EventID,
&i.InvitedByUserID,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const insertParticipation = `-- name: InsertParticipation :one
INSERT INTO participation (
user_id, event_id, invited_by_user_id, created_at, updated_at

View File

@ -13,6 +13,7 @@ type Querier interface {
DeleteTransactionsOfExpenseID(ctx context.Context, expenseID int32) error
GetEventByID(ctx context.Context, id int32) (GetEventByIDRow, error)
GetExpenseByID(ctx context.Context, id int32) (GetExpenseByIDRow, error)
GetParticipation(ctx context.Context, arg GetParticipationParams) (Participation, error)
GetUserByEmail(ctx context.Context, email string) (User, error)
GetUserByID(ctx context.Context, id int32) (User, error)
InsertEvent(ctx context.Context, arg InsertEventParams) (Event, error)

View File

@ -34,43 +34,34 @@ import (
)
type userRepository struct {
querier *sqlc.Queries
queries *sqlc.Queries
}
const insertTimeout = 1 * time.Second
func NewUserRepository(db *sql.DB) repo.UserRepository {
return &userRepository{
querier: sqlc.New(db),
queries: sqlc.New(db),
}
}
// Create
func (ur *userRepository) Create(
func (u *userRepository) Create(
ctx context.Context,
transaction interface{},
u *model.UserEntity,
userEntity *model.UserEntity,
tx any,
) (*model.UserEntity, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, insertTimeout)
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
args := sqlc.InsertUserParams{
Email: u.Email,
FirstName: u.FirstName,
LastName: u.LastName,
Password: u.Password,
queries := getQueries(u.queries, tx)
userDB, err := queries.InsertUser(timeoutCtx, sqlc.InsertUserParams{
Email: userEntity.Email,
FirstName: userEntity.FirstName,
LastName: userEntity.LastName,
Password: userEntity.Password,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
tx, ok := transaction.(*sql.Tx)
if !ok {
return nil, errors.New("transaction is not a *sql.Tx")
}
queries := sqlc.New(tx)
userDB, err := queries.InsertUser(timeoutCtx, args)
})
if err != nil {
return nil, err
}
@ -87,8 +78,17 @@ func (ur *userRepository) Create(
}
// GetByEmail if not found, return nil for user but not error.
func (ur *userRepository) GetByEmail(ctx context.Context, email string) (*model.UserEntity, error) {
userDB, err := ur.querier.GetUserByEmail(ctx, email)
func (u *userRepository) GetByEmail(
ctx context.Context,
email string,
tx any,
) (*model.UserEntity, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(u.queries, tx)
userDB, err := queries.GetUserByEmail(timeoutCtx, email)
if errors.Is(err, sql.ErrNoRows) {
// No query error, but user not found
return nil, nil
@ -107,8 +107,13 @@ func (ur *userRepository) GetByEmail(ctx context.Context, email string) (*model.
}, nil
}
func (ur *userRepository) GetByID(ctx context.Context, id int) (*model.UserEntity, error) {
userDB, err := ur.querier.GetUserByID(ctx, int32(id))
func (u *userRepository) GetByID(ctx context.Context, id int, tx any) (*model.UserEntity, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout)
defer cancel()
queries := getQueries(u.queries, tx)
userDB, err := queries.GetUserByID(timeoutCtx, int32(id))
if errors.Is(err, sql.ErrNoRows) {
// No query error, but user not found
return nil, nil

View File

@ -36,7 +36,7 @@ type EventCreateRequest struct {
// }}}
// {{{ Response View Object (from service to controller)
type EventBaseItemResponse struct {
type EventListResponse struct {
ID int
Name string
Description string

View File

@ -29,30 +29,46 @@ import (
)
type EventRepository interface {
Create(ctx context.Context, evEntity *model.EventEntity) (*model.EventEntity, error)
Create(ctx context.Context, evEntity *model.EventEntity, tx any) (*model.EventEntity, error)
// UpdateEventByID updates the event related information (name, descriptions)
UpdateEventByID(ctx context.Context, event *model.EventUpdateEntity) error
UpdateEventByID(ctx context.Context, event *model.EventUpdateEntity, tx any) error
GetByID(ctx context.Context, eventID int) (*model.EventRetrieved, error)
GetByID(ctx context.Context, eventID int, tx any) (*model.EventRetrieved, error)
// related to events of a user
ListEventsByUserID(ctx context.Context, userID int) ([]model.EventListRetrieved, error)
ListEventsByUserID(ctx context.Context, userID int, tx any) ([]model.EventListRetrieved, error)
// CheckParticipation(ctx context.Context, userID, eventID int) error
InsertParticipation(
ctx context.Context,
userID, eventID, invitedByUserID int,
tx any,
) (*model.ParticipationEntity, error)
GetParticipation(
ctx context.Context,
userID, eventID int,
tx any,
) (*model.ParticipationEntity, error)
}
type ExpenseRepository interface {
DeleteExpense(ctx context.Context, expenseID int) error
DeleteTransactionsOfExpense(ctx context.Context, expenseID int) error
GetExpenseByID(ctx context.Context, expenseID int) (*model.ExpenseRetrieved, error)
DeleteExpense(ctx context.Context, expenseID int, tx any) error
DeleteTransactionsOfExpense(ctx context.Context, expenseID int, tx any) error
GetExpenseByID(ctx context.Context, expenseID int, tx any) (*model.ExpenseRetrieved, error)
InsertExpense(
ctx context.Context,
expenseEntity *model.ExpenseEntity,
tx any,
) (*model.ExpenseEntity, error)
ListExpensesByEventID(ctx context.Context, id int) ([]model.ExpensesListRetrieved, error)
ListExpensesByEventID(
ctx context.Context,
id int,
tx any,
) ([]model.ExpensesListRetrieved, error)
UpdateExpenseByID(
ctx context.Context,
expenseUpdate *model.ExpenseUpdateEntity,
tx any,
) (*model.ExpenseEntity, error)
}

View File

@ -31,9 +31,9 @@ import (
type UserRepository interface {
Create(
ctx context.Context,
transaction interface{},
u *model.UserEntity,
tx any,
) (*model.UserEntity, error)
GetByEmail(ctx context.Context, email string) (*model.UserEntity, error)
GetByID(ctx context.Context, id int) (*model.UserEntity, error)
GetByEmail(ctx context.Context, email string, tx any) (*model.UserEntity, error)
GetByID(ctx context.Context, id int, tx any) (*model.UserEntity, error)
}

View File

@ -62,7 +62,7 @@ func (evuc *eventUsecase) CreateEvent(
ctx context.Context,
evRequest *model.EventCreateRequest,
) (*model.EventInfoResponse, error) {
// transfer evRequest to PO
// transfer evRequest to evEntity
evEntity := &model.EventEntity{
Name: evRequest.Name,
@ -74,12 +74,37 @@ func (evuc *eventUsecase) CreateEvent(
data, err := evuc.dbRepo.Transaction(
ctx,
func(txCtx context.Context, tx interface{}) (interface{}, error) {
created, err := evuc.eventRepo.Create(ctx, evEntity)
func(txCtx context.Context, tx any) (any, error) {
// Create the event
created, err := evuc.eventRepo.Create(ctx, evEntity, tx)
if err != nil {
return nil, err
}
// participate to the event
participation, err := evuc.eventRepo.InsertParticipation(
ctx,
created.OwnerID,
created.ID,
0,
tx,
)
if err != nil {
return nil, err
}
if participation == nil {
// Unexpected error
log.ErrorLog(
"participation existed for event-user pair",
"userID",
created.OwnerID,
"eventID",
created.ID,
)
return nil, errno.InternalServerErr
}
// TODO: App log, maybe can be sent to some third party service.
log.InfoLog(
"created new event",
@ -89,6 +114,7 @@ func (evuc *eventUsecase) CreateEvent(
created.OwnerID,
)
// Construct the response
ownerResponse, err := evuc.userUC.GetUserBaseResponseByID(ctx, created.OwnerID)
if err != nil {
return nil, err
@ -104,9 +130,12 @@ func (evuc *eventUsecase) CreateEvent(
),
Owner: ownerResponse,
CreatedAt: created.CreatedAt,
UpdatedAt: created.UpdatedAt,
Users: []model.UserBaseResponse{*ownerResponse},
}
return evResponse, err
})
},
)
if err != nil {
return nil, err
}
@ -119,8 +148,28 @@ func (evuc *eventUsecase) CreateEvent(
func (evuc *eventUsecase) ListEvents(
ctx context.Context,
userID int,
) ([]model.EventBaseItemResponse, error) {
return nil, nil
) ([]model.EventListResponse, error) {
eventListRetrieved, err := evuc.eventRepo.ListEventsByUserID(ctx, userID, nil)
if err != nil {
return nil, err
}
// Check if the user is a member of the event
responses := make([]model.EventListResponse, len(eventListRetrieved))
for i, retrieved := range eventListRetrieved {
ownner := model.UserBaseResponse(*retrieved.Owner)
res := model.EventListResponse{
ID: retrieved.ID,
Name: retrieved.Name,
Description: retrieved.Description,
Owner: &ownner,
CreatedAt: retrieved.CreatedAt,
}
responses[i] = res
}
return responses, nil
}
// GetEventDetail

View File

@ -36,8 +36,8 @@ type TestUserRepository struct{}
func (tur *TestUserRepository) Create(
ctx context.Context,
transaction interface{},
u *model.UserEntity,
tx any,
) (*model.UserEntity, error) {
user := *u
@ -53,6 +53,7 @@ func (tur *TestUserRepository) Create(
func (tur *TestUserRepository) GetByEmail(
ctx context.Context,
email string,
tx any,
) (*model.UserEntity, error) {
hashedPwd, _ := bcrypt.GenerateFromPassword([]byte("strongHashed"), 12)
switch email {
@ -71,7 +72,11 @@ func (tur *TestUserRepository) GetByEmail(
return nil, UserTestDummyErr
}
func (tur *TestUserRepository) GetByID(ctx context.Context, id int) (*model.UserEntity, error) {
func (tur *TestUserRepository) GetByID(
ctx context.Context,
id int,
tx any,
) (*model.UserEntity, error) {
hashedPwd, _ := bcrypt.GenerateFromPassword([]byte("strongHashed"), 12)
switch id {
case 123:

View File

@ -86,12 +86,12 @@ func (uuc *userUsecase) Create(
data, err := uuc.dbRepo.Transaction(
ctx,
func(txCtx context.Context, tx interface{}) (interface{}, error) {
created, err := uuc.userRepo.Create(txCtx, tx, &model.UserEntity{
created, err := uuc.userRepo.Create(txCtx, &model.UserEntity{
Email: u.Email,
Password: u.Password,
FirstName: u.FirstName,
LastName: u.LastName,
})
}, tx)
if err != nil {
match, _ := regexp.MatchString("SQLSTATE 23505", err.Error())
if match {
@ -132,7 +132,7 @@ func (uuc *userUsecase) Create(
}
func (uuc *userUsecase) Exist(ctx context.Context, u *model.UserExistRequest) error {
got, err := uuc.userRepo.GetByEmail(ctx, u.Email)
got, err := uuc.userRepo.GetByEmail(ctx, u.Email, nil)
// Any query error?
if err != nil {
return err
@ -160,7 +160,7 @@ func (uuc *userUsecase) GetUserBaseResponseByID(
// If not exists, get from the DB. And then put back
// into the cache with a timeout.
// Refresh the cache when the user data is updated (for now it cannot be updated)
got, err := uuc.userRepo.GetByID(ctx, userID)
got, err := uuc.userRepo.GetByID(ctx, userID, nil)
if err != nil {
return nil, err
}