gui: New rest endpoint to get errors when web UI is opened

Since #4340 pulls aren't happening every 10s anymore and may be delayed up to 1h.
This means that no folder error event reaches the web UI for a long time, thus no
failed items will show up for a long time. Now errors are populated when the
web UI is opened.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4650
LGTM: AudriusButkevicius
This commit is contained in:
Simon Frei
2018-01-14 17:01:06 +00:00
committed by Audrius Butkevicius
parent 89a021609b
commit fecb21cdb1
10 changed files with 96 additions and 57 deletions

View File

@@ -111,6 +111,7 @@ type modelIntf interface {
RemoteSequence(folder string) (int64, bool)
State(folder string) (string, time.Time, error)
UsageReportingStats(version int, preview bool) map[string]interface{}
PullErrors(folder string) ([]model.FileError, error)
}
type configIntf interface {
@@ -263,6 +264,7 @@ func (s *apiService) Serve() {
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
getRestMux.HandleFunc("/rest/folder/versions", s.getFolderVersions) // folder
getRestMux.HandleFunc("/rest/folder/pullerrors", s.getPullErrors) // folder
getRestMux.HandleFunc("/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events]
getRestMux.HandleFunc("/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
getRestMux.HandleFunc("/rest/stats/device", s.getDeviceStats) // -
@@ -681,12 +683,23 @@ func jsonCompletion(comp model.FolderCompletion) map[string]interface{} {
func (s *apiService) getDBStatus(w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
folder := qs.Get("folder")
sendJSON(w, folderSummary(s.cfg, s.model, folder))
if sum, err := folderSummary(s.cfg, s.model, folder); err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
} else {
sendJSON(w, sum)
}
}
func folderSummary(cfg configIntf, m modelIntf, folder string) map[string]interface{} {
func folderSummary(cfg configIntf, m modelIntf, folder string) (map[string]interface{}, error) {
var res = make(map[string]interface{})
pullErrors, err := m.PullErrors(folder)
if err != nil && err != model.ErrFolderPaused {
// Stats from the db can still be obtained if the folder is just paused
return nil, err
}
res["pullErrors"] = len(pullErrors)
res["invalid"] = "" // Deprecated, retains external API for now
global := m.GlobalSize(folder)
@@ -700,7 +713,6 @@ func folderSummary(cfg configIntf, m modelIntf, folder string) map[string]interf
res["inSyncFiles"], res["inSyncBytes"] = global.Files-need.Files, global.Bytes-need.Bytes
var err error
res["state"], res["stateChanged"], err = m.State(folder)
if err != nil {
res["error"] = err.Error()
@@ -721,7 +733,7 @@ func folderSummary(cfg configIntf, m modelIntf, folder string) map[string]interf
}
}
return res
return res, nil
}
func (s *apiService) postDBOverride(w http.ResponseWriter, r *http.Request) {
@@ -1352,6 +1364,36 @@ func (s *apiService) postFolderVersionsRestore(w http.ResponseWriter, r *http.Re
sendJSON(w, ferr)
}
func (s *apiService) getPullErrors(w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
folder := qs.Get("folder")
page, perpage := getPagingParams(qs)
errors, err := s.model.PullErrors(folder)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
start := (page - 1) * perpage
if start >= len(errors) {
errors = nil
} else {
errors = errors[start:]
if perpage < len(errors) {
errors = errors[:perpage]
}
}
sendJSON(w, map[string]interface{}{
"folder": folder,
"errors": errors,
"page": page,
"perpage": perpage,
})
}
func (s *apiService) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
current := qs.Get("current")