Przeglądaj źródła

Show 503 page on collections under high load

This acknowledges "too many connections" and "max user connections"
errors in MySQL and propagates the error up the chain so we can notify
the user and return the correct HTTP code.
pull/284/head
Matt Baer 4 lat temu
rodzic
commit
0285a9b0bd
5 zmienionych plików z 30 dodań i 0 usunięć
  1. +10
    -0
      database-no-sqlite.go
  2. +4
    -0
      database.go
  3. +2
    -0
      errors.go
  4. +7
    -0
      handle.go
  5. +7
    -0
      pages/503.tmpl

+ 10
- 0
database-no-sqlite.go Wyświetl plik

@@ -40,3 +40,13 @@ func (db *datastore) isIgnorableError(err error) bool {

return false
}

func (db *datastore) isHighLoadError(err error) bool {
if db.driverName == driverMySQL {
if mysqlErr, ok := err.(*mysql.MySQLError); ok {
return mysqlErr.Number == mySQLErrMaxUserConns || mysqlErr.Number == mySQLErrTooManyConns
}
}

return false
}

+ 4
- 0
database.go Wyświetl plik

@@ -39,6 +39,8 @@ import (
const (
mySQLErrDuplicateKey = 1062
mySQLErrCollationMix = 1267
mySQLErrTooManyConns = 1040
mySQLErrMaxUserConns = 1203

driverMySQL = "mysql"
driverSQLite = "sqlite3"
@@ -793,6 +795,8 @@ func (db *datastore) GetCollectionBy(condition string, value interface{}) (*Coll
switch {
case err == sql.ErrNoRows:
return nil, impart.HTTPError{http.StatusNotFound, "Collection doesn't exist."}
case db.isHighLoadError(err):
return nil, ErrUnavailable
case err != nil:
log.Error("Failed selecting from collections: %v", err)
return nil, err


+ 2
- 0
errors.go Wyświetl plik

@@ -37,6 +37,8 @@ var (
ErrInternalGeneral = impart.HTTPError{http.StatusInternalServerError, "The humans messed something up. They've been notified."}
ErrInternalCookieSession = impart.HTTPError{http.StatusInternalServerError, "Could not get cookie session."}

ErrUnavailable = impart.HTTPError{http.StatusServiceUnavailable, "Service temporarily unavailable due to high load."}

ErrCollectionNotFound = impart.HTTPError{http.StatusNotFound, "Collection doesn't exist."}
ErrCollectionGone = impart.HTTPError{http.StatusGone, "This blog was unpublished."}
ErrCollectionPageNotFound = impart.HTTPError{http.StatusNotFound, "Collection page doesn't exist."}


+ 7
- 0
handle.go Wyświetl plik

@@ -83,6 +83,7 @@ type ErrorPages struct {
NotFound *template.Template
Gone *template.Template
InternalServerError *template.Template
UnavailableError *template.Template
Blank *template.Template
}

@@ -94,6 +95,7 @@ func NewHandler(apper Apper) *Handler {
NotFound: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>404</title></head><body><p>Not found.</p></body></html>{{end}}")),
Gone: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>410</title></head><body><p>Gone.</p></body></html>{{end}}")),
InternalServerError: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>500</title></head><body><p>Internal server error.</p></body></html>{{end}}")),
UnavailableError: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>503</title></head><body><p>Service is temporarily unavailable.</p></body></html>{{end}}")),
Blank: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>{{.Title}}</title></head><body><p>{{.Content}}</p></body></html>{{end}}")),
},
sessionStore: apper.App().SessionStore(),
@@ -111,6 +113,7 @@ func NewWFHandler(apper Apper) *Handler {
NotFound: pages["404-general.tmpl"],
Gone: pages["410.tmpl"],
InternalServerError: pages["500.tmpl"],
UnavailableError: pages["503.tmpl"],
Blank: pages["blank.tmpl"],
})
return h
@@ -763,6 +766,10 @@ func (h *Handler) handleHTTPError(w http.ResponseWriter, r *http.Request, err er
log.Info("handleHTTPErorr internal error render")
h.errors.InternalServerError.ExecuteTemplate(w, "base", pageForReq(h.app.App(), r))
return
} else if err.Status == http.StatusServiceUnavailable {
w.WriteHeader(err.Status)
h.errors.UnavailableError.ExecuteTemplate(w, "base", pageForReq(h.app.App(), r))
return
} else if err.Status == http.StatusAccepted {
impart.WriteSuccess(w, "", err.Status)
return


+ 7
- 0
pages/503.tmpl Wyświetl plik

@@ -0,0 +1,7 @@
{{define "head"}}<title>Temporarily Unavailable &mdash; {{.SiteMetaName}}</title>{{end}}
{{define "content"}}
<div class="error-page">
<p class="msg">The words aren't coming to me. &#x1F5C5;</p>
<p>We couldn't serve this page due to high server load. This should only be temporary.</p>
</div>
{{end}}

Ładowanie…
Anuluj
Zapisz