Permalink
Browse files

add code that uses another dep : github.com/boltdb/bolt

  • Loading branch information...
freeformz committed Feb 4, 2017
1 parent 259b580 commit c719d1ca8dddaf72e104e0207b767e26c415e0c5
Showing with 188 additions and 0 deletions.
  1. +12 −0 main.go
  2. +84 −0 math/handler.go
  3. +92 −0 math/math.go
View
12 main.go
@@ -3,12 +3,24 @@ package main
import (
"net/http"
"os"
"time"
"github.com/boltdb/bolt"
"github.com/freeformz/depExample/math"
"github.com/gorilla/mux"
)
func main() {
db, err := bolt.Open("maths.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
panic(err)
}
c := math.Calc{DB: db}
h := math.Handler{Calculator: &c}
r := mux.NewRouter()
r.Handle("/", http.FileServer(http.Dir(".")))
r.Handle("/math/{op}/{key}", &h)
r.Handle("/math/{op}/{key}/{value}", &h)
http.ListenAndServe(":"+os.Getenv("PORT"), r)
}
View
@@ -0,0 +1,84 @@
package math
import (
"io"
"net/http"
"strconv"
"fmt"
"github.com/gorilla/mux"
)
const (
errorHeader = "Error"
)
// Handler for http requests
type Handler struct {
Calculator *Calc
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
header := w.Header()
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
o, ok := vars["op"]
if !ok {
header.Add(errorHeader, "op missing")
w.WriteHeader(http.StatusBadRequest)
return
}
op := operation(o)
key, ok := vars["key"]
if !ok {
header.Add(errorHeader, "key missing")
w.WriteHeader(http.StatusBadRequest)
return
}
var val, sum int
var err error
switch op {
case add, subtract:
vs, ok := vars["value"]
if !ok {
header.Add(errorHeader, "value missing")
w.WriteHeader(http.StatusBadRequest)
return
}
val, err = strconv.Atoi(vs)
if err != nil {
header.Add(errorHeader, "error converting value: "+err.Error())
w.WriteHeader(http.StatusBadRequest)
return
}
switch op {
case add:
sum, err = h.Calculator.Add(val, key)
case subtract:
sum, err = h.Calculator.Subtract(val, key)
}
case value:
sum, err = h.Calculator.Value(key)
default:
header.Add(errorHeader, "unknown op: "+string(op))
w.WriteHeader(http.StatusBadRequest)
return
}
if err != nil {
header.Add(errorHeader, "processing error: "+err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
io.WriteString(w, fmt.Sprintf("%s %s %d %d", op, key, val, sum))
}
View
@@ -0,0 +1,92 @@
package math
import (
"fmt"
"strconv"
"github.com/boltdb/bolt"
)
type operation string
const (
add operation = "add"
subtract operation = "subtract"
value operation = "value"
)
// Calc / store the named variables
type Calc struct {
DB *bolt.DB
}
var (
valueKey = []byte("value")
)
// Add i to the key
func (c *Calc) Add(i int, key string) (v int, err error) {
err = c.DB.Update(func(tx *bolt.Tx) error {
v, err = transactionOp(tx, i, key, add)
return err
})
return
}
// Subtract i from the key
func (c *Calc) Subtract(i int, key string) (v int, err error) {
err = c.DB.Update(func(tx *bolt.Tx) error {
v, err = transactionOp(tx, i, key, subtract)
return err
})
return
}
// Value of the key
func (c *Calc) Value(key string) (v int, err error) {
err = c.DB.View(func(tx *bolt.Tx) error {
v, err = transactionOp(tx, 0, key, value)
return err
})
return
}
func transactionOp(tx *bolt.Tx, i int, key string, op operation) (int, error) {
k := []byte(key)
var b *bolt.Bucket
var err error
switch op {
case value:
b = tx.Bucket(k)
default:
b, err = tx.CreateBucketIfNotExists(k)
}
if err != nil {
return 0, err
}
var rv []byte
if b != nil {
rv = b.Get(valueKey)
}
var v int
switch len(rv) {
case 0: // zero value
default:
v, err = strconv.Atoi(string(rv))
}
if err != nil {
return 0, err
}
switch op {
case add:
v += i
return v, b.Put(valueKey, []byte(strconv.Itoa(v)))
case subtract:
v -= i
return v, b.Put(valueKey, []byte(strconv.Itoa(v)))
case value:
return v, nil
default:
return v, fmt.Errorf("unknown operation: %s", op)
}
}

0 comments on commit c719d1c

Please sign in to comment.