diff --git a/database/imconnector.go b/database/imconnector.go index 19f0a0b..e9af486 100644 --- a/database/imconnector.go +++ b/database/imconnector.go @@ -27,6 +27,7 @@ func (m *Manager) SaveInstance(i *instance.Instance) error { Identified: i.Identified, Implementation: i.Implementation, NextFetch: i.NextFetch, + LastError: i.LastError, NodeInfoURL: i.NodeInfoURL, ServerImplementationString: i.ServerImplementationString, ServerVersionString: i.ServerVersionString, @@ -49,6 +50,7 @@ func (m *Manager) SaveInstance(i *instance.Instance) error { ei.Fetching = i.Fetching ei.HighestID = i.HighestID ei.Hostname = i.Hostname + ei.LastError = i.LastError ei.Identified = i.Identified ei.Implementation = string(i.Implementation) ei.NextFetch = i.NextFetch @@ -56,7 +58,6 @@ func (m *Manager) SaveInstance(i *instance.Instance) error { ei.ServerImplementationString = i.ServerImplementationString ei.ServerVersionString = i.ServerVersionString ei.SuccessCount = i.SuccessCount - r := m.db.Save(&ei) return r.Error } @@ -77,6 +78,7 @@ func (m *Manager) ListInstances() ([]*instance.Instance, error) { x.Fetching = i.Fetching x.HighestID = i.HighestID x.Hostname = i.Hostname + x.LastError = i.LastError x.Identified = i.Identified x.Implementation = i.Implementation x.NextFetch = i.NextFetch diff --git a/database/model.go b/database/model.go index 307b782..93c942d 100644 --- a/database/model.go +++ b/database/model.go @@ -21,7 +21,7 @@ type StoredToot struct { Content []byte TextContent []byte URL string - Hostname string + Hostname string `gorm:"index:hostnameindex"` } type APInstance struct { @@ -34,6 +34,7 @@ type APInstance struct { Identified bool Fetching bool Disabled bool + LastError string Implementation string NextFetch time.Time NodeInfoURL string diff --git a/database/readshortcuts.go b/database/readshortcuts.go new file mode 100644 index 0000000..79edb89 --- /dev/null +++ b/database/readshortcuts.go @@ -0,0 +1,24 @@ +package database + +import ( + "github.com/google/uuid" +) + +func (m *Manager) TootCountForHostname(hostname string) (uint, error) { + var c uint + e := m.db.Model(&StoredToot{}).Where("hostname = ?", hostname).Count(&c) + if e.Error != nil { + return 0, e.Error + } else { + return c, nil + } +} + +func (m *Manager) GetAPInstanceFromUUID(uuid *uuid.UUID) (*APInstance, error) { + var i APInstance + e := m.db.Model(&APInstance{}).Where("uuid = ?", uuid).First(&i) + if e.Error != nil { + return nil, e.Error + } + return &i, nil +} diff --git a/instance/instance.go b/instance/instance.go index 6247ae8..fd6eed6 100644 --- a/instance/instance.go +++ b/instance/instance.go @@ -37,6 +37,7 @@ type Instance struct { Implementation string InitialFSMState string NextFetch time.Time + LastError string NodeInfoURL string ServerImplementationString string ServerVersionString string diff --git a/process/handlers.go b/process/handlers.go index 3b11984..ffeb8b5 100644 --- a/process/handlers.go +++ b/process/handlers.go @@ -20,15 +20,19 @@ func (a *Server) instances() []hash { now := time.Now() for _, v := range a.feta.manager.ListInstances() { i := make(hash) + // TODO move this locking onto a method on Instance that just + // returns a new hash // FIXME figure out why a very short lock here deadlocks v.Lock() i["hostname"] = v.Hostname + i["uuid"] = v.UUID.String() i["nextCheck"] = v.NextFetch.UTC().Format(time.RFC3339) i["nextCheckAfter"] = (-1 * now.Sub(v.NextFetch)).String() i["successCount"] = v.SuccessCount i["errorCount"] = v.ErrorCount i["identified"] = v.Identified - i["status"] = v.Status() //FIXME maybe this is why + //this only locks the FSM, not the whole instance struct + i["status"] = v.Status() i["software"] = "unknown" i["version"] = "unknown" if v.Identified { @@ -38,6 +42,14 @@ func (a *Server) instances() []hash { v.Unlock() resp = append(resp, i) } + + for _, item := range resp { + count, err := a.feta.dbm.TootCountForHostname(item["hostname"].(string)) + item["tootCount"] = 0 + if err != nil { + item["tootCount"] = count + } + } return resp } @@ -75,10 +87,27 @@ func (a *Server) getInstanceListHandler() http.HandlerFunc { } */ +func (a *Server) instanceHandler(c echo.Context) error { + tu := c.Param("uuid") + u, err := uuid.Parse(tu) + if err != nil { + return c.String(http.StatusNotFound, "404 not found") + } + + + i := a.feta.manager.ListInstances() { + tc := pongo2.Context{ + "instance": i, + } + + return c.Render(http.StatusOK, "instance.html", tc) +} + func (a *Server) indexHandler(c echo.Context) error { tc := pongo2.Context{ - "time": time.Now().UTC().Format(time.RFC3339Nano), - "gitrev": a.feta.version, + "time": time.Now().UTC().Format(time.RFC3339Nano), + "gitrev": a.feta.version, + "instances": a.instances(), } return c.Render(http.StatusOK, "index.html", tc) } diff --git a/process/server.go b/process/server.go index 29270af..b117b04 100644 --- a/process/server.go +++ b/process/server.go @@ -95,6 +95,7 @@ func (s *Server) initRouter() { // Routes s.e.GET("/", s.indexHandler) + s.e.GET("/instance/:uuid", s.instanceHandler) s.e.GET("/stats.json", s.statsHandler) s.e.GET("/.well-known/healthcheck.json", s.healthCheckHandler) //a.e.GET("/about", s.aboutHandler) diff --git a/view/base.html b/view/base.html index f299191..8ecb07f 100644 --- a/view/base.html +++ b/view/base.html @@ -10,6 +10,7 @@ --> {{ htmltitle }} +