DEV Community

Cover image for Rollback Functions in Golang
Omnia Wahid
Omnia Wahid

Posted on

7 3

Rollback Functions in Golang

Errors in Go

Go methods can return multiple values. One of these values can be an error. The zero value of an error is nil. After the call of each method, you check the error value with nil. If it is not equal to nil, then an error has occurred.

How to Implement a Rollback Function?

A function can call multiple methods in it. When an error occurs in one of the methods, you will need to reverse the methods called before the error. Reverting the output of the methods is done by implementing a rollback function and calling it every time an error occurs.

The concept of the rollback function is reverse-engineering. First, extract information from the called methods. This information is the success status of each method. The state may be a boolean variable with a value equal to true when the method succeeds and false when it fails; it also may be a string with the result of the method.

Then, collect the information and abstract it into a model. Finally, pass this model to the rollback function and review each status; if it is a success status, reverse the method and if it is a failure status, ignore it.

In this way, there are no side effects to the function when an error occurs. Moreover, the program will be maintainable.

Example

//Modeling
type CreateHotelStatusModel struct {
    HotelId             string `json:"hotelId"`
    FloorId             string `json:"floorId"`
    RoomId              string `json:"roomId"`
    IsFirstFloorCreated bool   `json:"isFirstFloorCreated"`
    IsFirstRoomCreated  bool   `json:"isFirstRoomCreated"`
}

func CreateHotel(hotelName string) error {
    var hotelStatusModel CreateHotelStatusModel
    //create hotel DB record
    hotelId, createHotelDBErr := CreateHotelDBRecord(hotelName)
    //Information extraction
    hotelStatusModel.HotelId = hotelId
    if createHotelDBErr != nil {
        createHotelRollback(&hotelStatusModel)
        return createHotelDBErr
    }

    //create first floor
    floorId, isFloorCreated, createFloorErr := CreateFirstFloor(hotelId)
    hotelStatusModel.FloorId = floorId
    hotelStatusModel.IsFirstFloorCreated = isFloorCreated
    if createFloorErr != nil {
        createHotelRollback(&hotelStatusModel)
        return createFloorErr
    }

    //create first room
    roomId, isRoomCreated, createRoomErr := CreateFirstRoom(floorId)
    hotelStatusModel.RoomId = roomId
    hotelStatusModel.IsFirstRoomCreated = isRoomCreated
    if createRoomErr != nil {
        createHotelRollback(&hotelStatusModel)
        return createRoomErr
    }
    DispatchEvent("success","topic")
    return nil
}

//Review
func createHotelRollback(statusModel *CreateHotelStatusModel) {
    if statusModel.HotelId != "" {
        DeleteHotelDBRecord(statusModel.HotelId)
    }
    if statusModel.IsFirstFloorCreated {
        DeleteFloor(statusModel.FloorId)
    }
    if statusModel.IsFirstRoomCreated {
        DeleteRoom(statusModel.RoomId)
    }
    DispatchEvent("failure","topic")
}
Enter fullscreen mode Exit fullscreen mode

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (2)

Collapse
 
3ddpaz profile image
Ed

Why not simply add everything on a database transaction?? and dispatch the event only if it fails that transaction.

Collapse
 
omniawahid profile image
Omnia Wahid

That can be a solution if you are only integrating with database, however, if you are integrating with third parties services, you will need to reverse each.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay