Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map also success responses on Controllers #398

Open
5 tasks done
acostapazo opened this issue Aug 7, 2023 · 0 comments
Open
5 tasks done

Map also success responses on Controllers #398

acostapazo opened this issue Aug 7, 2023 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@acostapazo
Copy link
Contributor

acostapazo commented Aug 7, 2023

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I already read and followed all the tutorial in the README and didn't find an answer.
  • I already reviewed the petisco-fastapi-example

Commit to Help

  • I commit to help with one of those options 👆

Example Code

class CreateTaskController(FastAPIController):

    class Config:
        success_handler= lambda result: {"message": "Task saved"}
        error_map= {
           TaskAlreadyCreated: HttpError(status_code=409, detail="Task already created")
           TaskDescriptionTooLong: HttpError(status_code=422, detail="Task description is too long")
        }


    def execute(self, task: Task) -> BoolResult:
        task_creator = TaskCreator(
            labeler=Container.get(TaskLabeler),
            repository=Container.get(CrudRepository, alias="task_repository"),
            domain_event_bus=Container.get(DomainEventBus),
        )
        return task_creator.execute(task=task)

Description

With petisco you normally define success_handler and error_map to manage all the paths your use case can take.

In the above example:

  • With success_handler: lambda result: {"message": "Task saved"} your program allways will return a 200 (default value) and the payload {"message": "Task saved"}.

  • In case of failure, it will return 409 or 422 depending on the Failure returned by TaskCreator:
    * TaskAlreadyCreated -> 409
    * TaskDescriptionTooLong -> 422

But what if you want to have different behaviors for successful results?

Image we want to change the status code depending of the Success values is True or False. Now, we have to do it as following;

def my_example_success_handler(result: Result):
         if result.value is True:
                return JSONResponse(
                    status_code=status.HTTP_200_OK,
                    content={"message": "Task saved"}
                )
         else:
            return JSONResponse(
                status_code=status.HTTP_206_PARTIAL_CONTENT,
                content={"message": "Task will be saved"},
            )


class CreateTaskController(FastAPIController):

    class Config:
        success_handler= my_example_success_handler
        error_map= {
           TaskAlreadyCreated: HttpError(status_code=409, detail="Task already created")
           TaskDescriptionTooLong: HttpError(status_code=422, detail="Task description is too long")
        }


    def execute(self, task: Task) -> BoolResult:
        task_creator = TaskCreator(
            labeler=Container.get(TaskLabeler),
            repository=Container.get(CrudRepository, alias="task_repository"),
            domain_event_bus=Container.get(DomainEventBus),
        )
        return task_creator.execute(task=task)

The two solutions proposed below would have to take into account that these new mappings would be reflected in the static responses function, accessible in this example at: CreateTaskController.responses().

Proposal 1 (success_map)

Add a success_map similar to error_map and map success values.

class CreateTaskController(FastAPIController):

    class Config:
        success_map = {
               True: JSONResponse(status_code=200, content={"message": "Task saved"})
               False: JSONResponse(status_code=206, content={"message": "Task will be saved"})
        }
        error_map= {
           TaskAlreadyCreated: HttpError(status_code=409, detail="Task already created")
           TaskDescriptionTooLong: HttpError(status_code=422, detail="Task description is too long")
        }


    def execute(self, task: Task) -> BoolResult:
        task_creator = TaskCreator(
            labeler=Container.get(TaskLabeler),
            repository=Container.get(CrudRepository, alias="task_repository"),
            domain_event_bus=Container.get(DomainEventBus),
        )
        return task_creator.execute(task=task)

Proposal 2 (response_map)

Refactor the error_map and promote this to responses_map. In the case above will have to define a success alternative class with a domain class (e.g Success(AsynTaskQueued())

class CreateTaskController(FastAPIController):

    class Config:
        responses_map= {
           DEFAULT: JSONResponse(status_code=200, content={"message": "Task saved"}),
           False: JSONResponse(status_code=206, content={"message": "Task will be saved"})
           TaskAlreadyCreated: HttpError(status_code=409, detail="Task already created")
           TaskDescriptionTooLong: HttpError(status_code=422, detail="Task description is too long")
        }


    def execute(self, task: Task) -> BoolResult:
        task_creator = TaskCreator(
            labeler=Container.get(TaskLabeler),
            repository=Container.get(CrudRepository, alias="task_repository"),
            domain_event_bus=Container.get(DomainEventBus),
        )
        return task_creator.execute(task=task)
@acostapazo acostapazo added the enhancement New feature or request label Aug 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants