Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions app/controller/base_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ func (bc *BaseController[T]) Add(w http.ResponseWriter, r *http.Request) {
u.SetUpdatedAt(now)
}

if err := bc.Repo.Add(m); err != nil {
ctx := helper.GetContextWithoutCancel(r)

if err := bc.Repo.AddContext(ctx, m); err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Insert error", err)
return
}
Expand Down Expand Up @@ -93,7 +95,9 @@ func (bc *BaseController[T]) Bulk(w http.ResponseWriter, r *http.Request) {
}
fields := helper.GetFieldsParamList(r, bc.Repo.New().Columns(), orderBy)

list, err := bc.Repo.Bulk(input.IDs, limit, pageCursor, orderBy, order, fields)
ctx := helper.GetContextWithoutCancel(r)

list, err := bc.Repo.BulkContext(ctx, input.IDs, limit, pageCursor, orderBy, order, fields)
if err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Bulk error", err)
return
Expand Down Expand Up @@ -149,7 +153,9 @@ func (bc *BaseController[T]) BulkAdd(w http.ResponseWriter, r *http.Request) {
}
}

if err := bc.Repo.BulkAdd(items); err != nil {
ctx := helper.GetContextWithoutCancel(r)

if err := bc.Repo.BulkAddContext(ctx, items); err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Bulk insert failed", err)
return
}
Expand All @@ -171,8 +177,9 @@ func (bc *BaseController[T]) DeadDetail(w http.ResponseWriter, r *http.Request)
return
}

ctx := helper.GetContextWithoutCancel(r)
fields := helper.GetFieldsParamOne(r, bc.Repo.New().Columns())
m, err := bc.Repo.DeadDetail(id, fields)
m, err := bc.Repo.DeadDetailContext(ctx, id, fields)
if err != nil {
helper.JSONError(w, http.StatusNotFound, "Detail error", err)
return
Expand All @@ -196,7 +203,9 @@ func (bc *BaseController[T]) DeadList(w http.ResponseWriter, r *http.Request) {
fields := helper.GetFieldsParamList(r, bc.Repo.New().Columns(), orderBy)
filters := helper.GetFilters(r, bc.Repo.New().Columns())

list, err := bc.Repo.DeadList(limit, pageCursor, orderBy, order, fields, filters)
ctx := helper.GetContextWithoutCancel(r)

list, err := bc.Repo.DeadListContext(ctx, limit, pageCursor, orderBy, order, fields, filters)
if err != nil {
helper.JSONError(w, http.StatusInternalServerError, "List error", err)
return
Expand All @@ -217,10 +226,11 @@ func (bc *BaseController[T]) Delete(w http.ResponseWriter, r *http.Request) {
return
}

ctx := helper.GetContextWithoutCancel(r)
m := bc.Repo.New()
bc.SetPK(m, id)

if err := bc.Repo.Delete(m); err != nil {
if err := bc.Repo.DeleteContext(ctx, m); err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Delete error", err)
return
}
Expand All @@ -240,8 +250,9 @@ func (bc *BaseController[T]) Detail(w http.ResponseWriter, r *http.Request) {
return
}

ctx := helper.GetContextWithoutCancel(r)
fields := helper.GetFieldsParamOne(r, bc.Repo.New().Columns())
m, err := bc.Repo.Detail(id, fields)
m, err := bc.Repo.DetailContext(ctx, id, fields)
if err != nil {
helper.JSONError(w, http.StatusNotFound, "Detail error", err)
return
Expand All @@ -268,7 +279,9 @@ func (bc *BaseController[T]) Edit(w http.ResponseWriter, r *http.Request) {
return
}

fetched, err := bc.Repo.Detail(id, bc.Repo.New().Columns())
ctx := helper.GetContextWithoutCancel(r)

fetched, err := bc.Repo.DetailContext(ctx, id, bc.Repo.New().Columns())
if err != nil {
helper.JSONError(w, http.StatusNotFound, "Not found", err)
return
Expand Down Expand Up @@ -298,7 +311,7 @@ func (bc *BaseController[T]) Edit(w http.ResponseWriter, r *http.Request) {
m := bc.Repo.New()
bc.SetPK(m, id)

if err := bc.Repo.Edit(m.TableName(), m.PrimaryKey(), m.PrimaryKeyValue(), updateCols, updateVals); err != nil {
if err := bc.Repo.EditContext(ctx, m.TableName(), m.PrimaryKey(), m.PrimaryKeyValue(), updateCols, updateVals); err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Edit error", err)
return
}
Expand All @@ -312,6 +325,7 @@ func (bc *BaseController[T]) List(w http.ResponseWriter, r *http.Request) {
return
}

ctx := helper.GetContextWithoutCancel(r)
orderBy, order := helper.GetOrderParams(r, "id")
limit, pageCursor, err := helper.GetPaginationParams(r)
if err != nil {
Expand All @@ -321,7 +335,7 @@ func (bc *BaseController[T]) List(w http.ResponseWriter, r *http.Request) {
fields := helper.GetFieldsParamList(r, bc.Repo.New().Columns(), orderBy)
filters := helper.GetFilters(r, bc.Repo.New().Columns())

list, err := bc.Repo.List(limit, pageCursor, orderBy, order, fields, filters)
list, err := bc.Repo.ListContext(ctx, limit, pageCursor, orderBy, order, fields, filters)
if err != nil {
helper.JSONError(w, http.StatusInternalServerError, "List error", err)
return
Expand All @@ -336,11 +350,12 @@ func (bc *BaseController[T]) ListOne(w http.ResponseWriter, r *http.Request) {
return
}

ctx := helper.GetContextWithoutCancel(r)
orderBy, order := helper.GetOrderParams(r, "id")
fields := helper.GetFieldsParamOne(r, bc.Repo.New().Columns())
filters := helper.GetFilters(r, bc.Repo.New().Columns())

result, err := bc.Repo.ListOne(orderBy, order, fields, filters)
result, err := bc.Repo.ListOneContext(ctx, orderBy, order, fields, filters)
if err != nil {
helper.JSONError(w, http.StatusInternalServerError, "List one error", err)
return
Expand Down Expand Up @@ -387,7 +402,8 @@ func (bc *BaseController[T]) Raw(w http.ResponseWriter, r *http.Request) {
return
}

results, err := bc.Repo.Raw(sqlText, input.Params)
ctx := helper.GetContextWithoutCancel(r)
results, err := bc.Repo.RawContext(ctx, sqlText, input.Params)
if err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Raw execution failed", err)
return
Expand All @@ -411,7 +427,8 @@ func (bc *BaseController[T]) Undelete(w http.ResponseWriter, r *http.Request) {
m := bc.Repo.New()
bc.SetPK(m, id)

if err := bc.Repo.Undelete(m); err != nil {
ctx := helper.GetContextWithoutCancel(r)
if err := bc.Repo.UndeleteContext(ctx, m); err != nil {
helper.JSONError(w, http.StatusInternalServerError, "Undelete error", err)
return
}
Expand Down
10 changes: 10 additions & 0 deletions app/helper/context_helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package helper

import (
"context"
"net/http"
)

func GetContextWithoutCancel(r *http.Request) context.Context {
return context.WithoutCancel(r.Context())
}
105 changes: 83 additions & 22 deletions app/repository/base_repository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package repository

import (
"context"
"database/sql"
"time"

Expand Down Expand Up @@ -48,6 +49,18 @@ type RepositoryInterface[T BaseModel] interface {
ListOne(orderBy, order string, fields []string, filters []helper.Filter) (map[string]any, error)
Raw(query string, params map[string]any) ([]map[string]any, error)
Undelete(m T) error
AddContext(ctx context.Context, m T) error
BulkContext(ctx context.Context, ids []string, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string) ([]map[string]any, error)
BulkAddContext(ctx context.Context, models []T) error
DeadDetailContext(ctx context.Context, id interface{}, fields []string) (map[string]any, error)
DeadListContext(ctx context.Context, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error)
DeleteContext(ctx context.Context, m T) error
DetailContext(ctx context.Context, id interface{}, fields []string) (map[string]any, error)
EditContext(ctx context.Context, table, pk string, pkVal interface{}, cols []string, vals []interface{}) error
ListContext(ctx context.Context, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error)
ListOneContext(ctx context.Context, orderBy, order string, fields []string, filters []helper.Filter) (map[string]any, error)
RawContext(ctx context.Context, query string, params map[string]any) ([]map[string]any, error)
UndeleteContext(ctx context.Context, m T) error
}

type Repository[T BaseModel] struct {
Expand All @@ -67,64 +80,112 @@ func (r *Repository[T]) New() T {
}

func (r *Repository[T]) Add(m T) error {
return addRecord(r.DB, m)
return r.AddContext(context.Background(), m)
}

func (r *Repository[T]) BulkAdd(m []T) error {
return r.BulkAddContext(context.Background(), m)
}

func (r *Repository[T]) Bulk(ids []string, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string) ([]map[string]any, error) {
return r.BulkContext(context.Background(), ids, limit, pageCursor, orderBy, order, fields)
}

func (r *Repository[T]) DeadDetail(id interface{}, fields []string) (map[string]any, error) {
return r.DeadDetailContext(context.Background(), id, fields)
}

func (r *Repository[T]) DeadList(limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error) {
return r.DeadListContext(context.Background(), limit, pageCursor, orderBy, order, fields, filters)
}

func (r *Repository[T]) Delete(m T) error {
return r.DeleteContext(context.Background(), m)
}

func (r *Repository[T]) Detail(id interface{}, fields []string) (map[string]any, error) {
return r.DetailContext(context.Background(), id, fields)
}

func (r *Repository[T]) Edit(table, pk string, pkVal interface{}, cols []string, vals []interface{}) error {
return r.EditContext(context.Background(), table, pk, pkVal, cols, vals)
}

func (r *Repository[T]) List(limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error) {
return r.ListContext(context.Background(), limit, pageCursor, orderBy, order, fields, filters)
}

func (r *Repository[T]) ListOne(orderBy, order string, fields []string, filters []helper.Filter) (map[string]any, error) {
return r.ListOneContext(context.Background(), orderBy, order, fields, filters)
}

func (r *Repository[T]) Raw(query string, params map[string]any) ([]map[string]any, error) {
return r.RawContext(context.Background(), query, params)
}

func (r *Repository[T]) Undelete(m T) error {
return r.UndeleteContext(context.Background(), m)
}

func (r *Repository[T]) AddContext(ctx context.Context, m T) error {
return addRecord(ctx, r.DB, m)
}

func (r *Repository[T]) BulkAddContext(ctx context.Context, m []T) error {
baseModels := make([]BaseModel, len(m))
for i, model := range m {
baseModels[i] = model
}
return bulkAddRecords(r.DB, baseModels)
return bulkAddRecords(ctx, r.DB, baseModels)
}

func (r *Repository[T]) Bulk(ids []string, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string) ([]map[string]any, error) {
func (r *Repository[T]) BulkContext(ctx context.Context, ids []string, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string) ([]map[string]any, error) {
m := r.New()
return bulkRecords(r.DB, m.Schema(), m.TableName(), m.PrimaryKey(), fields, ids, limit, pageCursor, orderBy, order)
return bulkRecords(ctx, r.DB, m.Schema(), m.TableName(), m.PrimaryKey(), fields, ids, limit, pageCursor, orderBy, order)
}

func (r *Repository[T]) DeadDetail(id interface{}, fields []string) (map[string]any, error) {
func (r *Repository[T]) DeadDetailContext(ctx context.Context, id interface{}, fields []string) (map[string]any, error) {
m := r.New()
return getRecord(r.DB, id, m.Schema(), m.TableName(), m.PrimaryKey(), fields, true)
return getRecord(ctx, r.DB, id, m.Schema(), m.TableName(), m.PrimaryKey(), fields, true)
}

func (r *Repository[T]) DeadList(limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error) {
func (r *Repository[T]) DeadListContext(ctx context.Context, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error) {
m := r.New()
return listRecords(r.DB, m.Schema(), m.TableName(), fields, limit, pageCursor, orderBy, order, filters, true)
return listRecords(ctx, r.DB, m.Schema(), m.TableName(), fields, limit, pageCursor, orderBy, order, filters, true)
}

func (r *Repository[T]) Delete(m T) error {
return deleteRecord(r.DB, m.TableName(), m.PrimaryKey(), m.PrimaryKeyValue())
func (r *Repository[T]) DeleteContext(ctx context.Context, m T) error {
return deleteRecord(ctx, r.DB, m.TableName(), m.PrimaryKey(), m.PrimaryKeyValue())
}

func (r *Repository[T]) Detail(id interface{}, fields []string) (map[string]any, error) {
func (r *Repository[T]) DetailContext(ctx context.Context, id interface{}, fields []string) (map[string]any, error) {
m := r.New()
return getRecord(r.DB, id, m.Schema(), m.TableName(), m.PrimaryKey(), fields, false)
return getRecord(ctx, r.DB, id, m.Schema(), m.TableName(), m.PrimaryKey(), fields, false)
}

func (r *Repository[T]) Edit(table, pk string, pkVal interface{}, cols []string, vals []interface{}) error {
return editRecord(r.DB, table, pk, pkVal, cols, vals)
func (r *Repository[T]) EditContext(ctx context.Context, table, pk string, pkVal interface{}, cols []string, vals []interface{}) error {
return editRecord(ctx, r.DB, table, pk, pkVal, cols, vals)
}

func (r *Repository[T]) List(limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error) {
func (r *Repository[T]) ListContext(ctx context.Context, limit int, pageCursor *helper.PageCursor, orderBy, order string, fields []string, filters []helper.Filter) ([]map[string]any, error) {
m := r.New()
return listRecords(r.DB, m.Schema(), m.TableName(), fields, limit, pageCursor, orderBy, order, filters, false)
return listRecords(ctx, r.DB, m.Schema(), m.TableName(), fields, limit, pageCursor, orderBy, order, filters, false)
}

func (r *Repository[T]) ListOne(orderBy, order string, fields []string, filters []helper.Filter) (map[string]any, error) {
results, err := r.List(1, nil, orderBy, order, fields, filters)
func (r *Repository[T]) ListOneContext(ctx context.Context, orderBy, order string, fields []string, filters []helper.Filter) (map[string]any, error) {
results, err := r.ListContext(ctx, 1, nil, orderBy, order, fields, filters)
if len(results) == 0 {
return make(map[string]any), err
}
return results[0], err
}

func (r *Repository[T]) Raw(query string, params map[string]any) ([]map[string]any, error) {
func (r *Repository[T]) RawContext(ctx context.Context, query string, params map[string]any) ([]map[string]any, error) {
m := r.New()
sqlText, args := helper.PrepareRawQuery(query, params)
return rawRecords(r.DB, m.Schema(), sqlText, args...)
return rawRecords(ctx, r.DB, m.Schema(), sqlText, args...)
}

func (r *Repository[T]) Undelete(m T) error {
return undeleteRecord(r.DB, m.TableName(), m.PrimaryKey(), m.PrimaryKeyValue())
func (r *Repository[T]) UndeleteContext(ctx context.Context, m T) error {
return undeleteRecord(ctx, r.DB, m.TableName(), m.PrimaryKey(), m.PrimaryKeyValue())
}
Loading