mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-09 17:45:03 +09:00
Use headstorage in objecttree tests
This commit is contained in:
parent
5492a43920
commit
7600889730
5 changed files with 89 additions and 63 deletions
|
@ -38,6 +38,7 @@ type EntryIterator func(entry HeadsEntry) (bool, error)
|
|||
type HeadStorage interface {
|
||||
IterateEntries(ctx context.Context, iter EntryIterator) error
|
||||
GetEntry(ctx context.Context, id string) (HeadsEntry, error)
|
||||
DeleteEntryTx(txCtx context.Context, id string) error
|
||||
UpdateEntryTx(txCtx context.Context, update HeadsUpdate) error
|
||||
}
|
||||
|
||||
|
@ -105,6 +106,10 @@ func (h *headStorage) UpdateEntryTx(ctx context.Context, update HeadsUpdate) (er
|
|||
return
|
||||
}
|
||||
|
||||
func (h *headStorage) DeleteEntryTx(ctx context.Context, id string) error {
|
||||
return h.headsColl.DeleteId(ctx, id)
|
||||
}
|
||||
|
||||
func (h *headStorage) entryFromDoc(doc anystore.Doc) HeadsEntry {
|
||||
return HeadsEntry{
|
||||
Id: doc.Value().GetString(idKey),
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/headsync/headstorage"
|
||||
"github.com/anyproto/any-sync/commonspace/object/accountdata"
|
||||
"github.com/anyproto/any-sync/commonspace/object/acl/list"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
|
||||
|
@ -308,7 +309,9 @@ func TestObjectTree(t *testing.T) {
|
|||
IsEncrypted: true,
|
||||
}, aAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
aStore, err := CreateStorage(ctx, root, store)
|
||||
aHeadsStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
aStore, err := CreateStorage(ctx, root, aHeadsStorage, store)
|
||||
require.NoError(t, err)
|
||||
aTree, err := BuildKeyFilterableObjectTree(aStore, aAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
|
@ -359,7 +362,9 @@ func TestObjectTree(t *testing.T) {
|
|||
IsEncrypted: true,
|
||||
}, aAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
aStore, err := CreateStorage(ctx, root, storeA)
|
||||
aHeadsStorage, err := headstorage.New(ctx, storeA)
|
||||
require.NoError(t, err)
|
||||
aStore, err := CreateStorage(ctx, root, aHeadsStorage, storeA)
|
||||
require.NoError(t, err)
|
||||
aTree, err := BuildKeyFilterableObjectTree(aStore, aAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
|
@ -372,7 +377,9 @@ func TestObjectTree(t *testing.T) {
|
|||
})
|
||||
require.NoError(t, err)
|
||||
storeB := copyStore(ctx, t, storeA.(testStore), "b")
|
||||
bStore, err := NewStorage(ctx, root.Id, storeB)
|
||||
bHeadsStorage, err := headstorage.New(ctx, storeB)
|
||||
require.NoError(t, err)
|
||||
bStore, err := NewStorage(ctx, root.Id, bHeadsStorage, storeB)
|
||||
require.NoError(t, err)
|
||||
bTree, err := BuildKeyFilterableObjectTree(bStore, bAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
|
@ -447,7 +454,9 @@ func TestObjectTree(t *testing.T) {
|
|||
IsEncrypted: true,
|
||||
}, aAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
aStore, err := CreateStorage(ctx, root, storeA)
|
||||
aHeadsStorage, err := headstorage.New(ctx, storeA)
|
||||
require.NoError(t, err)
|
||||
aStore, err := CreateStorage(ctx, root, aHeadsStorage, storeA)
|
||||
require.NoError(t, err)
|
||||
aTree, err := BuildKeyFilterableObjectTree(aStore, aAccount.Acl)
|
||||
require.NoError(t, err)
|
||||
|
@ -460,7 +469,9 @@ func TestObjectTree(t *testing.T) {
|
|||
})
|
||||
require.NoError(t, err)
|
||||
storeB := copyStore(ctx, t, storeA.(testStore), "b")
|
||||
bStore, err := NewStorage(ctx, root.Id, storeB)
|
||||
bHeadsStorage, err := headstorage.New(ctx, storeB)
|
||||
require.NoError(t, err)
|
||||
bStore, err := NewStorage(ctx, root.Id, bHeadsStorage, storeB)
|
||||
require.NoError(t, err)
|
||||
// copying old version of storage
|
||||
prevAclRecs, err := bAccount.Acl.RecordsAfter(ctx, "")
|
||||
|
@ -512,7 +523,10 @@ func TestObjectTree(t *testing.T) {
|
|||
}, aclList)
|
||||
require.NoError(t, err)
|
||||
store := createStore(ctx, t)
|
||||
storage, _ := CreateStorage(ctx, root, store)
|
||||
headsStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
storage, err := CreateStorage(ctx, root, headsStorage, store)
|
||||
require.NoError(t, err)
|
||||
oTree, err := BuildObjectTree(storage, aclList)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -582,7 +596,10 @@ func TestObjectTree(t *testing.T) {
|
|||
}, aclList)
|
||||
require.NoError(t, err)
|
||||
store := createStore(ctx, t)
|
||||
storage, _ := CreateStorage(ctx, root, store)
|
||||
headsStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
storage, err := CreateStorage(ctx, root, headsStorage, store)
|
||||
require.NoError(t, err)
|
||||
oTree, err := BuildObjectTree(storage, aclList)
|
||||
require.NoError(t, err)
|
||||
emptyDataTreeDeps = nonVerifiableTreeDeps
|
||||
|
@ -604,7 +621,10 @@ func TestObjectTree(t *testing.T) {
|
|||
}, aclList)
|
||||
require.NoError(t, err)
|
||||
store := createStore(ctx, t)
|
||||
storage, _ := CreateStorage(ctx, root, store)
|
||||
headsStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
storage, err := CreateStorage(ctx, root, headsStorage, store)
|
||||
require.NoError(t, err)
|
||||
oTree, err := BuildObjectTree(storage, aclList)
|
||||
require.NoError(t, err)
|
||||
validateStore := createStore(ctx, t)
|
||||
|
@ -638,7 +658,10 @@ func TestObjectTree(t *testing.T) {
|
|||
}, aclList)
|
||||
require.NoError(t, err)
|
||||
store := createStore(ctx, t)
|
||||
storage, _ := CreateStorage(ctx, root, store)
|
||||
headsStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
storage, err := CreateStorage(ctx, root, headsStorage, store)
|
||||
require.NoError(t, err)
|
||||
oTree, err := BuildObjectTree(storage, aclList)
|
||||
require.NoError(t, err)
|
||||
_, err = oTree.AddContent(ctx, SignableChangeContent{
|
||||
|
@ -685,7 +708,10 @@ func TestObjectTree(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
emptyDataTreeDeps = nonVerifiableTreeDeps
|
||||
store := createStore(ctx, t)
|
||||
storage, _ := CreateStorage(ctx, root, store)
|
||||
headsStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
storage, err := CreateStorage(ctx, root, headsStorage, store)
|
||||
require.NoError(t, err)
|
||||
oTree, err := BuildObjectTree(storage, aclList)
|
||||
require.NoError(t, err)
|
||||
_, err = oTree.AddContent(ctx, SignableChangeContent{
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
anystore "github.com/anyproto/any-store"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/headsync/headstorage"
|
||||
"github.com/anyproto/any-sync/commonspace/object/acl/list"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
"github.com/anyproto/any-sync/util/slice"
|
||||
|
@ -20,7 +21,12 @@ type tempTreeStorageCreator struct {
|
|||
}
|
||||
|
||||
func (t *tempTreeStorageCreator) CreateTreeStorage(payload treestorage.TreeStorageCreatePayload) (Storage, error) {
|
||||
return CreateStorage(context.Background(), payload.RootRawChange, t.store)
|
||||
ctx := context.Background()
|
||||
headStorage, err := headstorage.New(ctx, t.store)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return CreateStorage(ctx, payload.RootRawChange, headStorage, t.store)
|
||||
}
|
||||
|
||||
type ValidatorFunc func(payload treestorage.TreeStorageCreatePayload, storageCreator TreeStorageCreator, aclList list.AclList) (ret ObjectTree, err error)
|
||||
|
|
|
@ -9,22 +9,20 @@ import (
|
|||
"github.com/anyproto/any-store/anyenc"
|
||||
"github.com/anyproto/any-store/query"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/headsync/headstorage"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
|
||||
"github.com/anyproto/any-sync/util/crypto"
|
||||
"github.com/anyproto/any-sync/util/storeutil"
|
||||
)
|
||||
|
||||
const (
|
||||
orderKey = "o"
|
||||
headsKey = "h"
|
||||
commonSnapshotKey = "s"
|
||||
idKey = "id"
|
||||
rawChangeKey = "r"
|
||||
snapshotCounterKey = "sc"
|
||||
changeSizeKey = "sz"
|
||||
snapshotIdKey = "i"
|
||||
prevIdsKey = "p"
|
||||
headsCollectionName = "heads"
|
||||
orderKey = "o"
|
||||
idKey = "id"
|
||||
rawChangeKey = "r"
|
||||
snapshotCounterKey = "sc"
|
||||
changeSizeKey = "sz"
|
||||
snapshotIdKey = "i"
|
||||
prevIdsKey = "p"
|
||||
)
|
||||
|
||||
type StorageChange struct {
|
||||
|
@ -62,17 +60,18 @@ type Storage interface {
|
|||
type storage struct {
|
||||
id string
|
||||
store anystore.DB
|
||||
headsColl anystore.Collection
|
||||
headStorage headstorage.HeadStorage
|
||||
changesColl anystore.Collection
|
||||
arena *anyenc.Arena
|
||||
}
|
||||
|
||||
var storageChangeBuilder = NewChangeBuilder
|
||||
|
||||
func CreateStorage(ctx context.Context, root *treechangeproto.RawTreeChangeWithId, store anystore.DB) (Storage, error) {
|
||||
func CreateStorage(ctx context.Context, root *treechangeproto.RawTreeChangeWithId, headStorage headstorage.HeadStorage, store anystore.DB) (Storage, error) {
|
||||
st := &storage{
|
||||
id: root.Id,
|
||||
store: store,
|
||||
id: root.Id,
|
||||
store: store,
|
||||
headStorage: headStorage,
|
||||
}
|
||||
builder := storageChangeBuilder(crypto.NewKeyStorage(), root)
|
||||
_, err := builder.Unmarshall(root, true)
|
||||
|
@ -88,11 +87,6 @@ func CreateStorage(ctx context.Context, root *treechangeproto.RawTreeChangeWithI
|
|||
OrderId: firstOrder,
|
||||
ChangeSize: len(root.RawChange),
|
||||
}
|
||||
headsColl, err := store.Collection(ctx, headsCollectionName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st.headsColl = headsColl
|
||||
changesColl, err := store.Collection(ctx, root.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -119,11 +113,11 @@ func CreateStorage(ctx context.Context, root *treechangeproto.RawTreeChangeWithI
|
|||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
headsDoc := st.arena.NewObject()
|
||||
headsDoc.Set(headsKey, storeutil.NewStringArrayValue([]string{root.Id}, st.arena))
|
||||
headsDoc.Set(commonSnapshotKey, st.arena.NewString(root.Id))
|
||||
headsDoc.Set(idKey, st.arena.NewString(root.Id))
|
||||
err = st.headsColl.Insert(tx.Context(), headsDoc)
|
||||
err = st.headStorage.UpdateEntryTx(tx.Context(), headstorage.HeadsUpdate{
|
||||
Id: root.Id,
|
||||
Heads: []string{root.Id},
|
||||
CommonSnapshot: &root.Id,
|
||||
})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
|
@ -131,17 +125,12 @@ func CreateStorage(ctx context.Context, root *treechangeproto.RawTreeChangeWithI
|
|||
return st, tx.Commit()
|
||||
}
|
||||
|
||||
func NewStorage(ctx context.Context, id string, store anystore.DB) (Storage, error) {
|
||||
// TODO: use spacestorage to set heads
|
||||
func NewStorage(ctx context.Context, id string, headStorage headstorage.HeadStorage, store anystore.DB) (Storage, error) {
|
||||
st := &storage{
|
||||
id: id,
|
||||
store: store,
|
||||
id: id,
|
||||
store: store,
|
||||
headStorage: headStorage,
|
||||
}
|
||||
headsColl, err := store.Collection(ctx, headsCollectionName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st.headsColl = headsColl
|
||||
changesColl, err := store.Collection(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -161,20 +150,15 @@ func NewStorage(ctx context.Context, id string, store anystore.DB) (Storage, err
|
|||
}
|
||||
|
||||
func (s *storage) Heads(ctx context.Context) (res []string, err error) {
|
||||
doc, err := s.headsColl.FindId(ctx, s.id)
|
||||
headsEntry, err := s.headStorage.GetEntry(ctx, s.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
res = make([]string, 0, len(res))
|
||||
heads := doc.Value().GetArray(headsKey)
|
||||
for _, h := range heads {
|
||||
res = append(res, h.GetString())
|
||||
}
|
||||
return
|
||||
return headsEntry.Heads, nil
|
||||
}
|
||||
|
||||
func (s *storage) Has(ctx context.Context, id string) (bool, error) {
|
||||
_, err := s.headsColl.FindId(ctx, s.id)
|
||||
_, err := s.changesColl.FindId(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, anystore.ErrDocNotFound) {
|
||||
return false, nil
|
||||
|
@ -226,12 +210,12 @@ func (s *storage) AddAll(ctx context.Context, changes []StorageChange, heads []s
|
|||
tx.Rollback()
|
||||
return nil
|
||||
}
|
||||
mod := query.ModifyFunc(func(a *anyenc.Arena, v *anyenc.Value) (result *anyenc.Value, modified bool, err error) {
|
||||
v.Set(headsKey, storeutil.NewStringArrayValue(heads, a))
|
||||
v.Set(commonSnapshotKey, a.NewString(commonSnapshot))
|
||||
return v, true, nil
|
||||
})
|
||||
_, err = s.headsColl.UpsertId(tx.Context(), s.id, mod)
|
||||
update := headstorage.HeadsUpdate{
|
||||
Id: s.id,
|
||||
Heads: heads,
|
||||
CommonSnapshot: &commonSnapshot,
|
||||
}
|
||||
err = s.headStorage.UpdateEntryTx(tx.Context(), update)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return nil
|
||||
|
@ -249,7 +233,7 @@ func (s *storage) Delete(ctx context.Context) error {
|
|||
tx.Rollback()
|
||||
return fmt.Errorf("failed to delete changes collection: %w", err)
|
||||
}
|
||||
err = s.headsColl.DeleteId(tx.Context(), s.id)
|
||||
err = s.headStorage.DeleteEntryTx(tx.Context(), s.id)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("failed to remove document from heads collection: %w", err)
|
||||
|
@ -271,11 +255,11 @@ func (s *storage) Root(ctx context.Context) (StorageChange, error) {
|
|||
|
||||
func (s *storage) CommonSnapshot(ctx context.Context) (string, error) {
|
||||
// TODO: cache this in memory if needed
|
||||
doc, err := s.headsColl.FindId(ctx, s.id)
|
||||
entry, err := s.headStorage.GetEntry(ctx, s.id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return doc.Value().GetString(commonSnapshotKey), nil
|
||||
return entry.CommonSnapshot, nil
|
||||
}
|
||||
|
||||
func (s *storage) Get(ctx context.Context, id string) (StorageChange, error) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
libcrypto "github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/headsync/headstorage"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
|
||||
"github.com/anyproto/any-sync/util/crypto"
|
||||
)
|
||||
|
@ -164,7 +165,11 @@ func (c *MockChangeCreator) CreateNewTreeStorage(t *testing.T, treeId, aclHeadId
|
|||
ChangeBuilder: NewChangeBuilder(newMockKeyStorage(), rootChange),
|
||||
}
|
||||
}
|
||||
storage, err := CreateStorage(context.Background(), root, c.storeCreator())
|
||||
ctx := context.Background()
|
||||
store := c.storeCreator()
|
||||
headStorage, err := headstorage.New(ctx, store)
|
||||
require.NoError(t, err)
|
||||
storage, err := CreateStorage(ctx, root, headStorage, store)
|
||||
require.NoError(t, err)
|
||||
return &testStorage{
|
||||
Storage: storage,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue