Repository: prometheus/tsdb
Pull request #539 (2019-03-04 14:12:05)

[bug] didn't update 'last' variable in chunks.MergeOverlappingChunks()
1. Update 'last' variable after appending a chunk.
2. I add test case for it. The blocks of labels ("before", "fix") are overlapping together and they can pass in the original codes. The blocks of labels ("after", "fix") are overlapping only for the last two blocks and cannot pass in the original codes.


Patch:
diff --git a/.travis.yml b/.travis.yml
index faed514..c146e02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,3 @@
-# sudo is enabled because it provides more memory which was needed to run go test -race
-sudo: required
 dist: trusty
 language: go
 os:
@@ -10,6 +8,7 @@ os:
 go:
   - 1.10.x
   - 1.11.x
+  - 1.12.x
 
 go_import_path: github.com/prometheus/tsdb
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 534de25..dca10c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,5 @@
 ## master / unreleased
+  - [BUGFIX] Update `last` after appending a non-overlapping chunk in `chunks.MergeOverlappingChunks`. [#539](https://github.com/prometheus/tsdb/pull/539)
 
 ## 0.6.0
   - [CHANGE] `AllowOverlappingBlock` is now `AllowOverlappingBlocks`.
diff --git a/Makefile.common b/Makefile.common
index 7e86f45..7105cff 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -70,7 +70,7 @@ else
 	GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)
 endif
 
-PROMU_VERSION ?= 0.2.0
+PROMU_VERSION ?= 0.3.0
 PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
 STATICCHECK_VERSION ?= 2019.1
 STATICCHECK_URL     := https://github.com/dominikh/go-tools/releases/download/$(STATICCHECK_VERSION)/staticcheck_$(GOHOSTOS)_$(GOHOSTARCH)
diff --git a/chunks/chunks.go b/chunks/chunks.go
index 3f643bc..dd5a5f8 100644
--- a/chunks/chunks.go
+++ b/chunks/chunks.go
@@ -213,6 +213,7 @@ func MergeOverlappingChunks(chks []Meta) ([]Meta, error) {
 		// So never overlaps with newChks[last-1] or anything before that.
 		if c.MinTime > newChks[last].MaxTime {
 			newChks = append(newChks, c)
+			last += 1
 			continue
 		}
 		nc := &newChks[last]


Test patch:
diff --git a/compact_test.go b/compact_test.go
index 9dc9396..1e06b39 100644
--- a/compact_test.go
+++ b/compact_test.go
@@ -653,7 +653,8 @@ func TestCompaction_populateBlock(t *testing.T) {
 			expErr:         errors.New("found chunk with minTime: 10 maxTime: 20 outside of compacted minTime: 0 maxTime: 10"),
 		},
 		{
-			// No special deduplication expected.
+			// Deduplication expected.
+			// Introduced by pull/370 and pull/539.
 			title: "Populate from two blocks containing duplicated chunk.",
 			inputSeriesSamples: [][]seriesSamples{
 				{
@@ -672,7 +673,53 @@ func TestCompaction_populateBlock(t *testing.T) {
 			expSeriesSamples: []seriesSamples{
 				{
 					lset:   map[string]string{"a": "b"},
-					chunks: [][]sample{{{t: 1}, {t: 2}}, {{t: 10}, {t: 20}}, {{t: 10}, {t: 20}}},
+					chunks: [][]sample{{{t: 1}, {t: 2}}, {{t: 10}, {t: 20}}},
+				},
+			},
+		},
+		{
+			// Introduced by https://github.com/prometheus/tsdb/pull/539.
+			title: "Populate from three blocks that the last two are overlapping.",
+			inputSeriesSamples: [][]seriesSamples{
+				{
+					{
+						lset:   map[string]string{"before": "fix"},
+						chunks: [][]sample{{{t: 0}, {t: 10}, {t: 11}, {t: 20}}},
+					},
+					{
+						lset:   map[string]string{"after": "fix"},
+						chunks: [][]sample{{{t: 0}, {t: 10}, {t: 11}, {t: 20}}},
+					},
+				},
+				{
+					{
+						lset:   map[string]string{"before": "fix"},
+						chunks: [][]sample{{{t: 19}, {t: 30}}},
+					},
+					{
+						lset:   map[string]string{"after": "fix"},
+						chunks: [][]sample{{{t: 21}, {t: 30}}},
+					},
+				},
+				{
+					{
+						lset:   map[string]string{"before": "fix"},
+						chunks: [][]sample{{{t: 27}, {t: 35}}},
+					},
+					{
+						lset:   map[string]string{"after": "fix"},
+						chunks: [][]sample{{{t: 27}, {t: 35}}},
+					},
+				},
+			},
+			expSeriesSamples: []seriesSamples{
+				{
+					lset:   map[string]string{"after": "fix"},
+					chunks: [][]sample{{{t: 0}, {t: 10}, {t: 11}, {t: 20}}, {{t: 21}, {t: 27}, {t: 30}, {t: 35}}},
+				},
+				{
+					lset:   map[string]string{"before": "fix"},
+					chunks: [][]sample{{{t: 0}, {t: 10}, {t: 11}, {t: 19}, {t: 20}, {t: 27}, {t: 30}, {t: 35}}},
 				},
 			},
 		},