1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-11 02:13:41 +09:00

GO-2726 Fix long state constructing

This commit is contained in:
Mikhail Iudin 2024-01-22 10:45:30 +00:00
parent 0f622b2d40
commit 857eac5f98
No known key found for this signature in database
GPG key ID: FAAAA8BAABDFF1C0
5 changed files with 127 additions and 51 deletions

View file

@ -144,6 +144,7 @@ func (s *State) Merge(s2 *State) *State {
}
func (s *State) ApplyChange(changes ...*pb.ChangeContent) (err error) {
defer s.resetParentIdsCache()
for _, ch := range changes {
if err = s.applyChange(ch); err != nil {
return
@ -174,6 +175,7 @@ func (s *State) GetAndUnsetFileKeys() (keys []pb.ChangeFileKeys) {
// ApplyChangeIgnoreErr should be called with changes from the single pb.Change
func (s *State) ApplyChangeIgnoreErr(changes ...*pb.ChangeContent) {
defer s.resetParentIdsCache()
for _, ch := range changes {
if err := s.applyChange(ch); err != nil {
log.With("objectID", s.RootId()).Warnf("error while applying change %T: %v; ignore", ch.Value, err)
@ -389,15 +391,10 @@ func (s *State) changeBlockUpdate(update *pb.ChangeBlockUpdate) error {
}
func (s *State) changeBlockMove(move *pb.ChangeBlockMove) error {
ns := s.NewState()
for _, id := range move.Ids {
ns.Unlink(id)
s.Unlink(id)
}
if err := ns.InsertTo(move.TargetId, move.Position, move.Ids...); err != nil {
return err
}
_, _, err := ApplyStateFastOne(ns)
return err
return s.InsertTo(move.TargetId, move.Position, move.Ids...)
}
func (s *State) changeStoreKeySet(set *pb.ChangeStoreKeySet) error {

View file

@ -104,7 +104,7 @@ func (s *State) normalizeChildren(b simple.Block) {
m := b.Model()
for _, cid := range m.ChildrenIds {
if !s.Exists(cid) {
m.ChildrenIds = slice.RemoveMut(m.ChildrenIds, cid)
s.setChildrenIds(m, slice.RemoveMut(m.ChildrenIds, cid))
s.normalizeChildren(b)
return
}
@ -166,7 +166,7 @@ func (s *State) normalizeTree() (err error) {
if s.Pick(headerId) != nil && slice.FindPos(s.Pick(s.RootId()).Model().ChildrenIds, headerId) != 0 {
s.Unlink(headerId)
root := s.Get(s.RootId()).Model()
root.ChildrenIds = append([]string{headerId}, root.ChildrenIds...)
s.setChildrenIds(root, append([]string{headerId}, root.ChildrenIds...))
}
return nil
}
@ -229,9 +229,9 @@ func (s *State) wrapChildrenToDiv(id string) (nextId string) {
}
div := s.newDiv()
div.Model().ChildrenIds = parent.ChildrenIds
s.setChildrenIds(div.Model(), parent.ChildrenIds)
s.Add(div)
parent.ChildrenIds = []string{div.Model().Id}
s.setChildrenIds(parent, []string{div.Model().Id})
return parent.Id
}
@ -245,9 +245,8 @@ func (s *State) divBalance(d1, d2 *model.Block) (overflow bool) {
d1ChildrenIds := make([]string, div)
copy(d1ChildrenIds, d1.ChildrenIds[:div])
d2.ChildrenIds = d1.ChildrenIds[div:]
d1.ChildrenIds = d1ChildrenIds
s.setChildrenIds(d2, d1.ChildrenIds[div:])
s.setChildrenIds(d1, d1ChildrenIds)
return len(d2.ChildrenIds) > maxChildrenThreshold
}
@ -305,7 +304,7 @@ func (s *State) removeDuplicates() {
idx = idx - i
chIds = append(chIds[:idx], chIds[idx+1:]...)
}
b.Model().ChildrenIds = chIds
s.setChildrenIds(b.Model(), chIds)
}
handledBlocks[b.Model().Id] = struct{}{}
return true
@ -384,7 +383,7 @@ func CleanupLayouts(s *State) (removedCount int) {
}
}
}
b.Model().ChildrenIds = result
s.setChildrenIds(b.Model(), result)
return
}
cleanup(s.RootId())

View file

@ -55,19 +55,20 @@ func (s *State) InsertTo(targetId string, reqPos model.BlockPosition, ids ...str
switch reqPos {
case model.Block_Bottom:
pos = targetPos + 1
targetParentM.ChildrenIds = slice.Insert(targetParentM.ChildrenIds, pos, ids...)
s.insertChildrenIds(targetParentM, pos, ids...)
case model.Block_Top:
pos = targetPos
targetParentM.ChildrenIds = slice.Insert(targetParentM.ChildrenIds, pos, ids...)
s.insertChildrenIds(targetParentM, pos, ids...)
case model.Block_Left, model.Block_Right:
if err = s.moveFromSide(target, s.Get(targetParentM.Id), reqPos, ids...); err != nil {
return
}
case model.Block_Inner:
target.Model().ChildrenIds = append(target.Model().ChildrenIds, ids...)
s.prependChildrenIds(target.Model(), ids...)
case model.Block_Replace:
pos = targetPos + 1
if len(ids) > 0 && len(s.Get(ids[0]).Model().ChildrenIds) == 0 {
id0Block := s.Get(ids[0]).Model()
if len(ids) > 0 && len(id0Block.ChildrenIds) == 0 {
var idsIsChild bool
if targetChild := target.Model().ChildrenIds; len(targetChild) > 0 {
for _, id := range ids {
@ -78,13 +79,13 @@ func (s *State) InsertTo(targetId string, reqPos model.BlockPosition, ids ...str
}
}
if !idsIsChild {
s.Get(ids[0]).Model().ChildrenIds = target.Model().ChildrenIds
s.setChildrenIds(id0Block, target.Model().ChildrenIds)
}
}
targetParentM.ChildrenIds = slice.Insert(targetParentM.ChildrenIds, pos, ids...)
s.insertChildrenIds(targetParentM, pos, ids...)
s.Unlink(target.Model().Id)
case model.Block_InnerFirst:
target.Model().ChildrenIds = append(ids, target.Model().ChildrenIds...)
s.appendChildrenIds(target.Model(), ids...)
default:
return fmt.Errorf("unexpected position")
}
@ -160,16 +161,7 @@ func (s *State) moveFromSide(target, parent simple.Block, pos model.BlockPositio
}
target = s.Get(row.Model().ChildrenIds[0])
}
column := simple.New(&model.Block{
Id: "cd-" + opId,
ChildrenIds: ids,
Content: &model.BlockContentOfLayout{
Layout: &model.BlockContentLayout{
Style: model.BlockContentLayout_Column,
},
},
})
s.Add(column)
column := s.addNewColumn(opId, ids)
targetPos := slice.FindPos(row.Model().ChildrenIds, target.Model().Id)
if targetPos == -1 {
@ -180,12 +172,73 @@ func (s *State) moveFromSide(target, parent simple.Block, pos model.BlockPositio
if pos == model.Block_Right {
columnPos += 1
}
row.Model().ChildrenIds = slice.Insert(row.Model().ChildrenIds, columnPos, column.Model().Id)
s.insertChildrenIds(row.Model(), columnPos, column.Model().Id)
s.changesStructureIgnoreIds = append(s.changesStructureIgnoreIds, "cd-"+opId, "ct-"+opId, "r-"+opId, row.Model().Id)
return
}
func (s *State) wrapToRow(opId string, parent, b simple.Block) (row simple.Block, err error) {
column := s.addNewBlockAndWrapToColumn(opId, b)
row = s.addNewColumnToRow(opId, column)
pos := slice.FindPos(parent.Model().ChildrenIds, b.Model().Id)
if pos == -1 {
return nil, fmt.Errorf("creating row: can't find child[%s] in given parent[%s]", b.Model().Id, parent.Model().Id)
}
parent.Model().ChildrenIds[pos] = row.Model().Id
return
}
func (s *State) setChildrenIds(parent *model.Block, childrenIds []string) {
parent.ChildrenIds = childrenIds
if s.isParentIdsCacheEnabled {
cache := s.getParentIdsCache()
for _, childId := range childrenIds {
cache[childId] = parent.Id
}
}
}
func (s *State) prependChildrenIds(block *model.Block, ids ...string) {
s.setChildrenIds(block, append(block.ChildrenIds, ids...))
}
func (s *State) appendChildrenIds(block *model.Block, ids ...string) {
s.setChildrenIds(block, append(ids, block.ChildrenIds...))
}
func (s *State) insertChildrenIds(block *model.Block, pos int, ids ...string) {
s.setChildrenIds(block, slice.Insert(block.ChildrenIds, pos, ids...))
}
func (s *State) addNewColumn(opId string, ids []string) simple.Block {
column := simple.New(&model.Block{
Id: "cd-" + opId,
ChildrenIds: ids,
Content: &model.BlockContentOfLayout{
Layout: &model.BlockContentLayout{
Style: model.BlockContentLayout_Column,
},
},
})
s.Add(column)
return column
}
func (s *State) addNewColumnToRow(opId string, column simple.Block) simple.Block {
row := simple.New(&model.Block{
Id: "r-" + opId,
ChildrenIds: []string{column.Model().Id},
Content: &model.BlockContentOfLayout{
Layout: &model.BlockContentLayout{
Style: model.BlockContentLayout_Row,
},
},
})
s.Add(row)
return row
}
func (s *State) addNewBlockAndWrapToColumn(opId string, b simple.Block) simple.Block {
column := simple.New(&model.Block{
Id: "ct-" + opId,
ChildrenIds: []string{b.Model().Id},
@ -196,20 +249,5 @@ func (s *State) wrapToRow(opId string, parent, b simple.Block) (row simple.Block
},
})
s.Add(column)
row = simple.New(&model.Block{
Id: "r-" + opId,
ChildrenIds: []string{column.Model().Id},
Content: &model.BlockContentOfLayout{
Layout: &model.BlockContentLayout{
Style: model.BlockContentLayout_Row,
},
},
})
s.Add(row)
pos := slice.FindPos(parent.Model().ChildrenIds, b.Model().Id)
if pos == -1 {
return nil, fmt.Errorf("creating row: can't find child[%s] in given parent[%s]", b.Model().Id, parent.Model().Id)
}
parent.Model().ChildrenIds[pos] = row.Model().Id
return
return column
}

View file

@ -133,6 +133,8 @@ type State struct {
groupId string
noObjectType bool
originalCreatedTimestamp int64 // pass here from snapshots when importing objects
parentIdsCache map[string]string
isParentIdsCacheEnabled bool
}
func (s *State) MigrationVersion() uint32 {
@ -201,6 +203,7 @@ func (s *State) Add(b simple.Block) (ok bool) {
if s.Pick(id) == nil {
s.blocks[id] = b
s.blockInit(b)
s.setChildrenIds(b.Model(), b.Model().ChildrenIds)
return true
}
return false
@ -210,11 +213,21 @@ func (s *State) Set(b simple.Block) {
if !s.Exists(b.Model().Id) {
s.Add(b)
} else {
s.removeFromCache(s.Pick(b.Model().Id).Model().ChildrenIds...)
s.setChildrenIds(b.Model(), b.Model().ChildrenIds)
s.blocks[b.Model().Id] = b
s.blockInit(b)
}
}
func (s *State) removeFromCache(ids ...string) {
if s.isParentIdsCacheEnabled {
for _, id := range ids {
delete(s.parentIdsCache, id)
}
}
}
func (s *State) Get(id string) (b simple.Block) {
if b = s.blocks[id]; b != nil {
return
@ -269,6 +282,7 @@ func (s *State) Unlink(id string) (ok bool) {
if parent := s.GetParentOf(id); parent != nil {
parentM := parent.Model()
parentM.ChildrenIds = slice.RemoveMut(parentM.ChildrenIds, id)
s.removeFromCache(id)
return true
}
return
@ -308,6 +322,13 @@ func (s *State) HasParent(id, parentId string) bool {
}
func (s *State) PickParentOf(id string) (res simple.Block) {
if s.isParentIdsCacheEnabled {
if parentId, ok := s.getParentIdsCache()[id]; ok {
return s.Pick(parentId)
}
return
}
s.Iterate(func(b simple.Block) bool {
if slice.FindPos(b.Model().ChildrenIds, id) != -1 {
res = b
@ -318,6 +339,24 @@ func (s *State) PickParentOf(id string) (res simple.Block) {
return
}
func (s *State) resetParentIdsCache() {
s.parentIdsCache = nil
s.isParentIdsCacheEnabled = false
}
func (s *State) getParentIdsCache() map[string]string {
if s.parentIdsCache == nil {
s.parentIdsCache = make(map[string]string)
s.Iterate(func(block simple.Block) bool {
for _, id := range block.Model().ChildrenIds {
s.parentIdsCache[id] = block.Model().Id
}
return true
})
}
return s.parentIdsCache
}
func (s *State) IsChild(parentId, childId string) bool {
for {
parent := s.PickParentOf(childId)
@ -422,6 +461,7 @@ func ApplyStateFastOne(s *State) (msgs []simple.EventMessage, action undo.Action
}
func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage, action undo.Action, err error) {
defer s.resetParentIdsCache()
if s.parent != nil && (s.parent.parent != nil || fast) {
s.intermediateApply()
if one {
@ -675,7 +715,6 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
}
msgs = s.processTrailingDuplicatedEvents(msgs)
log.Debugf("middle: state apply: %d affected; %d for remove; %d copied; %d changes; for a %v", len(affectedIds), len(toRemove), len(s.blocks), len(s.changes), time.Since(st))
return
}

View file

@ -64,6 +64,9 @@ func New(eventEndpoint string, key string, isCompressed bool) Service {
}
func (c *Client) SendEvents(amplEvents []Event, info AppInfoProvider) error {
if len(amplEvents) == 0 {
return nil
}
arena := c.arenaPool.Get()
appVersion := arena.NewString(info.GetAppVersion())
deviceId := arena.NewString(info.GetDeviceId())