Skip to content

Commit fb62fa4

Browse files
authored
fix(manifest): resolve node persistence after removal (#4819)
1 parent dab9aa1 commit fb62fa4

File tree

4 files changed

+119
-3
lines changed

4 files changed

+119
-3
lines changed

pkg/manifest/mantaray/marshal.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ func (n *Node) UnmarshalBinary(data []byte) error {
287287
bb.fromBytes(data[offset:])
288288
offset += 32 // skip forks
289289
return bb.iter(func(b byte) error {
290+
if refBytesSize == 0 {
291+
return nil
292+
}
290293
f := &fork{}
291294

292295
if len(data) < offset+nodeForkTypeBytesSize {
@@ -296,7 +299,6 @@ func (n *Node) UnmarshalBinary(data []byte) error {
296299
nodeType := data[offset]
297300

298301
nodeForkSize := nodeForkPreReferenceSize + refBytesSize
299-
300302
if nodeTypeIsWithMetadataType(nodeType) {
301303
if len(data) < offset+nodeForkPreReferenceSize+refBytesSize+nodeForkMetadataBytesSize {
302304
return fmt.Errorf("not enough bytes for node fork: %d (%d) on byte '%x': %w", (len(data) - offset), (nodeForkPreReferenceSize + refBytesSize + nodeForkMetadataBytesSize), []byte{b}, ErrInvalidManifest)

pkg/manifest/mantaray/node.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,11 @@ func (n *Node) Remove(ctx context.Context, path []byte, ls LoadSaver) error {
311311
return ErrNotFound
312312
}
313313
rest := path[len(f.prefix):]
314+
defer func() {
315+
n.ref = nil
316+
}()
314317
if len(rest) == 0 {
315-
// full path matched
318+
316319
delete(n.forks, path[0])
317320
return nil
318321
}

pkg/manifest/mantaray/persist.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package mantaray
77
import (
88
"context"
99
"errors"
10-
1110
"golang.org/x/sync/errgroup"
1211
)
1312

pkg/manifest/mantaray/persist_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
"context"
1010
"crypto/sha256"
11+
"errors"
1112
"sync"
1213
"testing"
1314

@@ -62,6 +63,117 @@ func TestPersistIdempotence(t *testing.T) {
6263
}
6364
}
6465

66+
func TestPersistRemove(t *testing.T) {
67+
t.Parallel()
68+
69+
for _, tc := range []struct {
70+
name string
71+
toAdd []mantaray.NodeEntry
72+
toRemove [][]byte
73+
}{
74+
{
75+
name: "simple",
76+
toAdd: []mantaray.NodeEntry{
77+
{
78+
Path: []byte("/"),
79+
Metadata: map[string]string{
80+
"index-document": "index.html",
81+
},
82+
},
83+
{
84+
Path: []byte("index.html"),
85+
},
86+
{
87+
Path: []byte("img/1.png"),
88+
},
89+
{
90+
Path: []byte("img/2.png"),
91+
},
92+
{
93+
Path: []byte("robots.txt"),
94+
},
95+
},
96+
toRemove: [][]byte{
97+
[]byte("img/2.png"),
98+
},
99+
},
100+
{
101+
name: "nested-prefix-is-not-collapsed",
102+
toAdd: []mantaray.NodeEntry{
103+
{
104+
Path: []byte("index.html"),
105+
},
106+
{
107+
Path: []byte("img/1.png"),
108+
},
109+
{
110+
Path: []byte("img/2/test1.png"),
111+
},
112+
{
113+
Path: []byte("img/2/test2.png"),
114+
},
115+
{
116+
Path: []byte("robots.txt"),
117+
},
118+
},
119+
toRemove: [][]byte{
120+
[]byte("img/2/test1.png"),
121+
},
122+
},
123+
} {
124+
ctx := context.Background()
125+
var ls mantaray.LoadSaver = newMockLoadSaver()
126+
t.Run(tc.name, func(t *testing.T) {
127+
t.Parallel()
128+
129+
// add and persist
130+
n := mantaray.New()
131+
for i := 0; i < len(tc.toAdd); i++ {
132+
c := tc.toAdd[i].Path
133+
e := tc.toAdd[i].Entry
134+
if len(e) == 0 {
135+
e = append(make([]byte, 32-len(c)), c...)
136+
}
137+
m := tc.toAdd[i].Metadata
138+
err := n.Add(ctx, c, e, m, ls)
139+
if err != nil {
140+
t.Fatalf("expected no error, got %v", err)
141+
}
142+
}
143+
err := n.Save(ctx, ls)
144+
if err != nil {
145+
t.Fatalf("expected no error, got %v", err)
146+
}
147+
ref := n.Reference()
148+
// reload and remove
149+
nn := mantaray.NewNodeRef(ref)
150+
for i := 0; i < len(tc.toRemove); i++ {
151+
c := tc.toRemove[i]
152+
err := nn.Remove(ctx, c, ls)
153+
if err != nil {
154+
t.Fatalf("expected no error, got %v", err)
155+
}
156+
}
157+
158+
err = nn.Save(ctx, ls)
159+
if err != nil {
160+
t.Fatalf("expected no error, got %v", err)
161+
}
162+
163+
ref = nn.Reference()
164+
// reload and lookup removed node
165+
nnn := mantaray.NewNodeRef(ref)
166+
for i := 0; i < len(tc.toRemove); i++ {
167+
c := tc.toRemove[i]
168+
_, err = nnn.LookupNode(ctx, c, ls)
169+
if !errors.Is(err, mantaray.ErrNotFound) {
170+
t.Fatalf("expected not found error, got %v", err)
171+
}
172+
}
173+
})
174+
}
175+
}
176+
65177
type addr [32]byte
66178
type mockLoadSaver struct {
67179
mtx sync.Mutex

0 commit comments

Comments
 (0)