From a5766e57f8ba03a2bbe9ec247e18c5a8564a25f0 Mon Sep 17 00:00:00 2001 From: Gregory Eremin Date: Tue, 26 Jul 2016 23:52:48 +0200 Subject: [PATCH] Add http package --- daemon.go | 4 +++ examples/http/main.go | 21 +++++++++++ http/server.go | 82 +++++++++++++++++++++++++++++++++++++++++++ shezmu.go | 16 +++++++++ 4 files changed, 123 insertions(+) create mode 100644 examples/http/main.go create mode 100644 http/server.go diff --git a/daemon.go b/daemon.go index 23f3dd9..24e0525 100644 --- a/daemon.go +++ b/daemon.go @@ -133,6 +133,10 @@ func (d *BaseDaemon) Logf(format string, v ...interface{}) { } } +// Startup is the empty implementation of the daemons' Startup function that +// is inherited and used by default. +func (d *BaseDaemon) Startup() {} + // Shutdown is the empty implementation of the daemons' Shutdown function that // is inherited and used by default. func (d *BaseDaemon) Shutdown() {} diff --git a/examples/http/main.go b/examples/http/main.go new file mode 100644 index 0000000..8bce583 --- /dev/null +++ b/examples/http/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "net/http" + + "github.com/julienschmidt/httprouter" + "github.com/localhots/shezmu" + shezttp "github.com/localhots/shezmu/http" +) + +func main() { + sv := shezmu.Summon() + server := shezttp.NewServer(sv, ":2255") + server.Get("/", func(w http.ResponseWriter, r *http.Request, params httprouter.Params) { + w.Write([]byte("It works!")) + }) + go server.Start() + + sv.StartDaemons() + sv.HandleSignals() +} diff --git a/http/server.go b/http/server.go new file mode 100644 index 0000000..38cc283 --- /dev/null +++ b/http/server.go @@ -0,0 +1,82 @@ +package http + +import ( + "fmt" + "net/http" + + hr "github.com/julienschmidt/httprouter" + "github.com/localhots/shezmu" +) + +// Server is an implementation of HTTP server that executes requests using +// Shezmu actors. +type Server struct { + sv *shezmu.Shezmu + address string + router *hr.Router +} + +type handler struct { + shezmu.BaseDaemon + + name string + handle hr.Handle +} + +// NewServer creates a new server. +func NewServer(sv *shezmu.Shezmu, address string) *Server { + return &Server{ + sv: sv, + address: address, + router: hr.New(), + } +} + +// Start starts the server. +func (s *Server) Start() error { + s.sv.Logger.Printf("Starting server at %s", s.address) + return http.ListenAndServe(s.address, s.router) +} + +// Get installs a handler for GET requests. +func (s *Server) Get(path string, handle hr.Handle) { + s.router.GET(path, s.addHandlerDaemon(path, handle)) +} + +// Post installs a handler for POST requests. +func (s *Server) Post(path string, handle hr.Handle) { + s.router.POST(path, s.addHandlerDaemon(path, handle)) +} + +// Put installs a handler for PUT requests. +func (s *Server) Put(path string, handle hr.Handle) { + s.router.PUT(path, s.addHandlerDaemon(path, handle)) +} + +// Delete installs a handler for DELETE requests. +func (s *Server) Delete(path string, handle hr.Handle) { + s.router.DELETE(path, s.addHandlerDaemon(path, handle)) +} + +func (s *Server) addHandlerDaemon(path string, handle hr.Handle) hr.Handle { + h := &handler{ + name: fmt.Sprintf("HTTP[%s]", path), + handle: handle, + } + s.sv.AddDaemon(h) + + return h.process +} + +func (h *handler) process(w http.ResponseWriter, r *http.Request, params hr.Params) { + wait := make(chan struct{}) + h.Process(func() { + defer close(wait) + h.handle(w, r, params) + }) + <-wait +} + +func (h *handler) String() string { + return h.name +} diff --git a/shezmu.go b/shezmu.go index 9169374..0acb662 100644 --- a/shezmu.go +++ b/shezmu.go @@ -4,8 +4,10 @@ import ( "fmt" "log" "os" + "os/signal" "runtime/debug" "sync" + "syscall" "time" "github.com/localhots/shezmu/stats" @@ -114,6 +116,20 @@ func (s *Shezmu) StopDaemons() { fmt.Println(s.runtimeStats.Fetch(stats.Latency)) } +func (s *Shezmu) HandleSignals() { + ch := make(chan os.Signal) + signal.Notify(ch, syscall.SIGINT) + for { + switch sig := <-ch; sig { + case syscall.SIGINT: + s.StopDaemons() + return + default: + s.Logger.Printf("Signal ignored: %s", sig) + } + } +} + func (s *Shezmu) setupDaemon(d Daemon) { defer func() { if err := recover(); err != nil {