/puffadder

current account database

Primary LanguageGo

puffadder

Package puffadder is a project database built from scratch that is designed to store and update current bank accounts.

The main features that allow this are:

  • Event source architecture so that you have a history of activity on each account.

  • Choice of homemade algorithm (btree, hash_table, ordered_array).

  • Transactions between accounts are atomic.

  • The database is durable, it stores each action to a file (like a commit log in other databases)

    • Side note: I havn't looked into making sure it is flushed to permenated storeage like postgres (fsync)


Install

With a correctly configured Go toolchain:

go get -u github.com/zoomie/puffadder

Run

In the project direcotry run the following

go build .
./puffadder

Examples

Run the http server in main.go, open the data.puff file and run each of the following commands:

curl 'localhost:8090/create-account' -d 'accountName=joe'
curl 'localhost:8090/view-current-account?accountName=joe' 
curl 'localhost:8090/add-money' -d 'accountName=joe&addAmount=100'
curl 'localhost:8090/withdraw-money' -d 'accountName=joe&subtractAmount=10'

curl 'localhost:8090/create-account' -d 'accountName=john' 
curl 'localhost:8090/transfer' -d 'fromAccount=joe&toAccount=john&transferAmount=10'

The above commands will produce the following data.puff file.

joe-------:create--:---------0
joe-------:add-----:-------100
joe-------:withdraw:--------10
john------:create--:---------0
joe-------:withdraw:--------10
john------:add-----:--------10

Test example of how to create an account in code, can be found in server_test.go.

func createAccountSetUp(accountName string) (*httptest.ResponseRecorder, *http.Request) {
	form := url.Values{}
	form.Add("accountName", accountName)
	body := strings.NewReader(form.Encode())
	url := path.Join(baseURL, "create-account")
	request, _ := http.NewRequest("POST", url, body)
	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	recorder := httptest.NewRecorder()
	return recorder, request
}

func TestCreateAccount(t *testing.T) {
	channelSrv := setUp()
	recorder, request := createAccountSetUp("joe")
	channelSrv.createAccount(recorder, request)
	response := recorder.Result()
	if response.StatusCode != http.StatusOK {
		t.Errorf("Creating account failed")
	}
}

Structure

The server and entry point for the database is found in:

Algorithms that store value in memory:

The file that persists the data to disk and updates the current value using an algorithm:

Tests: