Category Archives: Golang

Automatically Recover from Connectivity Failure in Go

Fork me on GitHubGo Fallback
Go provides a very effective means of executing HTTP requests, exposed through the net/http package. In certain scenarios, it may be favourable to provide recovery mechanisms that allow Go applications to function as normal in the event of HTTP connectivity failure.

Assuming the following process flow:

Application with dependency

Application with dependency

Our Go application has an explicit dependency on System 1. Let’s assume that communication between both systems occurs over HTTP, and that our Go application must be highly available; in that it must remain functional if downstream systems fail:

Application with fallback dependencies

Application with fallback dependencies

Now we must configure our Go application, in the event of System 1 failure; to automatically attempt to repeat the failing HTTP request to Backup 1.

Similarly, should the connection to Backup 1 become unavailable, our Go application should attempt to repeat the failing HTTP request to Backup 2.

Chain of Responsibility

Chain of Responsibility

Chain of Responsibility

The Chain of Responsibility design pattern provides a suitable solution. The pattern defines a series of handlers, each one designed to execute a specific task. The task is passed along the chain until a handler successfully completes the task, or all handlers fail to complete the task.

Package fallback is designed to achieve this pattern, and to provide redundancy in the event of connectivity failure. The process flow pertaining to the above example is as follows:

Fallback process flow

Fallback process flow

Builder

Builder Design Pattern

Builder Design Pattern

Package fallback handles the execution of HTTP requests by wrapping each request in a ConnectionBuilder, as per the Builder design pattern. This allows the developer control over the manner in which underlying HTTP requests are constructed. Each ConnectionBuilder controls an underlying Connection – a wrapper for the actual HTTP request.

Each HTTP request is wrapped in a ConnectionBuilder, and managed by a ConnectionManager –  the Director component. Once the Chain of Responsibility has been established, the ExecuteHTTPRequest method is executed on the first underlying Connection. This method will attempt to successfully execute the underlying HTTP request. Should the request fail, the method will invoke the ExecuteHTTPRequest on the next Connection in the chain, in a recursive manner, until any given request succeeds, or all requests fail.

Installation

go get github.com/daishisystems/fallback

Sample Code

First, we need to establish some data structures:

    // BasicResponse represents the response issued from the first successful
    // HTTP request, if applicable.
    type BasicResponse struct {
        Text   string
        Detail string
    }

    // BasicError represents the error issued from the last unsuccessful
    // HTTP request, if applicable.
    type BasicError struct {
        Code    int
        Message string
    }

    //
    type PostBody struct {
        Name   string
        Amount int
    }

    basicResponse := &BasicResponse{}
    basicError := &BasicError{}

    postBody := PostBody{
        "Random", 100,
    }

Next, we initialise a ConnectionManager (the Director in our Builder implementation) and pass a ConnectionBuilder (the Builder itself). This particular ConnectionBuilder, in this example, is designed to execute successfully:

    passPath := "http://demo7227109.mockable.io/get-basic"
    failPath2 := "http://demo7227109.mockable.io/fail-basic"
    failPath1 := "http://demo7227109.mockable.io/fail-basic-post"

    connectionManager := fallback.ConnectionManager{}

    // This Connection will execute last, and will succeed.
    passBuilder := fallback.NewConnectionBuilder("PASS", "GET", passPath, true,
        nil, nil, &basicResponse, &basicError, nil)
    connectionManager.CreateConnection(passBuilder)

Now add 2 more ConnectionBuilders to the chain, both of which, in this example, are designed to fail execution:

    // This Connection will be the 2nd Connection to execute, and will fail.
    failBuilder2 := fallback.NewConnectionBuilder("FAIL2", "POST", failPath2,
        true, nil, nil, &basicResponse, &basicError, passBuilder.Connection)
    connectionManager.CreateConnection(failBuilder2)

    //This Connection will be the 1st Connection to execute, and will fail.
    failBuilder1 := fallback.NewConnectionBuilder("FAIL1", "POST", failPath1,
        true, postBody, nil, &basicResponse, &basicError,
        failBuilder2.Connection)
    connectionManager.CreateConnection(failBuilder1)

Finally, invoke the first ConnectionBuilder in the chain. In this example, both first and second ConnectionBuilders are designed to fail. Execution recursively falls back to passBuilder, which executes successfully:

    // Each Connection will be invoked in a recursive manner until a
    // Connection succeeds, or all Connections fail. Please refer to the Chain
    // of Responsibility design for more information.
    statusCode, err := failBuilder1.Connection.ExecuteHTTPRequest()
    if err != nil {
        panic(err)
    }

    fmt.Printf("HTTP status code: %d\n", statusCode)
    fmt.Printf("Text: %s\n", basicResponse.Text)
    fmt.Printf("Detail: %s", basicResponse.Detail)

The fall-back process is encapsulated within package fallback; consuming clients are unaware of failures, and instead, are guaranteed success, long as at least one HTTP connection remains viable.

Summary

Package fallback enhances the durability of your API by automatically recovering from connectivity failure. It achieves this by providing an enhanced degree of redundancy to HTTP requests, introducing a Chain of Responsibility, consisting of a series of fallback HTTP requests designed to augment an initial HTTP request. Should the initial HTTP request fail, the next fallback HTTP request in the chain will execute.

Any number of fallback HTTP requests can be chained sequentially. Redundancy is achieved by executing each fallback HTTP request in a recursive manner until one of the requests succeeds, or all requests fail.

Connect with me:

RSSGitHubTwitter
LinkedInYouTubeGoogle+

Simple Date Handling in Go

Fork me on GitHubGo Month Package
Package time provides functionality focused on managing times and dates. The package consists of a wide range of features designed to facilitate a Gregorian calendar. Here is a canonical example:

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Printf("Time is set to %s\n", t.Local())
}

Last Day of the Month

Very nice, neat, and concise. Let’s say that I want to calculate the last day of the month, for any given month in any given year. For example, I know that 2012 was a leap year, and February therefore had 29 days. Here is how such a calculation would look in C#:

var lastDayofMonth = DateTime.DaysInMonth(2012, 02);

And in Java:

// Java 7
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
Date convertedDate = dateFormat.parse(date);
Calendar c = Calendar.getInstance();
c.setTime(convertedDate);
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));

// Java 8
LocalDate date = LocalDate.of(2012, Month.FEBRUARY, 1);

System.out.printf("The last day of February is: %s%n",
	date.with(TemporalAdjusters.lastDayOfMonth()));

That’s a little verbose. Let’s try JavaScript:

return new Date(2012, 2, 0).getDate();

How does Go stack up against these idioms?

m := time.February
t := time.Date(2012, m+1, 0, 0, 0, 0, 0, time.UTC)
fmt.Println(2012, m, t.Day())

That’s quite succinct, but not very intuitive. Essentially we’re incrementing the month value by 1, and setting the day value to zero. This causes the underlying date mechanisms to roll back the date to the last day of the previous month – remember, we specified the month value as February, and incremented this value by 1. Now our month value is equal to March. Setting the day value to 0 effectively rolls the date back to the last day of February; in this case, the 29th.

This method gets the job done, at the expense of adding verbosity. The above example in C# is arguably the most intuitive. It would be nice if we could calculate the last day of the month in a similar manner in Go.

Fortunately the Go Month package provides this functionality. The package is designed with developer productivity in mind, encapsulating some of the more verbose features of underlying Go packages, and exposing them intuitively. Let’s install the package and take a look at some examples:

go get github.com/daishisystems/month
    // The last numeric day of January is 31
    m := month.January
    fmt.Printf("The last numeric day of %s is %d\n", m, m.LastDay(2015))

    // The last numeric day of February is 28
    m = month.February
    fmt.Printf("The last numeric day of %s is %d\n", m, month.February.LastDay(2015))

    // The last numeric day of February is 29
    m = month.February
    fmt.Printf("The last numeric day of %s is %d\n", m, m.LastDay(2008))

    // The last numeric day of July is 31
    m = month.July
    fmt.Printf("The last numeric day of %s is %d\n", m, m.LastDay(2015))

What exactly does LastDay do? Is it just a wrapper that encapsulates built-in Go functionality?

No, it’s a bespoke method that doesn’t rely on existing date or time functionality. In fact, the package does not depend on any other packages at all. Here is the method in detail:

func (m Month) LastDay(year uint16) int {

	if m == 2 {

		isLeapYear := year%4 == 0 &&
			(year%100 != 0 || year%400 == 0)

		if isLeapYear {
			return 29
		}
		return 28
	}
	return monthDays[int(m)]
}

The method accepts a year value. This is necessary, given that the month of February contains 29 days in a leap year. Notice that I refer to the code snippet as a method. Methods and functions are not interchangeable terms in Go. Specifically, a method must have a receiver; a type to which the method is applied. In this case, our receiver is of type Month. Think of Go methods as being similar to class-level functions in C# or Java.

The package contains a static collection of months represented as integers, and the corresponding number of days in each month. Only February is omitted:

var monthNames = [12]string{
	"January",
	"February",
	"March",
	"April",
	"May",
	"June",
	"July",
	"August",
	"September",
	"October",
	"November",
	"December",
}

LastDay simply returns the value of the above map (Dictionary in C#, HashMap in Java) associated with the specified month, if the month is any other month than February. Otherwise, the method determines whether or not the year is a leap year. A leap year is defined as being:

  • Evenly divisible by 4
  • Not evenly divisible by 100, unless it is also evenly divisible by 400

LastDay employs this calculation as follows:

isLeapYear := year%4 == 0 &&
    (year%100 != 0 || year%400 == 0)

Very simply, if the year is determined to be a leap year, LastDay returns 29, otherwise, 28:

if isLeapYear {
    return 29
}
return 28

Summary

The Go Month Package provides functionality in an intuitive format, has no dependencies on existing date or time packages (or any packages at all), and very little verbosity. Please reach out and contact me for questions, suggestions, or to just talk tech in general.

Connect with me:

RSSGitHubTwitter
LinkedInYouTubeGoogle+