Improve info when config is reloaded. (#16)

- Using toasts as message outputs (still a lot of room for improvement)

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
This commit is contained in:
Antonio Navarro Perez 2020-11-09 11:33:19 +01:00 committed by GitHub
parent 0e2288565d
commit ab7d379408
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 59 deletions

View file

@ -57,21 +57,22 @@ function bin2string(array) {
function reload() { function reload() {
fetch("/api/reload", { fetch("/api/reload", {
method: "POST", method: "POST",
}).then(function (response) {
if (response.ok) {
return response.text();
} else {
toastError(
"Error saving configuration file. Response: " + response.status
);
}
}) })
.then(function (text) { .then(function (response) {
toastInfo(text); if (response.ok) {
}) return response.json();
.catch(function (error) { } else {
toastError("Error reloading server: " + error.message); toastError(
}); "Error saving configuration file. Response: " + response.status
);
}
})
.then(function (json) {
toastInfo(json.message);
})
.catch(function (error) {
toastError("Error reloading server: " + error.message);
});
} }
function save() { function save() {

View file

@ -1,25 +1,29 @@
function toast(msg, color, time) {
Toastify({
text: msg,
duration: time,
newWindow: true,
close: true,
gravity: "top",
position: "right",
backgroundColor: color,
stopOnFocus: true,
}).showToast();
}
function toastError(msg) { function toastError(msg) {
Toastify({ toast(msg, "red", 5000);
text: msg,
duration: 5000,
newWindow: true,
close: true,
gravity: "top", // `top` or `bottom`
position: 'right', // `left`, `center` or `right`
backgroundColor: "red",
stopOnFocus: true, // Prevents dismissing of toast on hover
}).showToast();
} }
function toastInfo(msg) { function toastInfo(msg) {
Toastify({ toast(msg, "green", 5000);
text: msg, }
duration: 5000,
newWindow: true, function toastMessage(msg) {
close: true, toast(msg, "grey", 10000);
gravity: "top", // `top` or `bottom` }
position: 'right', // `left`, `center` or `right`
backgroundColor: "green", var stream = new EventSource("/api/events");
stopOnFocus: true, // Prevents dismissing of toast on hover stream.addEventListener("event", function (e) {
}).showToast(); toastMessage(e.data);
} });

View file

@ -103,13 +103,12 @@ func load(configPath string, port int) error {
for _, mp := range c.MountPoints { for _, mp := range c.MountPoints {
ef(fmt.Sprintf("mounting %v with %d torrents...", mp.Path, len(mp.Torrents))) ef(fmt.Sprintf("mounting %v with %d torrents...", mp.Path, len(mp.Torrents)))
if err := mountService.Mount(mp); err != nil { if err := mountService.Mount(mp, ef); err != nil {
return fmt.Errorf("error mounting folder %v: %w", mp.Path, err) return fmt.Errorf("error mounting folder %v: %w", mp.Path, err)
} }
ef(fmt.Sprintf("%v mounted", mp.Path))
} }
ef("all OK")
return nil return nil
}) })

View file

@ -29,7 +29,7 @@ func NewHandler(c *torrent.Client, s *stats.Torrent) *Handler {
} }
} }
func (s *Handler) Mount(mpc *config.MountPoint) error { func (s *Handler) Mount(mpc *config.MountPoint, ef config.EventFunc) error {
var torrents []fs.Filesystem var torrents []fs.Filesystem
for _, mpcTorrent := range mpc.Torrents { for _, mpcTorrent := range mpc.Torrents {
var t *torrent.Torrent var t *torrent.Torrent
@ -51,6 +51,7 @@ func (s *Handler) Mount(mpc *config.MountPoint) error {
// only get info if name is not available // only get info if name is not available
if t.Name() == "" { if t.Name() == "" {
ef(fmt.Sprintf("getting torrent info...: %v", t.InfoHash()))
log.WithField("hash", t.InfoHash()).Info("getting torrent info") log.WithField("hash", t.InfoHash()).Info("getting torrent info")
<-t.GotInfo() <-t.GotInfo()
} }
@ -58,6 +59,7 @@ func (s *Handler) Mount(mpc *config.MountPoint) error {
s.s.Add(mpc.Path, t) s.s.Add(mpc.Path, t)
torrents = append(torrents, fs.NewTorrent(t)) torrents = append(torrents, fs.NewTorrent(t))
ef(fmt.Sprintf("torrent %v added to mountpoint", t.Name()))
log.WithField("name", t.Name()).WithField("path", mpc.Path).Info("torrent added to mountpoint") log.WithField("name", t.Name()).WithField("path", mpc.Path).Info("torrent added to mountpoint")
} }

View file

@ -4,6 +4,7 @@ import (
"errors" "errors"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http"
"github.com/ajnavarro/distribyted/config" "github.com/ajnavarro/distribyted/config"
"github.com/ajnavarro/distribyted/stats" "github.com/ajnavarro/distribyted/stats"
@ -14,7 +15,7 @@ import (
var apiStatusHandler = func(fc *filecache.Cache, ss *stats.Torrent) gin.HandlerFunc { var apiStatusHandler = func(fc *filecache.Cache, ss *stats.Torrent) gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
// TODO move to a struct // TODO move to a struct
ctx.JSON(200, gin.H{ ctx.JSON(http.StatusOK, gin.H{
"cacheItems": fc.Info().NumItems, "cacheItems": fc.Info().NumItems,
"cacheFilled": fc.Info().Filled / 1024 / 1024, "cacheFilled": fc.Info().Filled / 1024 / 1024,
"cacheCapacity": fc.Info().Capacity / 1024 / 1024, "cacheCapacity": fc.Info().Capacity / 1024 / 1024,
@ -26,7 +27,7 @@ var apiStatusHandler = func(fc *filecache.Cache, ss *stats.Torrent) gin.HandlerF
var apiRoutesHandler = func(ss *stats.Torrent) gin.HandlerFunc { var apiRoutesHandler = func(ss *stats.Torrent) gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
stats := ss.RoutesStats() stats := ss.RoutesStats()
ctx.JSON(200, stats) ctx.JSON(http.StatusOK, stats)
} }
} }
@ -34,54 +35,69 @@ var apiGetConfigFile = func(ch *config.Handler) gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
rc, err := ch.GetRaw() rc, err := ch.GetRaw()
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(http.StatusInternalServerError, err)
return return
} }
ctx.Data(200, "text/x-yaml", rc) ctx.Data(http.StatusOK, "text/x-yaml", rc)
} }
} }
var apiSetConfigFile = func(ch *config.Handler) gin.HandlerFunc { var apiSetConfigFile = func(ch *config.Handler) gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
if ctx.Request.Body == nil { if ctx.Request.Body == nil {
ctx.AbortWithError(500, errors.New("no config file sent")) ctx.AbortWithError(http.StatusInternalServerError, errors.New("no config file sent"))
return return
} }
c, err := ioutil.ReadAll(ctx.Request.Body) c, err := ioutil.ReadAll(ctx.Request.Body)
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(http.StatusInternalServerError, err)
return return
} }
if len(c) == 0 { if len(c) == 0 {
ctx.AbortWithError(500, errors.New("no config file sent")) ctx.AbortWithError(http.StatusInternalServerError, errors.New("no config file sent"))
return return
} }
if err := ch.Set(c); err != nil { if err := ch.Set(c); err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(http.StatusInternalServerError, err)
return return
} }
// TODO return something? ctx.JSON(http.StatusOK, gin.H{
ctx.JSON(200, nil) "message": "config file saved",
})
} }
} }
var apiReloadServer = func(ch *config.Handler) gin.HandlerFunc { var apiStreamEvents = func(events chan string) gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
ctx.Stream(func(w io.Writer) bool { ctx.Stream(func(w io.Writer) bool {
err := ch.Reload( if msg, ok := <-events; ok {
func(m string) { ctx.SSEvent("event", msg)
ctx.SSEvent("reload", m) return true
})
if err != nil {
ctx.AbortWithError(500, err)
} }
return false return false
}) })
} }
} }
var apiReloadServer = func(ch *config.Handler, events chan string) gin.HandlerFunc {
return func(ctx *gin.Context) {
events <- "starting reload configuration process..."
err := ch.Reload(
func(m string) {
events <- m
})
if err != nil {
ctx.AbortWithError(http.StatusInternalServerError, err)
}
ctx.JSON(http.StatusOK, gin.H{
"message": "reload process finished with no errors",
})
}
}

View file

@ -32,14 +32,16 @@ func New(fc *filecache.Cache, ss *stats.Torrent, ch *config.Handler, port int) e
r.GET("/routes", routesHandler(ss)) r.GET("/routes", routesHandler(ss))
r.GET("/config", configHandler) r.GET("/config", configHandler)
eventChan := make(chan string)
api := r.Group("/api") api := r.Group("/api")
{ {
api.GET("/status", apiStatusHandler(fc, ss)) api.GET("/status", apiStatusHandler(fc, ss))
api.GET("/routes", apiRoutesHandler(ss)) api.GET("/routes", apiRoutesHandler(ss))
api.GET("/config", apiGetConfigFile(ch)) api.GET("/config", apiGetConfigFile(ch))
api.POST("/config", apiSetConfigFile(ch)) api.POST("/config", apiSetConfigFile(ch))
api.POST("/reload", apiReloadServer(ch)) api.POST("/reload", apiReloadServer(ch, eventChan))
api.GET("/events", apiStreamEvents(eventChan))
} }
logrus.WithField("host", fmt.Sprintf("0.0.0.0:%d", port)).Info("starting webserver") logrus.WithField("host", fmt.Sprintf("0.0.0.0:%d", port)).Info("starting webserver")