absmach / magistrala

Industrial IoT Messaging and Device Management Platform

Home Page:https://www.abstractmachines.fr/magistrala.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Handle other layers (repo ,cache , auth) error in service layer

arvindh123 opened this issue · comments

Is your feature request related to a problem? Please describe.

Due to #2117 , API doesn't return proper error.

Describe the feature you are requesting, as well as the possible use case(s) for it.

We can have some common functions which can better handle and wrap the other layer errors like (repo, auth, cache layer error) , which can be called service layer and wrapped

Example

// This can be moved to common package and it can be used by other service. 
func handleRepoErr(err error, fallbackErrWrapper error) error {
	switch {
	case errors.Contains(repoerr.ErrNotFound, err):
		return errors.Wrap(svcerr.ErrNotFound, err)
	case errors.Contains(repoerr.ErrConflict, err):
		return errors.Wrap(svcerr.ErrConflict, err)
	default:
		return errors.Wrap(fallbackErrWrapper, err)
	}
}

func (svc service) UpdateClientRole(ctx context.Context, token string, cli mgclients.Client) (mgclients.Client, error) {
	tokenUserID, err := svc.Identify(ctx, token)
	if err != nil {
		return mgclients.Client{}, err
	}

	if err := svc.checkSuperAdmin(ctx, tokenUserID); err != nil {
		return mgclients.Client{}, err
	}
	client := mgclients.Client{
		ID:        cli.ID,
		Role:      cli.Role,
		UpdatedAt: time.Now(),
		UpdatedBy: tokenUserID,
	}

	if err := svc.updateClientPolicy(ctx, cli.ID, cli.Role); err != nil {
		return mgclients.Client{}, err
	}
	client, err = svc.clients.UpdateRole(ctx, client)
	if err != nil {
		// If failed to update role in DB, then revert back to platform admin policy in spicedb
		if errRollback := svc.updateClientPolicy(ctx, cli.ID, mgclients.UserRole); errRollback != nil {
			return mgclients.Client{}, errors.Wrap(errRollback, err)
		}
               // Here we are calling the repo error handler.
		return mgclients.Client{}, handleRepoErr(err,svcerr.ErrUpdateEntity)
	}
	return client, nil
}

Indicate the importance of this feature to you.

Must-have

Anything else?

No response

This works for me. It's a good idea to keep error handling in the "upper" layer anyways (i.e. handle repo error in svc, and svc in API, just like we initially planned).

As for the handleError location, I'd keep it unexported and per-service for the time being. If there is a lot of overlapping, we can consider making it the internal package.