From 3cec26d42db0529f14e82115515c9731ead2dd78 Mon Sep 17 00:00:00 2001 From: Erik Dubbelboer Date: Sat, 6 Feb 2021 10:22:14 +0100 Subject: [PATCH] Allow stopping FS handler cleanup gorountine (#942) * Allow stopping FS handler cleanup gorountine * CleanStop --- fs.go | 27 ++++++++++++++++++++++++++- fs_test.go | 20 ++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/fs.go b/fs.go index 77a2a24379..f8d4add94c 100644 --- a/fs.go +++ b/fs.go @@ -282,6 +282,11 @@ type FS struct { // FSCompressedFileSuffixes is used by default. CompressedFileSuffixes map[string]string + // If CleanStop is set, the channel can be closed to stop the cleanup handlers + // for the FS RequestHandlers created with NewRequestHandler. + // NEVER close this channel while the handler is still being used! + CleanStop chan struct{} + once sync.Once h RequestHandler } @@ -399,9 +404,29 @@ func (fs *FS) initRequestHandler() { go func() { var pendingFiles []*fsFile + + clean := func() { + pendingFiles = h.cleanCache(pendingFiles) + } + + if fs.CleanStop != nil { + t := time.NewTicker(cacheDuration / 2) + for { + select { + case <-t.C: + clean() + case _, stillOpen := <-fs.CleanStop: + // Ignore values send on the channel, only stop when it is closed. + if !stillOpen { + t.Stop() + return + } + } + } + } for { time.Sleep(cacheDuration / 2) - pendingFiles = h.cleanCache(pendingFiles) + clean() } }() diff --git a/fs_test.go b/fs_test.go index 8465ff8d29..01f8849173 100644 --- a/fs_test.go +++ b/fs_test.go @@ -70,9 +70,13 @@ func testPathNotFound(t *testing.T, pathNotFoundFunc RequestHandler) { req.SetRequestURI("http//some.url/file") ctx.Init(&req, nil, TestLogger{t}) + stop := make(chan struct{}) + defer close(stop) + fs := &FS{ Root: "./", PathNotFound: pathNotFoundFunc, + CleanStop: stop, } fs.NewRequestHandler()(&ctx) @@ -299,9 +303,13 @@ func TestServeFileUncompressed(t *testing.T) { func TestFSByteRangeConcurrent(t *testing.T) { t.Parallel() + stop := make(chan struct{}) + defer close(stop) + fs := &FS{ Root: ".", AcceptByteRange: true, + CleanStop: stop, } h := fs.NewRequestHandler() @@ -329,9 +337,13 @@ func TestFSByteRangeConcurrent(t *testing.T) { func TestFSByteRangeSingleThread(t *testing.T) { t.Parallel() + stop := make(chan struct{}) + defer close(stop) + fs := &FS{ Root: ".", AcceptByteRange: true, + CleanStop: stop, } h := fs.NewRequestHandler() @@ -468,11 +480,15 @@ func testParseByteRangeError(t *testing.T, v string, contentLength int) { func TestFSCompressConcurrent(t *testing.T) { // This test can't run parallel as files in / might by changed by other tests. + stop := make(chan struct{}) + defer close(stop) + fs := &FS{ Root: ".", GenerateIndexPages: true, Compress: true, CompressBrotli: true, + CleanStop: stop, } h := fs.NewRequestHandler() @@ -501,11 +517,15 @@ func TestFSCompressConcurrent(t *testing.T) { func TestFSCompressSingleThread(t *testing.T) { // This test can't run parallel as files in / might by changed by other tests. + stop := make(chan struct{}) + defer close(stop) + fs := &FS{ Root: ".", GenerateIndexPages: true, Compress: true, CompressBrotli: true, + CleanStop: stop, } h := fs.NewRequestHandler()