Change first thread entry handling

This commit is contained in:
mcrakhman 2022-07-12 10:27:02 +02:00 committed by Mikhail Iudin
parent af653405d0
commit 97829406fe
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
11 changed files with 72 additions and 68 deletions

View File

@ -10,6 +10,12 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/threadbuilder" "github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/threadbuilder"
) )
type mockListener struct{}
func (m *mockListener) Update(tree ACLTree) {}
func (m *mockListener) Rebuild(tree ACLTree) {}
func TestACLTree_UserJoinBuild(t *testing.T) { func TestACLTree_UserJoinBuild(t *testing.T) {
thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml") thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml")
if err != nil { if err != nil {
@ -21,7 +27,8 @@ func TestACLTree_UserJoinBuild(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
tree, err := BuildACLTree(thr, accountData) listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener)
if err != nil { if err != nil {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }
@ -55,7 +62,8 @@ func TestACLTree_UserRemoveBuild(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
tree, err := BuildACLTree(thr, accountData) listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener)
if err != nil { if err != nil {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }
@ -85,7 +93,8 @@ func TestACLTree_UserRemoveBeforeBuild(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
tree, err := BuildACLTree(thr, accountData) listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener)
if err != nil { if err != nil {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }
@ -116,7 +125,8 @@ func TestACLTree_InvalidSnapshotBuild(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
tree, err := BuildACLTree(thr, accountData) listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener)
if err != nil { if err != nil {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }
@ -146,7 +156,8 @@ func TestACLTree_ValidSnapshotBuild(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
tree, err := BuildACLTree(thr, accountData) listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener)
if err != nil { if err != nil {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }

View File

@ -6,7 +6,6 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/thread" "github.com/anytypeio/go-anytype-infrastructure-experiments/thread"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
gothread "github.com/textileio/go-threads/core/thread"
) )
type aclTreeBuilder struct { type aclTreeBuilder struct {
@ -56,11 +55,7 @@ func (tb *aclTreeBuilder) Build() (*Tree, error) {
} }
func (tb *aclTreeBuilder) buildTreeFromStart(heads []string) (err error) { func (tb *aclTreeBuilder) buildTreeFromStart(heads []string) (err error) {
changes, possibleRoots, err := tb.dfsFromStart(heads) changes, root, err := tb.dfsFromStart(heads)
if len(possibleRoots) == 0 {
return fmt.Errorf("cannot have Tree without root")
}
root, err := tb.getRoot(possibleRoots)
if err != nil { if err != nil {
return err return err
} }
@ -70,7 +65,8 @@ func (tb *aclTreeBuilder) buildTreeFromStart(heads []string) (err error) {
return return
} }
func (tb *aclTreeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleRoots []*Change, err error) { func (tb *aclTreeBuilder) dfsFromStart(heads []string) (buf []*Change, root *Change, err error) {
var possibleRoots []*Change
stack := make([]string, len(heads), len(heads)*2) stack := make([]string, len(heads), len(heads)*2)
copy(stack, heads) copy(stack, heads)
@ -98,32 +94,14 @@ func (tb *aclTreeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleR
possibleRoots = append(possibleRoots, ch) possibleRoots = append(possibleRoots, ch)
} }
} }
return buf, possibleRoots, nil header := tb.thread.Header()
}
func (tb *aclTreeBuilder) getRoot(possibleRoots []*Change) (*Change, error) {
threadId, err := gothread.Decode(tb.thread.ID())
if err != nil {
return nil, err
}
for _, r := range possibleRoots { for _, r := range possibleRoots {
id := r.Content.Identity if r.Id == header.FirstChangeId {
sk, err := tb.signingPubKeyDecoder.DecodeFromString(id) return buf, r, nil
if err != nil {
continue
}
res, err := thread.VerifyACLThreadID(sk, threadId)
if err != nil {
continue
}
if res {
return r, nil
} }
} }
return nil, fmt.Errorf("could not find any root")
return nil, nil, fmt.Errorf("could not find root change")
} }
func (tb *aclTreeBuilder) getACLHeads(heads []string) (aclTreeHeads []string, err error) { func (tb *aclTreeBuilder) getACLHeads(heads []string) (aclTreeHeads []string, err error) {

View File

@ -9,7 +9,6 @@ import (
//"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/lib/logging" //"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/lib/logging"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
gothread "github.com/textileio/go-threads/core/thread"
) )
var ( var (
@ -71,11 +70,7 @@ func (tb *treeBuilder) Build(fromStart bool) (*Tree, error) {
} }
func (tb *treeBuilder) buildTreeFromStart(heads []string) (err error) { func (tb *treeBuilder) buildTreeFromStart(heads []string) (err error) {
changes, possibleRoots, err := tb.dfsFromStart(heads) changes, root, err := tb.dfsFromStart(heads)
if len(possibleRoots) == 0 {
return fmt.Errorf("cannot have Tree without root")
}
root, err := tb.getRoot(possibleRoots)
if err != nil { if err != nil {
return err return err
} }
@ -85,7 +80,8 @@ func (tb *treeBuilder) buildTreeFromStart(heads []string) (err error) {
return return
} }
func (tb *treeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleRoots []*Change, err error) { func (tb *treeBuilder) dfsFromStart(heads []string) (buf []*Change, root *Change, err error) {
var possibleRoots []*Change
stack := make([]string, len(heads), len(heads)*2) stack := make([]string, len(heads), len(heads)*2)
copy(stack, heads) copy(stack, heads)
@ -113,7 +109,14 @@ func (tb *treeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleRoot
possibleRoots = append(possibleRoots, ch) possibleRoots = append(possibleRoots, ch)
} }
} }
return buf, possibleRoots, nil header := tb.thread.Header()
for _, r := range possibleRoots {
if r.Id == header.FirstChangeId {
return buf, r, nil
}
}
return nil, nil, fmt.Errorf("could not find root change")
} }
func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error) { func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error) {
@ -287,28 +290,3 @@ func (tb *treeBuilder) findCommonForTwoSnapshots(s1, s2 string) (s string, err e
return s2, nil return s2, nil
} }
func (tb *treeBuilder) getRoot(possibleRoots []*Change) (*Change, error) {
threadId, err := gothread.Decode(tb.thread.ID())
if err != nil {
return nil, err
}
for _, r := range possibleRoots {
id := r.Content.Identity
sk, err := tb.signingPubKeyDecoder.DecodeFromString(id)
if err != nil {
continue
}
res, err := thread.VerifyACLThreadID(sk, threadId)
if err != nil {
continue
}
if res {
return r, nil
}
}
return nil, fmt.Errorf("could not find any root")
}

View File

@ -117,6 +117,9 @@ graph:
baseSnapshot: A.1.2 baseSnapshot: A.1.2
aclHeads: [A.1.2] aclHeads: [A.1.2]
treeHeads: [A.1.2] treeHeads: [A.1.2]
header:
firstChangeId: A.1.1
isWorkspace: false
orphans: orphans:
- A.1.3 - A.1.3
- B.1.2 - B.1.2

View File

@ -13,6 +13,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb" "github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb"
testpb "github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/testchanges/pb" testpb "github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/testchanges/pb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/thread" "github.com/anytypeio/go-anytype-infrastructure-experiments/thread"
threadpb "github.com/anytypeio/go-anytype-infrastructure-experiments/thread/pb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
) )
@ -34,6 +35,7 @@ type ThreadBuilder struct {
heads []string heads []string
orphans []string orphans []string
keychain *Keychain keychain *Keychain
header *threadpb.ThreadHeader
} }
func NewThreadBuilder(keychain *Keychain) *ThreadBuilder { func NewThreadBuilder(keychain *Keychain) *ThreadBuilder {
@ -167,6 +169,10 @@ func (t *ThreadBuilder) GetUpdatedChanges() []*thread.RawChange {
return res return res
} }
func (t *ThreadBuilder) Header() *threadpb.ThreadHeader {
return t.header
}
func (t *ThreadBuilder) getChange(changeId string, m map[string]*threadChange) *thread.RawChange { func (t *ThreadBuilder) getChange(changeId string, m map[string]*threadChange) *thread.RawChange {
rec := m[changeId] rec := m[changeId]
@ -510,3 +516,10 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) {
func (t *ThreadBuilder) parseOrphans(thread *YMLThread) { func (t *ThreadBuilder) parseOrphans(thread *YMLThread) {
t.orphans = thread.Orphans t.orphans = thread.Orphans
} }
func (t *ThreadBuilder) parseHeader(thread *YMLThread) {
t.header = &threadpb.ThreadHeader{
FirstChangeId: thread.Header.FirstChangeId,
IsWorkspace: thread.Header.IsWorkspace,
}
}

View File

@ -99,6 +99,9 @@ graph:
baseSnapshot: A.1.1 baseSnapshot: A.1.1
aclHeads: [B.1.1] aclHeads: [B.1.1]
treeHeads: [B.1.1] treeHeads: [B.1.1]
header:
firstChangeId: A.1.1
isWorkspace: false
orphans: orphans:
- "A.1.3" - "A.1.3"
updatedChanges: updatedChanges:

View File

@ -101,6 +101,9 @@ graph:
baseSnapshot: A.1.1 baseSnapshot: A.1.1
aclHeads: [B.1.1] aclHeads: [B.1.1]
treeHeads: [B.1.1] treeHeads: [B.1.1]
header:
firstChangeId: A.1.1
isWorkspace: false
orphans: orphans:
- "A.1.3" - "A.1.3"
updatedChanges: updatedChanges:

View File

@ -104,3 +104,6 @@ graph:
orphans: orphans:
- "A.1.3" - "A.1.3"
- "B.1.2" - "B.1.2"
header:
firstChangeId: A.1.1
isWorkspace: false

View File

@ -104,3 +104,6 @@ graph:
orphans: orphans:
- "A.1.4" - "A.1.4"
- "B.1.2" - "B.1.2"
header:
firstChangeId: A.1.1
isWorkspace: false

View File

@ -127,4 +127,7 @@ graph:
orphans: orphans:
- "A.1.3" - "A.1.3"
- "B.1.2" - "B.1.2"
header:
firstChangeId: A.1.1
isWorkspace: false

View File

@ -90,6 +90,11 @@ type Change struct {
ReadKey string `yaml:"readKey"` ReadKey string `yaml:"readKey"`
} }
type Header struct {
FirstChangeId string `yaml:"firstChangeId"`
IsWorkspace bool `yaml:"isWorkspace"`
}
type YMLThread struct { type YMLThread struct {
Description *ThreadDescription `yaml:"thread"` Description *ThreadDescription `yaml:"thread"`
Changes []*Change `yaml:"changes"` Changes []*Change `yaml:"changes"`
@ -102,4 +107,5 @@ type YMLThread struct {
Heads []string `yaml:"heads"` Heads []string `yaml:"heads"`
Orphans []string `yaml:"orphans"` Orphans []string `yaml:"orphans"`
Header *Header `yaml:"header"`
} }