TestPartialReplay verifies that we can best-effort replay a partial/corrupted WAL block. This test works by flushing a WAL block across a few pages, corrupting one, and then replaying it.
(t *testing.T)
| 63 | // This test works by flushing a WAL block across a few pages, corrupting one, and then replaying |
| 64 | // it. |
| 65 | func TestPartialReplay(t *testing.T) { |
| 66 | decoder := model.MustNewSegmentDecoder(model.CurrentEncoding) |
| 67 | blockID := uuid.New() |
| 68 | basePath := t.TempDir() |
| 69 | |
| 70 | meta := backend.NewBlockMeta("fake", blockID, VersionString) |
| 71 | w, err := createWALBlock(meta, basePath, model.CurrentEncoding, 0) |
| 72 | require.NoError(t, err) |
| 73 | |
| 74 | // Flush a set of traces across 2 pages |
| 75 | count := 10 |
| 76 | ids := make([]common.ID, count) |
| 77 | trs := make([]*tempopb.Trace, count) |
| 78 | for i := 0; i < count; i++ { |
| 79 | ids[i] = test.ValidTraceID(nil) |
| 80 | trs[i] = test.MakeTrace(10, ids[i]) |
| 81 | trace.SortTrace(trs[i]) |
| 82 | |
| 83 | b1, err := decoder.PrepareForWrite(trs[i], 0, 0) |
| 84 | require.NoError(t, err) |
| 85 | |
| 86 | b2, err := decoder.ToObject([][]byte{b1}) |
| 87 | require.NoError(t, err) |
| 88 | |
| 89 | err = w.Append(ids[i], b2, 0, 0, true) |
| 90 | require.NoError(t, err) |
| 91 | |
| 92 | if i+1 == count/2 { |
| 93 | require.NoError(t, w.Flush()) |
| 94 | } |
| 95 | } |
| 96 | require.NoError(t, w.Flush()) |
| 97 | |
| 98 | // Delete half of page 2 |
| 99 | fpath := w.filepathOf(1) |
| 100 | info, err := os.Stat(fpath) |
| 101 | require.NoError(t, err) |
| 102 | require.NoError(t, os.Truncate(fpath, info.Size()/2)) |
| 103 | |
| 104 | // Replay, this has a warning on page 2 |
| 105 | w2, warning, err := openWALBlock(filepath.Base(w.walPath()), filepath.Dir(w.walPath()), 0, 0) |
| 106 | require.NoError(t, err) |
| 107 | require.ErrorContains(t, warning, "invalid magic footer of parquet file") |
| 108 | |
| 109 | // Verify we iterate only the records from the first flush |
| 110 | iter, err := w2.Iterator(context.Background()) |
| 111 | require.NoError(t, err) |
| 112 | |
| 113 | gotCount := 0 |
| 114 | for ; ; gotCount++ { |
| 115 | id, tr, err := iter.Next(context.Background()) |
| 116 | require.NoError(t, err) |
| 117 | |
| 118 | if id == nil { |
| 119 | break |
| 120 | } |
| 121 | |
| 122 | // Find trace in the input data |
nothing calls this directly
no test coverage detected