aboutsummaryrefslogtreecommitdiff
path: root/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'server.go')
-rw-r--r--server.go67
1 files changed, 56 insertions, 11 deletions
diff --git a/server.go b/server.go
index 620c36f..0ff4e2a 100644
--- a/server.go
+++ b/server.go
@@ -10,6 +10,7 @@ import (
"html/template"
"log"
"net/http"
+ "sync"
"time"
)
@@ -24,11 +25,18 @@ type Server struct {
httpd *http.Server
worker *worker
+ // updateq channel to receive notification when the new report coming
+ // from worker.
+ updateq chan struct{}
+
Options ServerOptions
- Reports Reports
pageIndexTmpl *template.Template
pageIndexBody bytes.Buffer
+
+ // pageIndexMutex guard the pageIndexBody between changes from worker
+ // Reports (write) and when rendered to client (read).
+ pageIndexMutex sync.Mutex
}
// NewServer create new server to serve the content of _www and HTTP APIs.
@@ -37,9 +45,7 @@ func NewServer(opts ServerOptions) (srv *Server, err error) {
srv = &Server{
Options: opts,
- Reports: Reports{
- Services: map[string]ServiceReport{},
- },
+ updateq: make(chan struct{}, 1),
}
err = srv.Options.init()
@@ -52,17 +58,11 @@ func NewServer(opts ServerOptions) (srv *Server, err error) {
return nil, fmt.Errorf(`%s: %w`, logp, err)
}
- for name := range srv.worker.Services {
- srv.Reports.Services[name] = ServiceReport{
- Name: name,
- }
- }
-
srv.pageIndexTmpl, err = template.ParseFS(wwwFS, `_www/index.tmpl`)
if err != nil {
return nil, err
}
- err = srv.pageIndexTmpl.Execute(&srv.pageIndexBody, &srv.Reports)
+ err = srv.pageIndexTmpl.Execute(&srv.pageIndexBody, &srv.worker.Reports)
if err != nil {
return nil, err
}
@@ -81,6 +81,9 @@ func NewServer(opts ServerOptions) (srv *Server, err error) {
// ListenAndServe start handling request on incoming connections.
func (srv *Server) ListenAndServe() (err error) {
+ go srv.update()
+ go srv.worker.start(srv.updateq)
+
log.Printf(`lilin: starting HTTP server at %s`, srv.Options.Address)
err = srv.httpd.ListenAndServe()
@@ -97,6 +100,8 @@ func (srv *Server) Shutdown(ctx context.Context) (err error) {
if err != nil {
return fmt.Errorf(`Shutdown: %w`, err)
}
+ srv.worker.stop()
+ close(srv.updateq)
return nil
}
@@ -105,7 +110,9 @@ func (srv *Server) ServeHTTP(resw http.ResponseWriter, req *http.Request) {
switch req.URL.Path {
case `/`, `/index.html`:
+ srv.pageIndexMutex.Lock()
_, err = resw.Write(srv.pageIndexBody.Bytes())
+ srv.pageIndexMutex.Unlock()
if err != nil {
srv.internalError(resw, err)
}
@@ -122,3 +129,41 @@ func (srv *Server) internalError(resw http.ResponseWriter, err error) {
log.Println(`internalError:`, err.Error())
}
}
+
+// update the index page body periodically only when there is changes from
+// upstream worker.
+// Since services may have different scanned interval (and may longer than
+// default interval), it will takes times to update the index page body every
+// times we receive updates from worker.
+// Hence why we need to update only when changes happened.
+func (srv *Server) update() {
+ var ticker = time.NewTicker(defInterval)
+ var c int
+ var err error
+ for {
+ select {
+ case _, ok := <-srv.updateq:
+ if !ok {
+ return
+ }
+ c++
+ case <-ticker.C:
+ if c == 0 {
+ continue
+ }
+ c = 0
+
+ srv.pageIndexMutex.Lock()
+ srv.worker.reportsMutex.Lock()
+
+ srv.pageIndexBody.Reset()
+ err = srv.pageIndexTmpl.Execute(&srv.pageIndexBody, &srv.worker.Reports)
+ if err != nil {
+ log.Printf(`update: pageIndexTmpl: %s`, err)
+ }
+
+ srv.worker.reportsMutex.Unlock()
+ srv.pageIndexMutex.Unlock()
+ }
+ }
+}