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:
parent
0f622b2d40
commit
857eac5f98
5 changed files with 127 additions and 51 deletions
|
@ -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 {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue