Skip to content

Instantly share code, notes, and snippets.

@nomkhonwaan
Created April 4, 2020 12:53
Show Gist options
  • Save nomkhonwaan/12546a4fe9e7a1f67399efa92838ce70 to your computer and use it in GitHub Desktop.
Save nomkhonwaan/12546a4fe9e7a1f67399efa92838ce70 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"github.com/go-chi/chi"
uuid "github.com/satori/go.uuid"
"log"
"math/rand"
"net/http"
"time"
)
const (
_ = iota
StatusWorking
StatusDone
StatusCanceled
)
type handler struct {
tickets map[string]*ticket
}
type ticket struct {
ID string `json:"id"`
Status int `json:"status"`
done chan struct{}
}
func init() {
rand.Seed(time.Now().UnixNano())
}
func main() {
h := handler{tickets: make(map[string]*ticket)}
r := chi.NewRouter()
r.Post("/import", h.handleFileImporting)
r.Get("/import/{ID}", h.printStatus)
r.Post("/import/{ID}/cancel", h.cancelFileImporting)
log.Println("server is listening on port :8080")
err := http.ListenAndServe(":8080", r)
if err != nil {
log.Panic(err)
}
}
func (h *handler) handleFileImporting(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
t := &ticket{
ID: uuid.NewV4().String(),
Status: StatusWorking,
done: make(chan struct{}),
}
h.tickets[t.ID] = t
go func(t *ticket) {
defer func() {
if t.Status != StatusCanceled {
t.Status = StatusDone
}
close(t.done)
}()
// simulate importing too many records data to database
for i := 0; i < 10; i++ {
time.Sleep(time.Second * time.Duration(rand.Intn(10)))
select {
case <-t.done:
t.Status = StatusCanceled
log.Printf("[%s] canceled\n", t.ID)
return
default:
log.Printf("[%s] importing data...\n", t.ID)
}
}
log.Printf("[%s] finished", t.ID)
}(t)
data, _ := json.Marshal(t)
_, _ = w.Write(data)
}
func (h *handler) printStatus(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
t, ok := h.tickets[id]
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
data, _ := json.Marshal(t)
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(data)
}
func (h *handler) cancelFileImporting(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
t, ok := h.tickets[id]
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
if t.Status != StatusWorking {
w.WriteHeader(http.StatusNotAcceptable)
return
}
log.Printf("[%s] cancelling...", t.ID)
t.done <- struct{}{}
w.WriteHeader(http.StatusAccepted)
_, _ = w.Write([]byte("OK"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment