lionell / pgapps

Different approaches to build interface to DB(backed by PostgreSQL)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PgApps

Build Status

This repository contains different ways to interact with database. From simple CLI to colab notebook based on WebSocket, deployed to the cluster. All of these are demos and are not designed to be used in production.

How it works

All the interactions with database is done via

type Engine interface {
  Open() error
  OpenRemote(host, port string) error
  Close()
  Exec(query string) (*Table, error)
}

So that you can easily substitute database backend with anything you want(eg. Aqua).

CLI

cli is a very simple Command Line Interface for database.

After you run the tool, you'll be welcomed with a prompt. Just type the query you want to run and press enter. It will be executed on the backend, and you'll see the nicely formatted results. To close the tool just enter exit.

$ go run cmd/cli/cli.go
> select * from users
   id     name   age
    1   Ruslan    21
    2     Dima    20
    3      Mat    18

RPC

client and server tools use Remote Procedure Calls to communicate.

User interface is pretty much the same as in the CLI version. To start server just run

$ go run cmd/server/server.go -port 1234
2017/11/29 03:10:30 Listening on port 1234
...

Then you can connect via client

$ go run cmd/client/client.go -host localhost -port 1234
Connection to localhost:1234 established.
> select * from users
   id     name   age
    1   Ruslan    21
    2     Dima    20
    3      Mat    18

REST API

rest tool exposes REST API for database.

To use it, we need to start server

$ go run cmd/rest/rest.go -port 8080
2017/11/29 03:19:41 Running server on port 8080.
...

Server can serve queries to any table in the database. Different tables are exposed as a different REST resources.

Here is how you can make a request

$ curl http://localhost:8080/users/1
{
  "header": [
    "id",
    "name",
    "age"
  ],
  "rows": [
    [
      "1",
      "Ruslan",
      "21"
    ]
  ]
}

This table shows how to make other REST calls, and whether you need to specify JSON data in request.

Action Method Pattern Data
Get all GET {table} No
Get by ID GET {table}/{id} No
Add new POST {table} Yes
Update by ID PUT {table}/{id} Yes
Remove by ID DELETE {table}/{id} No

For example if we want to update name for a user with id=1 we can do it this way

$ curl -X PUT --data '{"header":["name"],"rows":[["Nick"]]}' http://localhost:8080/users/1
$ curl http://localhost:8080/users/1
{
  "header": [
    "id",
    "name",
    "age"
  ],
  "rows": [
    [
      "1",
      "Nick",
      "21"
    ]
  ]
}

Ajax

ajax tool is using Ajax requests to communicate with server.

After you start the server, you can use user-friendly frontend to query database.

$ go run cmd/ajax/ajax.go -port 8080
2017/11/29 03:46:23 Running server on port 8080.
...

If you navigate to localhost:8080 on the same machine, you should see something like

Ajax Screenshot

When you type a query and press enter, a new Ajax request is sent to server. After it's processed, result will be nicely displayed on the web page.

React

This demo frontend is based on React.

First we need to start the backend server

$ go run cmd/http/http.go -port 8080
2017/11/29 04:07:14 Running server on port 8080.
...

Then we use NPM to start serving frontend

$ npm start --prefix react

Compiled successfully!
The app is running at:
  http://localhost:3000/
...

This should serve a page on port 3000 and automatically open a browser tab with it

React Screenshot

Functionality is the same as for Ajax.

WebSockets

Here we are using WebSockets to build colaboratory notebook.

To use websocket tool just start the server

$ go run cmd/websocket/websocket.go -port 8080
2017/11/29 04:18:56 Running server on port 8080.
...

Now everybody can connect on this port and run queries against your database. What's new here, is that everybody will see queries and results of others. It's like Google Docs but for queries :)

User-experience is pretty much the same as for React and Ajax.

Kubernetes

Building Docker image

There is a Dockerfile in the root of the repo that you can use to build Docker image for modified version of WebSockets app. Default version assumes that we have PostgreSQL running locally. Here you can specify where database is located.

To build an image and push it to Docker Hub just do

$ docker build -t lionell/websockets:v1 .
...

$ docker push lionell/websockets:v1

Now you can find image linked to your account(you should substitute 'lionell' in the commands above).

Kubernetes on GCP(optional)

Let's start a new Kubernetes cluster with 3 nodes on Google Cloud Platform.

$ gcloud container clusters create websockets-cluster --num-nodes=3

Now you should be able to see 3 nodes if you run

$ gcloud compute instances list

For more information see Deploying a containerized web application tutorial.

Deploying to Kubernetes cluster

We are going to use preconfigured Kubernetes resource files located in kubernetes/ to create services and deployments.

These commands will deploy PostgreSQL database to Kubernetes

$ kubectl create -f kubernetes/my-postgres-service.yml
$ kubectl create -f kubernetes/my-postgres.yml

Then we need to deploy our application. Deployment file kubernetes/app.yml uses Docker image lionell/websockets:v1 to create container

$ kubectl create -f kubernetes/app-service.yml
$ kubectl create -f kubernetes/app.yml

Let's find external IP address GCP issued to load balancer

$ kubectl get svc/app
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
app           LoadBalancer   10.43.251.48    35.202.209.153   80:31914/TCP   2m

In my case it's 35.202.209.153. So if I open it in the browser, I'll see my app. Hooray!

WebSockets screenshot

Application scaling

You can easily scale an application with Kubernetes. For example we can scale our app deployment like this

$ kubectl scale deployment/app --replicas 2

This will create 2 different pods for our service, and all the ingress traffic will be load balanced between the pods. In our particular case, scaling is not useful, as we'll loose ability to communicate query results to other users(that hitted different endpoint).

New version rollout

We can easily rollout a new version of an application with Kubernetes

$ kubectl set image deployment/app app=lionell/websockets:v2

This will sequentually turn down each replica in deployment and replace it with a new version. So that your application can function during the update.

Cleaning up(optional)

Don't forget to shut your cluster down.

$ kubectl delete service app
$ gclould container clusters delete websockets-cluster

License

MIT

About

Different approaches to build interface to DB(backed by PostgreSQL)

License:MIT License


Languages

Language:Go 53.5%Language:HTML 35.3%Language:JavaScript 9.9%Language:CSS 1.2%