From c102b41a97b191bff092dd7e8f1497d6ae7826aa Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 05:05:46 -0500 Subject: [PATCH 01/10] file bucket --- pmtiles/bucket.go | 48 ++++++++++++++++++++++++++++++++++++++++++ pmtiles/bucket_test.go | 33 +++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/pmtiles/bucket.go b/pmtiles/bucket.go index 979730d..561f9be 100644 --- a/pmtiles/bucket.go +++ b/pmtiles/bucket.go @@ -67,6 +67,46 @@ func (m mockBucket) NewRangeReaderEtag(_ context.Context, key string, offset int return io.NopCloser(bytes.NewReader(bs[offset:(offset + length)])), resultEtag, nil } +// FileBucket is a bucket backed by a directory on disk +type FileBucket struct { + path string +} + +func (b FileBucket) NewRangeReader(ctx context.Context, key string, offset, length int64) (io.ReadCloser, error) { + body, _, err := b.NewRangeReaderEtag(ctx, key, offset, length, "") + return body, err +} + +func (b FileBucket) NewRangeReaderEtag(ctx context.Context, key string, offset, length int64, etag string) (io.ReadCloser, string, error) { + name := b.path + string(os.PathSeparator) + key + file, err := os.Open(name) + defer file.Close() + if err != nil { + return nil, "", err + } + info, err := file.Stat() + if err != nil { + return nil, "", err + } + newEtag := fmt.Sprintf("%d %d", info.ModTime().UnixNano(), info.Size()) + if len(etag) > 0 && etag != newEtag { + return nil, "", &RefreshRequiredError{} + } + result := make([]byte, length) + read, err := file.ReadAt(result, offset) + if err != nil { + return nil, "", err + } + if read != int(length) { + return nil, "", fmt.Errorf("Expected to read %d bytes but only read %d", length, read) + } + return io.NopCloser(bytes.NewReader(result)), newEtag, nil +} + +func (b FileBucket) Close() error { + return nil +} + // HTTPClient is an interface that lets you swap out the default client with a mock one in tests type HTTPClient interface { Do(req *http.Request) (*http.Response, error) @@ -198,6 +238,14 @@ func OpenBucket(ctx context.Context, bucketURL string, bucketPrefix string) (Buc bucket := HTTPBucket{bucketURL, http.DefaultClient} return bucket, nil } + if strings.HasPrefix(bucketURL, "file") { + url, err := url.ParseRequestURI(bucketURL) + if err != nil { + return nil, err + } + bucket := FileBucket{url.Path} + return bucket, nil + } bucket, err := blob.OpenBucket(ctx, bucketURL) if err != nil { return nil, err diff --git a/pmtiles/bucket_test.go b/pmtiles/bucket_test.go index f65681b..8ebe854 100644 --- a/pmtiles/bucket_test.go +++ b/pmtiles/bucket_test.go @@ -2,6 +2,7 @@ package pmtiles import ( "context" + "fmt" "io" "net/http" "os" @@ -9,6 +10,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + _ "gocloud.dev/blob/fileblob" ) func TestNormalizeLocalFile(t *testing.T) { @@ -114,3 +116,34 @@ func TestHttpBucketRequestRequestEtagFailed(t *testing.T) { _, _, err = bucket.NewRangeReaderEtag(context.Background(), "a/b/c", 0, 3, "etag1") assert.False(t, isRefreshRequredError(err)) } + +func TestFileBucket(t *testing.T) { + dir := t.TempDir() + bucketURL, _, err := NormalizeBucketKey("", dir, "") + assert.Nil(t, err) + fmt.Println(bucketURL) + bucket, err := OpenBucket(context.Background(), bucketURL, "") + assert.Nil(t, err) + assert.NotNil(t, bucket) + assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) + + // first read from file + reader, etag1, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") + assert.Nil(t, err) + data, err := io.ReadAll(reader) + assert.Nil(t, err) + assert.Equal(t, []byte{2}, data) + + // change file, verify etag changes + assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{4, 5, 6}, 0666)) + reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") + assert.Nil(t, err) + data, err = io.ReadAll(reader) + assert.Nil(t, err) + assert.NotEqual(t, etag1, etag2) + assert.Equal(t, []byte{5}, data) + + // and requesting with old etag fails with refresh required error + _, _, err = bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, etag1) + assert.True(t, isRefreshRequredError(err)) +} From 38671fb31f2b122d18eacc63e4815d00e7392894 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 06:00:15 -0500 Subject: [PATCH 02/10] proper etag --- pmtiles/bucket.go | 7 +++++-- pmtiles/bucket_test.go | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/pmtiles/bucket.go b/pmtiles/bucket.go index 561f9be..3f42dbe 100644 --- a/pmtiles/bucket.go +++ b/pmtiles/bucket.go @@ -70,6 +70,7 @@ func (m mockBucket) NewRangeReaderEtag(_ context.Context, key string, offset int // FileBucket is a bucket backed by a directory on disk type FileBucket struct { path string + file *os.File } func (b FileBucket) NewRangeReader(ctx context.Context, key string, offset, length int64) (io.ReadCloser, error) { @@ -88,7 +89,9 @@ func (b FileBucket) NewRangeReaderEtag(ctx context.Context, key string, offset, if err != nil { return nil, "", err } - newEtag := fmt.Sprintf("%d %d", info.ModTime().UnixNano(), info.Size()) + modInfo := fmt.Sprintf("%d %d", info.ModTime().UnixNano(), info.Size()) + hash := md5.Sum([]byte(modInfo)) + newEtag := fmt.Sprintf(`"%s"`, hex.EncodeToString(hash[:])) if len(etag) > 0 && etag != newEtag { return nil, "", &RefreshRequiredError{} } @@ -243,7 +246,7 @@ func OpenBucket(ctx context.Context, bucketURL string, bucketPrefix string) (Buc if err != nil { return nil, err } - bucket := FileBucket{url.Path} + bucket := FileBucket{url.Path, nil} return bucket, nil } bucket, err := blob.OpenBucket(ctx, bucketURL) diff --git a/pmtiles/bucket_test.go b/pmtiles/bucket_test.go index 8ebe854..b9e69a1 100644 --- a/pmtiles/bucket_test.go +++ b/pmtiles/bucket_test.go @@ -117,7 +117,7 @@ func TestHttpBucketRequestRequestEtagFailed(t *testing.T) { assert.False(t, isRefreshRequredError(err)) } -func TestFileBucket(t *testing.T) { +func TestFileBucketReplace(t *testing.T) { dir := t.TempDir() bucketURL, _, err := NormalizeBucketKey("", dir, "") assert.Nil(t, err) @@ -147,3 +147,38 @@ func TestFileBucket(t *testing.T) { _, _, err = bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, etag1) assert.True(t, isRefreshRequredError(err)) } + +func TestFileBucketRename(t *testing.T) { + dir := t.TempDir() + assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(dir+"/archive2.pmtiles", []byte{4, 5, 6}, 0666)) + + bucketURL, _, err := NormalizeBucketKey("", dir, "") + assert.Nil(t, err) + fmt.Println(bucketURL) + bucket, err := OpenBucket(context.Background(), bucketURL, "") + assert.Nil(t, err) + assert.NotNil(t, bucket) + assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) + + // first read from file + reader, etag1, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") + assert.Nil(t, err) + data, err := io.ReadAll(reader) + assert.Nil(t, err) + assert.Equal(t, []byte{2}, data) + + // change file, verify etag changes + os.Rename(dir+"/archive.pmtiles", dir+"/archive3.pmtiles") + os.Rename(dir+"/archive2.pmtiles", dir+"/archive.pmtiles") + reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") + assert.Nil(t, err) + data, err = io.ReadAll(reader) + assert.Nil(t, err) + assert.NotEqual(t, etag1, etag2) + assert.Equal(t, []byte{5}, data) + + // and requesting with old etag fails with refresh required error + _, _, err = bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, etag1) + assert.True(t, isRefreshRequredError(err)) +} From abba9fee509b6d1e212b6c147d27891d0147317e Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 06:04:33 -0500 Subject: [PATCH 03/10] rm --- pmtiles/bucket.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pmtiles/bucket.go b/pmtiles/bucket.go index 3f42dbe..1a9b226 100644 --- a/pmtiles/bucket.go +++ b/pmtiles/bucket.go @@ -70,7 +70,6 @@ func (m mockBucket) NewRangeReaderEtag(_ context.Context, key string, offset int // FileBucket is a bucket backed by a directory on disk type FileBucket struct { path string - file *os.File } func (b FileBucket) NewRangeReader(ctx context.Context, key string, offset, length int64) (io.ReadCloser, error) { @@ -246,7 +245,7 @@ func OpenBucket(ctx context.Context, bucketURL string, bucketPrefix string) (Buc if err != nil { return nil, err } - bucket := FileBucket{url.Path, nil} + bucket := FileBucket{url.Path} return bucket, nil } bucket, err := blob.OpenBucket(ctx, bucketURL) From 0c26a49662fa8c1a8b690723eb76285af0cacf4f Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 06:31:32 -0500 Subject: [PATCH 04/10] run ci --- .github/workflows/test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e560c0..f34ab29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,9 @@ name: test -on: [push] +on: + pull_request: + branches: + - "main" jobs: test: @@ -12,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: '^1.21.0' + go-version: "^1.21.0" - run: go test ./pmtiles fmt_vet_lint: runs-on: ubuntu-latest @@ -20,7 +23,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: '^1.21.0' + go-version: "^1.21.0" - run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi - run: go vet caddy/pmtiles_proxy.go - run: go vet main.go From a324b1b1764b258ef7a416db0a6ab07af38b82dc Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 06:37:00 -0500 Subject: [PATCH 05/10] fix --- pmtiles/bucket_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pmtiles/bucket_test.go b/pmtiles/bucket_test.go index b9e69a1..1d81482 100644 --- a/pmtiles/bucket_test.go +++ b/pmtiles/bucket_test.go @@ -135,7 +135,7 @@ func TestFileBucketReplace(t *testing.T) { assert.Equal(t, []byte{2}, data) // change file, verify etag changes - assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{4, 5, 6}, 0666)) + assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{4, 5, 6, 7}, 0666)) reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") assert.Nil(t, err) data, err = io.ReadAll(reader) @@ -151,7 +151,7 @@ func TestFileBucketReplace(t *testing.T) { func TestFileBucketRename(t *testing.T) { dir := t.TempDir() assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) - assert.Nil(t, os.WriteFile(dir+"/archive2.pmtiles", []byte{4, 5, 6}, 0666)) + assert.Nil(t, os.WriteFile(dir+"/archive2.pmtiles", []byte{4, 5, 6, 7}, 0666)) bucketURL, _, err := NormalizeBucketKey("", dir, "") assert.Nil(t, err) From ff4d5d1b766313d51e7a7e72d15ed6d41c8635f2 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 06:42:27 -0500 Subject: [PATCH 06/10] fix --- pmtiles/bucket_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pmtiles/bucket_test.go b/pmtiles/bucket_test.go index 1d81482..7d19146 100644 --- a/pmtiles/bucket_test.go +++ b/pmtiles/bucket_test.go @@ -118,14 +118,14 @@ func TestHttpBucketRequestRequestEtagFailed(t *testing.T) { } func TestFileBucketReplace(t *testing.T) { - dir := t.TempDir() + dir := t.TempDir() + string(os.PathSeparator) bucketURL, _, err := NormalizeBucketKey("", dir, "") assert.Nil(t, err) fmt.Println(bucketURL) bucket, err := OpenBucket(context.Background(), bucketURL, "") assert.Nil(t, err) assert.NotNil(t, bucket) - assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{1, 2, 3}, 0666)) // first read from file reader, etag1, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") @@ -135,7 +135,7 @@ func TestFileBucketReplace(t *testing.T) { assert.Equal(t, []byte{2}, data) // change file, verify etag changes - assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{4, 5, 6, 7}, 0666)) + assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{4, 5, 6, 7}, 0666)) reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") assert.Nil(t, err) data, err = io.ReadAll(reader) @@ -149,9 +149,9 @@ func TestFileBucketReplace(t *testing.T) { } func TestFileBucketRename(t *testing.T) { - dir := t.TempDir() - assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) - assert.Nil(t, os.WriteFile(dir+"/archive2.pmtiles", []byte{4, 5, 6, 7}, 0666)) + dir := t.TempDir() + string(os.PathSeparator) + assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(dir+"archive2.pmtiles", []byte{4, 5, 6, 7}, 0666)) bucketURL, _, err := NormalizeBucketKey("", dir, "") assert.Nil(t, err) @@ -159,7 +159,7 @@ func TestFileBucketRename(t *testing.T) { bucket, err := OpenBucket(context.Background(), bucketURL, "") assert.Nil(t, err) assert.NotNil(t, bucket) - assert.Nil(t, os.WriteFile(dir+"/archive.pmtiles", []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{1, 2, 3}, 0666)) // first read from file reader, etag1, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") @@ -169,8 +169,8 @@ func TestFileBucketRename(t *testing.T) { assert.Equal(t, []byte{2}, data) // change file, verify etag changes - os.Rename(dir+"/archive.pmtiles", dir+"/archive3.pmtiles") - os.Rename(dir+"/archive2.pmtiles", dir+"/archive.pmtiles") + os.Rename(dir+"archive.pmtiles", dir+"archive3.pmtiles") + os.Rename(dir+"archive2.pmtiles", dir+"archive.pmtiles") reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") assert.Nil(t, err) data, err = io.ReadAll(reader) From 04efc677c6be8d7fd1d4b6014c6d42292e43413e Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 06:59:08 -0500 Subject: [PATCH 07/10] fix? --- pmtiles/bucket.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pmtiles/bucket.go b/pmtiles/bucket.go index 1a9b226..6dfde8f 100644 --- a/pmtiles/bucket.go +++ b/pmtiles/bucket.go @@ -241,11 +241,12 @@ func OpenBucket(ctx context.Context, bucketURL string, bucketPrefix string) (Buc return bucket, nil } if strings.HasPrefix(bucketURL, "file") { - url, err := url.ParseRequestURI(bucketURL) - if err != nil { - return nil, err + fileprotocol := "file://" + if string(os.PathSeparator) != "/" { + fileprotocol += "/" } - bucket := FileBucket{url.Path} + path := strings.Replace(bucketURL, fileprotocol, "", 1) + bucket := FileBucket{filepath.FromSlash(path)} return bucket, nil } bucket, err := blob.OpenBucket(ctx, bucketURL) From c9aad2a053eb90f412d75c0b48ebba1356e0df14 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 07:00:31 -0500 Subject: [PATCH 08/10] fix --- pmtiles/bucket.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmtiles/bucket.go b/pmtiles/bucket.go index 6dfde8f..a432d56 100644 --- a/pmtiles/bucket.go +++ b/pmtiles/bucket.go @@ -78,7 +78,7 @@ func (b FileBucket) NewRangeReader(ctx context.Context, key string, offset, leng } func (b FileBucket) NewRangeReaderEtag(ctx context.Context, key string, offset, length int64, etag string) (io.ReadCloser, string, error) { - name := b.path + string(os.PathSeparator) + key + name := filepath.Join(b.path, key) file, err := os.Open(name) defer file.Close() if err != nil { From 91e42ada54758e95dfc7a96a9a6fcbb0c239e1b2 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 07:02:35 -0500 Subject: [PATCH 09/10] cleanup test --- pmtiles/bucket_test.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pmtiles/bucket_test.go b/pmtiles/bucket_test.go index 7d19146..257b2f0 100644 --- a/pmtiles/bucket_test.go +++ b/pmtiles/bucket_test.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "os" + "path/filepath" "strings" "testing" @@ -118,14 +119,14 @@ func TestHttpBucketRequestRequestEtagFailed(t *testing.T) { } func TestFileBucketReplace(t *testing.T) { - dir := t.TempDir() + string(os.PathSeparator) - bucketURL, _, err := NormalizeBucketKey("", dir, "") + tmp := t.TempDir() + bucketURL, _, err := NormalizeBucketKey("", tmp, "") assert.Nil(t, err) fmt.Println(bucketURL) bucket, err := OpenBucket(context.Background(), bucketURL, "") assert.Nil(t, err) assert.NotNil(t, bucket) - assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(filepath.Join(tmp, "archive.pmtiles"), []byte{1, 2, 3}, 0666)) // first read from file reader, etag1, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") @@ -135,7 +136,7 @@ func TestFileBucketReplace(t *testing.T) { assert.Equal(t, []byte{2}, data) // change file, verify etag changes - assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{4, 5, 6, 7}, 0666)) + assert.Nil(t, os.WriteFile(filepath.Join(tmp, "archive.pmtiles"), []byte{4, 5, 6, 7}, 0666)) reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") assert.Nil(t, err) data, err = io.ReadAll(reader) @@ -149,17 +150,17 @@ func TestFileBucketReplace(t *testing.T) { } func TestFileBucketRename(t *testing.T) { - dir := t.TempDir() + string(os.PathSeparator) - assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{1, 2, 3}, 0666)) - assert.Nil(t, os.WriteFile(dir+"archive2.pmtiles", []byte{4, 5, 6, 7}, 0666)) + tmp := t.TempDir() + assert.Nil(t, os.WriteFile(filepath.Join(tmp, "archive.pmtiles"), []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(filepath.Join(tmp, "archive2.pmtiles"), []byte{4, 5, 6, 7}, 0666)) - bucketURL, _, err := NormalizeBucketKey("", dir, "") + bucketURL, _, err := NormalizeBucketKey("", tmp, "") assert.Nil(t, err) fmt.Println(bucketURL) bucket, err := OpenBucket(context.Background(), bucketURL, "") assert.Nil(t, err) assert.NotNil(t, bucket) - assert.Nil(t, os.WriteFile(dir+"archive.pmtiles", []byte{1, 2, 3}, 0666)) + assert.Nil(t, os.WriteFile(filepath.Join(tmp, "archive.pmtiles"), []byte{1, 2, 3}, 0666)) // first read from file reader, etag1, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") @@ -169,8 +170,8 @@ func TestFileBucketRename(t *testing.T) { assert.Equal(t, []byte{2}, data) // change file, verify etag changes - os.Rename(dir+"archive.pmtiles", dir+"archive3.pmtiles") - os.Rename(dir+"archive2.pmtiles", dir+"archive.pmtiles") + os.Rename(filepath.Join(tmp, "archive.pmtiles"), filepath.Join(tmp, "archive3.pmtiles")) + os.Rename(filepath.Join(tmp, "archive2.pmtiles"), filepath.Join(tmp, "archive.pmtiles")) reader, etag2, err := bucket.NewRangeReaderEtag(context.Background(), "archive.pmtiles", 1, 1, "") assert.Nil(t, err) data, err = io.ReadAll(reader) From 0d39a99518c74015714a63bf155448ec22a73e50 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Fri, 9 Feb 2024 07:08:35 -0500 Subject: [PATCH 10/10] cleanup warning --- pmtiles/bucket.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmtiles/bucket.go b/pmtiles/bucket.go index a432d56..a8cc269 100644 --- a/pmtiles/bucket.go +++ b/pmtiles/bucket.go @@ -77,7 +77,7 @@ func (b FileBucket) NewRangeReader(ctx context.Context, key string, offset, leng return body, err } -func (b FileBucket) NewRangeReaderEtag(ctx context.Context, key string, offset, length int64, etag string) (io.ReadCloser, string, error) { +func (b FileBucket) NewRangeReaderEtag(_ context.Context, key string, offset, length int64, etag string) (io.ReadCloser, string, error) { name := filepath.Join(b.path, key) file, err := os.Open(name) defer file.Close()