From b2eeff48d3bc6d5c29f7372e752d393d7be14c86 Mon Sep 17 00:00:00 2001
From: Jinghao Lu <archever@163.com>
Date: Fri, 8 Mar 2024 10:52:33 +0800
Subject: [PATCH] fix(engine): make actions in stable order (#23)

* fix(engine): make actions in stable order

* fix(engine): make actions in stable order

* fix(snapshot): fix simpleSet slice order

---------

Co-authored-by: lujinghao <lujinghao@bytedance.com>
---
 engine.go   | 10 ++++++++--
 snapshot.go | 13 ++++++++-----
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/engine.go b/engine.go
index 21d454b..a4abbfa 100644
--- a/engine.go
+++ b/engine.go
@@ -909,6 +909,7 @@ func (e *Stage) putNewID(changes []*entityChanged) error {
 // 相同操作,相同类型的PO,合并到一个 Action
 func (e *Stage) makeActions(changes []*entityChanged) ([]*Action, error) {
 	typeActions := make(map[OpType]map[reflect.Type]*Action, 3)
+	poTypes := []reflect.Type{}
 	for _, item := range changes {
 		for _, entity := range item.children {
 			op := changeType2OP(item.changeType)
@@ -921,6 +922,7 @@ func (e *Stage) makeActions(changes []*entityChanged) ([]*Action, error) {
 				return nil, err
 			}
 			poType := reflect.TypeOf(po)
+			poTypes = append(poTypes, poType)
 			if _, in := typeActions[op]; !in {
 				typeActions[op] = map[reflect.Type]*Action{}
 			}
@@ -940,8 +942,12 @@ func (e *Stage) makeActions(changes []*entityChanged) ([]*Action, error) {
 	}
 	actions := make([]*Action, 0)
 	for _, t := range []OpType{OpInsert, OpUpdate, OpDelete} {
-		for _, a := range typeActions[t] {
-			actions = append(actions, a)
+		for _, at := range poTypes {
+			if _, in := typeActions[t][at]; !in {
+				continue
+			}
+			actions = append(actions, typeActions[t][at])
+			delete(typeActions[t], at)
 		}
 	}
 	return actions, nil
diff --git a/snapshot.go b/snapshot.go
index 5e13dc4..8d45c6a 100644
--- a/snapshot.go
+++ b/snapshot.go
@@ -60,12 +60,12 @@ func (c *entityChanged) Remove(entity IEntity) bool {
 	return true
 }
 
-type simpleSet map[IEntity]bool
+type simpleSet map[IEntity]int
 
 func (s simpleSet) Diff(s2 simpleSet) simpleSet {
 	res := simpleSet{}
 	for e := range s {
-		if !s2[e] {
+		if _, in := s2[e]; !in {
 			res[e] = s[e]
 		}
 	}
@@ -86,7 +86,7 @@ func (s simpleSet) Inter(s2 simpleSet) simpleSet {
 	res := simpleSet{}
 	for e := range s {
 		if _, in := s2[e]; in {
-			res[e] = true
+			res[e] = s[e]
 		}
 	}
 
@@ -100,6 +100,9 @@ func (s simpleSet) ToSlice() []IEntity {
 		res[i] = e
 		i++
 	}
+	sort.SliceStable(res, func(i, j int) bool {
+		return s[res[i]] < s[res[j]]
+	})
 	return res
 }
 
@@ -109,8 +112,8 @@ func (s simpleSet) Empty() bool {
 
 func makeEntitySet(nodes []IEntity) simpleSet {
 	s := simpleSet{}
-	for _, n := range nodes {
-		s[n] = true
+	for i, n := range nodes {
+		s[n] = i
 	}
 	return s
 }
-- 
GitLab