refactor mw example

This commit is contained in:
dpurbosakti
2025-08-21 16:24:48 +07:00
parent 5c716eb269
commit 7a032ff518
5 changed files with 324 additions and 153 deletions
+45 -153
View File
@@ -1,7 +1,6 @@
package user
import (
"fmt"
e "simrs-vx/internal/domain/main-entities/user"
"strconv"
@@ -30,22 +29,12 @@ func Create(input e.CreateDto) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "create")
err := dg.I.Transaction(func(tx *gorm.DB) error {
for i := range createPreMw {
mwName := fmt.Sprintf("createPreMw[%d]", i)
executor := newMiddlewareExecutor(&event, tx)
executor.setMwtype(pu.MWTPre)
pl.SetLogInfo(&event, data, "started", mwName)
if err := createPreMw[i](&input, &data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_PRE_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Pre-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(&event, nil, "complete")
// Execute pre-middleware
if err := executor.ExecuteCreateMiddleware(createPreMw, &input, &data); err != nil {
return err
}
pl.SetLogInfo(&event, data, "started", "DBCreate")
@@ -62,19 +51,10 @@ func Create(input e.CreateDto) (*d.Data, error) {
pl.SetLogInfo(&event, nil, "complete")
for i := range createPostMw {
mwName := fmt.Sprintf("createPostMw[%d]", i)
pl.SetLogInfo(&event, input, "started", mwName)
if err := createPostMw[i](&input, &data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_POST_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Post-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
executor.setMwtype(pu.MWTPost)
// Execute post-middleware
if err := executor.ExecuteCreateMiddleware(createPostMw, &input, &data); err != nil {
return err
}
pl.SetLogInfo(&event, nil, "complete")
@@ -111,22 +91,12 @@ func ReadList(input e.ReadListDto) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "readList")
err = dg.I.Transaction(func(tx *gorm.DB) error {
for i := range readListPreMw {
mwName := fmt.Sprintf("readListPreMw[%d]", i)
executor := newMiddlewareExecutor(&event, tx)
executor.setMwtype(pu.MWTPre)
pl.SetLogInfo(&event, input, "started", mwName)
if err := readListPreMw[i](&input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_PRE_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Pre-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, input)
}
pl.SetLogInfo(&event, nil, "complete")
// Execute pre-middleware
if err := executor.ExecuteReadListMiddleware(readListPreMw, &input, data); err != nil {
return err
}
pl.SetLogInfo(&event, input, "started", "DBReadList")
@@ -143,22 +113,10 @@ func ReadList(input e.ReadListDto) (*d.Data, error) {
pl.SetLogInfo(&event, nil, "complete")
for i := range readListPostMw {
mwName := fmt.Sprintf("readListPostMw[%d]", i)
pl.SetLogInfo(&event, input, "started", mwName)
if err := readListPostMw[i](&input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_POST_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Post-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, input)
}
pl.SetLogInfo(&event, nil, "complete")
executor.setMwtype(pu.MWTPost)
// Execute post-middleware
if err := executor.ExecuteReadListMiddleware(readListPostMw, &input, data); err != nil {
return err
}
return nil
@@ -194,22 +152,12 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "readDetail")
err = dg.I.Transaction(func(tx *gorm.DB) error {
for i := range readDetailPreMw {
mwName := fmt.Sprintf("readDetailPreMw[%d]", i)
executor := newMiddlewareExecutor(&event, tx)
executor.setMwtype(pu.MWTPre)
pl.SetLogInfo(&event, input, "started", mwName)
if err := readDetailPreMw[i](&input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_PRE_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Pre-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, input)
}
pl.SetLogInfo(&event, nil, "complete")
// Execute pre-middleware
if err := executor.ExecuteReadDetailMiddleware(readDetailPreMw, &input, data); err != nil {
return err
}
pl.SetLogInfo(&event, input, "started", "DBReadDetail")
@@ -218,22 +166,10 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) {
return processedErr
}
for i := range readDetailPostMw {
mwName := fmt.Sprintf("readDetailPostMw[%d]", i)
pl.SetLogInfo(&event, data, "started", mwName)
if err := readDetailPostMw[i](&input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_POST_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Post-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(&event, nil, "complete")
executor.setMwtype(pu.MWTPost)
// Execute post-middleware
if err := executor.ExecuteReadDetailMiddleware(readDetailPostMw, &input, data); err != nil {
return err
}
return nil
@@ -287,22 +223,12 @@ func Update(input e.UpdateDto) (*d.Data, error) {
pl.SetLogInfo(&event, nil, "complete")
for i := range updatePreMw {
mwName := fmt.Sprintf("updatePreMw[%d]", i)
executor := newMiddlewareExecutor(&event, tx)
executor.setMwtype(pu.MWTPre)
pl.SetLogInfo(&event, data, "started", mwName)
if err := updatePreMw[i](&rdDto, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_PRE_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Pre-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(&event, nil, "complete")
// Execute pre-middleware
if err := executor.ExecuteUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil {
return err
}
pl.SetLogInfo(&event, data, "started", "DBUpdate")
@@ -318,22 +244,10 @@ func Update(input e.UpdateDto) (*d.Data, error) {
pl.SetLogInfo(&event, nil, "complete")
for i := range updatePostMw {
mwName := fmt.Sprintf("updatePostMw[%d]", i)
pl.SetLogInfo(&event, data, "started", mwName)
if err := updatePostMw[i](&rdDto, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_POST_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Post-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(&event, nil, "complete")
executor.setMwtype(pu.MWTPost)
// Execute post-middleware
if err := executor.ExecuteUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil {
return err
}
return nil
@@ -374,22 +288,12 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
return processedErr
}
for i := range deletePreMw {
mwName := fmt.Sprintf("deletePreMw[%d]", i)
executor := newMiddlewareExecutor(&event, tx)
executor.setMwtype(pu.MWTPre)
pl.SetLogInfo(&event, data, "started", mwName)
if err := deletePreMw[i](&rdDto, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_PRE_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Pre-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(&event, nil, "complete")
// Execute pre-middleware
if err := executor.ExecuteDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil {
return err
}
pl.SetLogInfo(&event, data, "started", "DBDelete")
@@ -405,22 +309,10 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
pl.SetLogInfo(&event, nil, "complete")
for i := range deletePostMw {
mwName := fmt.Sprintf("deletePostMw[%d]", i)
pl.SetLogInfo(&event, data, "started", mwName)
if err := deletePostMw[i](&rdDto, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "MW_POST_FAILED", // TODO: add to lang json
Detail: fmt.Sprintf("Post-middleware %s failed", mwName),
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(&event, nil, "complete")
executor.setMwtype(pu.MWTPost)
// Execute post-middleware
if err := executor.ExecuteDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil {
return err
}
return nil
@@ -5,9 +5,13 @@ Any functions that are used internally by the use-case
package user
import (
"fmt"
e "simrs-vx/internal/domain/main-entities/user"
pl "simrs-vx/pkg/logger"
p "simrs-vx/pkg/password"
"gorm.io/gorm"
)
func setCreate(src e.CreateDto, dst *e.User) error {
@@ -29,3 +33,103 @@ func setUpdate(src e.UpdateDto, dst *e.User) error {
return nil
}
// executeCreateMiddleware executes create middleware (pre or post)
func executeCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.User, tx *gorm.DB, event *pl.Event, mwType string) error {
for i := range middlewares {
mwName := fmt.Sprintf("%s[%d]", mwType, i)
pl.SetLogInfo(event, data, "started", mwName)
if err := middlewares[i](input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: getMiddlewareErrorCode(mwType),
Detail: fmt.Sprintf("%s middleware %s failed", getMiddlewareTypeLabel(mwType), mwName),
Raw: err,
}
return pl.SetLogError(*event, data)
}
pl.SetLogInfo(event, nil, "complete")
}
return nil
}
// executeReadListMiddleware executes read list middleware (pre or post)
func executeReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.User, tx *gorm.DB, event *pl.Event, mwType string) error {
for i := range middlewares {
mwName := fmt.Sprintf("%s[%d]", mwType, i)
pl.SetLogInfo(event, input, "started", mwName)
if err := middlewares[i](input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: getMiddlewareErrorCode(mwType),
Detail: fmt.Sprintf("%s middleware %s failed", getMiddlewareTypeLabel(mwType), mwName),
Raw: err,
}
return pl.SetLogError(*event, input)
}
pl.SetLogInfo(event, nil, "complete")
}
return nil
}
// executeReadDetailMiddleware executes read detail middleware (pre or post)
func executeReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User, tx *gorm.DB, event *pl.Event, mwType string) error {
for i := range middlewares {
mwName := fmt.Sprintf("%s[%d]", mwType, i)
// Use data for logging if available, otherwise use input
logData := interface{}(input)
if data != nil {
logData = data
}
pl.SetLogInfo(event, logData, "started", mwName)
if err := middlewares[i](input, data, tx); err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: getMiddlewareErrorCode(mwType),
Detail: fmt.Sprintf("%s middleware %s failed", getMiddlewareTypeLabel(mwType), mwName),
Raw: err,
}
return pl.SetLogError(*event, logData)
}
pl.SetLogInfo(event, nil, "complete")
}
return nil
}
// Helper functions to determine error codes and labels based on middleware type
func getMiddlewareErrorCode(mwType string) string {
if containsString(mwType, "Pre") {
return "MW_PRE_FAILED"
}
return "MW_POST_FAILED"
}
func getMiddlewareTypeLabel(mwType string) string {
if containsString(mwType, "Pre") {
return "Pre"
}
return "Post"
}
func containsString(str, substr string) bool {
return len(str) >= len(substr) && str[len(str)-len(substr):] != substr &&
(len(str) == len(substr) || str[len(str)-len(substr)-1:len(str)-len(substr)] != substr) &&
func() bool {
for i := 0; i <= len(str)-len(substr); i++ {
if str[i:i+len(substr)] == substr {
return true
}
}
return false
}()
}
@@ -0,0 +1,159 @@
package user
// pm "simrs-vx/internal/use-case/plugin/modifier"
import (
"fmt"
e "simrs-vx/internal/domain/main-entities/user"
pl "simrs-vx/pkg/logger"
pu "simrs-vx/pkg/use-case-helper"
"gorm.io/gorm"
)
// func init() {
// createPreMw = append(createPreMw, pm.ModifInput)
// createPreMw = append(createPreMw, pm.CheckData)
// }
type middlewareExecutor struct {
Event *pl.Event
Tx *gorm.DB
MwType pu.MWType
}
// NewMiddlewareExecutor creates a new middleware executor
func newMiddlewareExecutor(event *pl.Event, tx *gorm.DB) *middlewareExecutor {
return &middlewareExecutor{
Event: event,
Tx: tx,
}
}
// ExecuteCreateMiddleware executes create middleware
func (me *middlewareExecutor) ExecuteCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.User) error {
for i, middleware := range middlewares {
mwName := fmt.Sprintf("%s[%d]", me.MwType, i)
pl.SetLogInfo(me.Event, data, "started", mwName)
if err := middleware(input, data, me.Tx); err != nil {
me.Event.Status = "failed"
me.Event.ErrInfo = pl.ErrorInfo{
Code: pu.GetMiddlewareErrorCode(me.MwType),
Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName),
Raw: err,
}
return pl.SetLogError(*me.Event, data)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareExecutor) ExecuteReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.User) error {
for i, middleware := range middlewares {
mwName := fmt.Sprintf("%s[%d]", me.MwType, i)
pl.SetLogInfo(me.Event, input, "started", mwName)
if err := middleware(input, data, me.Tx); err != nil {
me.Event.Status = "failed"
me.Event.ErrInfo = pl.ErrorInfo{
Code: pu.GetMiddlewareErrorCode(me.MwType),
Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName),
Raw: err,
}
return pl.SetLogError(*me.Event, input)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareExecutor) ExecuteReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User) error {
for i, middleware := range middlewares {
mwName := fmt.Sprintf("%s[%d]", me.MwType, i)
// Use data for logging if available, otherwise use input
logData := interface{}(input)
if data != nil {
logData = data
}
pl.SetLogInfo(me.Event, logData, "started", mwName)
if err := middleware(input, data, me.Tx); err != nil {
me.Event.Status = "failed"
me.Event.ErrInfo = pl.ErrorInfo{
Code: pu.GetMiddlewareErrorCode(me.MwType),
Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName),
Raw: err,
}
return pl.SetLogError(*me.Event, logData)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareExecutor) ExecuteUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User) error {
for i, middleware := range middlewares {
mwName := fmt.Sprintf("%s[%d]", me.MwType, i)
// Use data for logging if available, otherwise use input
logData := interface{}(input)
if data != nil {
logData = data
}
pl.SetLogInfo(me.Event, logData, "started", mwName)
if err := middleware(input, data, me.Tx); err != nil {
me.Event.Status = "failed"
me.Event.ErrInfo = pl.ErrorInfo{
Code: pu.GetMiddlewareErrorCode(me.MwType),
Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName),
Raw: err,
}
return pl.SetLogError(*me.Event, logData)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareExecutor) ExecuteDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User) error {
for i, middleware := range middlewares {
mwName := fmt.Sprintf("%s[%d]", me.MwType, i)
// Use data for logging if available, otherwise use input
logData := interface{}(input)
if data != nil {
logData = data
}
pl.SetLogInfo(me.Event, logData, "started", mwName)
if err := middleware(input, data, me.Tx); err != nil {
me.Event.Status = "failed"
me.Event.ErrInfo = pl.ErrorInfo{
Code: pu.GetMiddlewareErrorCode(me.MwType),
Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName),
Raw: err,
}
return pl.SetLogError(*me.Event, logData)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareExecutor) setMwtype(mwType pu.MWType) {
me.MwType = mwType
}
+8
View File
@@ -0,0 +1,8 @@
package usecasehelper
type MWType string
const (
MWTPre MWType = "Pre"
MWTPost MWType = "Post"
)
+8
View File
@@ -3,6 +3,7 @@ package usecasehelper
import (
"errors"
"fmt"
"strings"
pl "simrs-vx/pkg/logger"
@@ -46,3 +47,10 @@ func HandleReadError(err error, event *pl.Event, itemType string, id interface{}
return pl.SetLogError(*event, nil)
}
func GetMiddlewareErrorCode(mwType MWType) string {
if strings.Contains(string(mwType), "Pre") {
return "MW_PRE_FAILED"
}
return "MW_POST_FAILED"
}