Skip to content

Commit ce3c954

Browse files
authored
MST walk, and repo tweak (#984)
Adds a `Walk` method to `Tree` for visiting all key/value in the MST. Also updates `GetRecordBytes` to return the CID, along with actual bytes. It needs to be looked up from the MST anyways, and this results in one less call/lookup in some cases. Code which doesn't need the CID can just ignore that return type.
2 parents 528f0e6 + 305d1f5 commit ce3c954

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

atproto/repo/mst/node.go

+19
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,25 @@ func (n *Node) writeToMap(m map[string]cid.Cid) error {
291291
return nil
292292
}
293293

294+
func (n *Node) walk(f func(key []byte, val cid.Cid) error) error {
295+
if n == nil {
296+
return fmt.Errorf("nil tree pointer")
297+
}
298+
for _, e := range n.Entries {
299+
if e.IsValue() {
300+
if err := f(e.Key, *e.Value); err != nil {
301+
return err
302+
}
303+
}
304+
if e.Child != nil {
305+
if err := e.Child.walk(f); err != nil {
306+
return err
307+
}
308+
}
309+
}
310+
return nil
311+
}
312+
294313
// Reads the value (CID) corresponding to the key. If key is not in the tree, returns (nil, nil).
295314
//
296315
// n: Node at top of sub-tree to operate on. Must not be nil.

atproto/repo/mst/tree.go

+5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ func (t *Tree) Get(key []byte) (*cid.Cid, error) {
7979
return t.Root.getCID(key, -1)
8080
}
8181

82+
// Walks the Tree, invoking the callback function on each key/value pair.
83+
func (t *Tree) Walk(f func(key []byte, val cid.Cid) error) error {
84+
return t.Root.walk(f)
85+
}
86+
8287
// Creates a new Tree by loading key/value pairs from a map.
8388
func LoadTreeFromMap(m map[string]cid.Cid) (*Tree, error) {
8489
if m == nil {

atproto/repo/repo.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,17 @@ func (repo *Repo) GetRecordCID(ctx context.Context, collection syntax.NSID, rkey
4848
return c, nil
4949
}
5050

51-
func (repo *Repo) GetRecordBytes(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey) ([]byte, error) {
51+
func (repo *Repo) GetRecordBytes(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey) ([]byte, *cid.Cid, error) {
5252
c, err := repo.GetRecordCID(ctx, collection, rkey)
5353
if err != nil {
54-
return nil, err
54+
return nil, nil, err
5555
}
5656
blk, err := repo.RecordStore.Get(ctx, *c)
5757
if err != nil {
58-
return nil, err
58+
return nil, nil, err
5959
}
6060
// TODO: not verifying CID
61-
return blk.RawData(), nil
61+
return blk.RawData(), c, nil
6262
}
6363

6464
// Snapshots the current state of the repository, resulting in a new (unsigned) `Commit` struct.

atproto/repo/sync.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,14 @@ func VerifyCommitMessage(ctx context.Context, msg *comatproto.SyncSubscribeRepos
6161
if err != nil {
6262
return nil, fmt.Errorf("invalid repo path in ops list: %w", err)
6363
}
64-
val, err := repo.GetRecordCID(ctx, nsid, rkey)
64+
// don't use the returned bytes, but do actually read them out of store (not just CID)
65+
_, val, err := repo.GetRecordBytes(ctx, nsid, rkey)
6566
if err != nil {
6667
return nil, err
6768
}
6869
if *c != *val {
6970
return nil, fmt.Errorf("record op doesn't match MST tree value")
7071
}
71-
_, err = repo.GetRecordBytes(ctx, nsid, rkey)
72-
if err != nil {
73-
return nil, err
74-
}
7572
}
7673
}
7774

0 commit comments

Comments
 (0)