diff --git a/Server.go b/Server.go index 093080c..477b8e8 100644 --- a/Server.go +++ b/Server.go @@ -8,6 +8,7 @@ import ( "os" "regexp" "strings" + "sync" "time" "github.com/boltdb/bolt" @@ -44,6 +45,7 @@ type Server struct { opts ServerOptions db *bolt.DB startTime time.Time + thumbnailSem sync.Mutex metadataBucket []byte } diff --git a/thumb.go b/thumb.go index cfcc3bb..556a208 100644 --- a/thumb.go +++ b/thumb.go @@ -1,6 +1,7 @@ package contented import ( + "context" "errors" "fmt" "log" @@ -51,6 +52,8 @@ func getThumbnailerConfig(t byte) (*thumbnail.Config, error) { } func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnailType byte, fileId string) { + ctx := r.Context() + opts, err := getThumbnailerConfig(thumbnailType) if err != nil { log.Printf("%s Thumbnail failed: %s\n", this.remoteIP(r), err.Error()) @@ -58,9 +61,18 @@ func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnai return } + // Only calculate one thumbnail at a time + this.thumbnailSem.Lock() + defer this.thumbnailSem.Unlock() + + if ctx.Err() != nil { + // The request was already cancelled + return + } + t := thumbnail.NewThumbnailerEx(opts) - err = this.handleThumbInternal(w, t, fileId) + err = this.handleThumbInternal(ctx, w, t, fileId) if err != nil { log.Printf("%s Thumbnail failed: %s\n", this.remoteIP(r), err.Error()) @@ -69,7 +81,7 @@ func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnai } } -func (this *Server) handleThumbInternal(w http.ResponseWriter, t thumbnail.Thumbnailer, fileId string) error { +func (this *Server) handleThumbInternal(ctx context.Context, w http.ResponseWriter, t thumbnail.Thumbnailer, fileId string) error { // Load metadata m, err := this.Metadata(fileId)