1515 */
1616package io .serverlessworkflow .impl .persistence .hashing ;
1717
18+ import com .github .f4b6a3 .ulid .UlidFactory ;
1819import java .util .ArrayList ;
1920import java .util .Arrays ;
2021import java .util .HashMap ;
2122import java .util .List ;
2223import java .util .Map ;
24+ import java .util .Map .Entry ;
2325import java .util .Optional ;
2426import java .util .concurrent .ConcurrentHashMap ;
2527import java .util .function .Consumer ;
2830
2931public class HashMappingCoordinator {
3032
33+ private static final UlidFactory idFactory = UlidFactory .newMonotonicInstance ();
34+
3135 public static final HashMappingCoordinator build (
32- Function <String , Map <String , List < byte []>>> retriever ,
36+ Function <String , Map <String , Map < String , byte []>>> retriever ,
3337 Consumer <Map <String , List <HashMappingInfo >>> writer ) {
3438 return new HashMappingCoordinator (retriever , writer );
3539 }
@@ -57,19 +61,19 @@ public boolean isTransient() {
5761 }
5862 }
5963
60- private record PendingWrite (String key , int index , BytesWithFlag bytes ) {}
64+ private record PendingWrite (String key , String index , BytesWithFlag bytes ) {}
6165
62- private final Function <String , Map <String , List < byte []>>> retriever ;
66+ private final Function <String , Map <String , Map < String , byte []>>> retriever ;
6367 private final Consumer <Map <String , List <HashMappingInfo >>> writer ;
6468
6569 private HashMappingCoordinator (
66- Function <String , Map <String , List < byte []>>> retriever ,
70+ Function <String , Map <String , Map < String , byte []>>> retriever ,
6771 Consumer <Map <String , List <HashMappingInfo >>> writer ) {
6872 this .retriever = retriever ;
6973 this .writer = writer ;
7074 }
7175
72- private static Map <String , Map <String , List < BytesWithFlag >>> mappingInfo =
76+ private static Map <String , Map <String , Map < String , BytesWithFlag >>> mappingInfo =
7377 new ConcurrentHashMap <>();
7478
7579 private Map <String , List <PendingWrite >> pending = new HashMap <>();
@@ -78,52 +82,45 @@ private HashMappingInfo from(PendingWrite pending) {
7882 return new HashMappingInfo (pending .key , pending .index , pending .bytes .bytes );
7983 }
8084
81- public int calculateIndex (String instanceId , HashItem item , byte [] bytes ) {
82- Map <String , List < BytesWithFlag >> instanceMap = getInstanceMap (instanceId );
85+ public String calculateIndex (String instanceId , HashItem item , byte [] bytes ) {
86+ Map <String , Map < String , BytesWithFlag >> instanceMap = getInstanceMap (instanceId );
8387 String key = item .key ();
8488 synchronized (instanceMap ) {
85- List <BytesWithFlag > list = instanceMap .computeIfAbsent (key , __ -> new ArrayList <>());
86- if (list .isEmpty ()) {
87- int index = 0 ;
88- BytesWithFlag bytesWithFlag = new BytesWithFlag (bytes );
89- list .add (bytesWithFlag );
90- addWrite (instanceId , key , index , bytesWithFlag );
91- return index ;
92- }
93- for (int i = 0 ; i < list .size (); i ++) {
94- BytesWithFlag bytesWithFlag = list .get (i );
95- if (Arrays .equals (bytesWithFlag .bytes , bytes )) {
96- if (bytesWithFlag .isTransient ()) {
97- addWrite (instanceId , key , i , bytesWithFlag );
89+ Map <String , BytesWithFlag > duplicateMap =
90+ instanceMap .computeIfAbsent (key , __ -> new HashMap <>());
91+
92+ for (Entry <String , BytesWithFlag > entry : duplicateMap .entrySet ()) {
93+ if (Arrays .equals (entry .getValue ().bytes , bytes )) {
94+ if (entry .getValue ().isTransient ()) {
95+ addWrite (instanceId , key , entry .getKey (), entry .getValue ());
9896 }
99- return i ;
97+ return entry . getKey () ;
10098 }
10199 }
100+ String index = idFactory .create ().toString ();
102101 BytesWithFlag bytesWithFlag = new BytesWithFlag (bytes );
103- list .add (bytesWithFlag );
104- int index = list .size () - 1 ;
102+ duplicateMap .put (index , bytesWithFlag );
105103 addWrite (instanceId , key , index , bytesWithFlag );
106104 return index ;
107105 }
108106 }
109107
110- private void addWrite (String instanceId , String key , int index , BytesWithFlag bytes ) {
108+ private void addWrite (String instanceId , String key , String index , BytesWithFlag bytes ) {
111109 pending
112110 .computeIfAbsent (instanceId , __ -> new ArrayList <>())
113111 .add (new PendingWrite (key , index , bytes ));
114112 }
115113
116- public Optional <byte []> readBytes (String instanceId , HashItem item , int index ) {
117- Map <String , List < BytesWithFlag >> instanceMap = getInstanceMap (instanceId );
114+ public Optional <byte []> readBytes (String instanceId , HashItem item , String index ) {
115+ Map <String , Map < String , BytesWithFlag >> instanceMap = getInstanceMap (instanceId );
118116 synchronized (instanceMap ) {
119117 return Optional .ofNullable (instanceMap .get (item .key ()))
120- .filter (list -> list .size () > index )
121- .map (list -> list .get (index ))
118+ .map (m -> m .get (index ))
122119 .map (bytes -> bytes .bytes );
123120 }
124121 }
125122
126- private Map <String , List < BytesWithFlag >> getInstanceMap (String instanceId ) {
123+ private Map <String , Map < String , BytesWithFlag >> getInstanceMap (String instanceId ) {
127124 return mappingInfo .computeIfAbsent (
128125 instanceId ,
129126 k ->
@@ -132,9 +129,11 @@ private Map<String, List<BytesWithFlag>> getInstanceMap(String instanceId) {
132129 Collectors .toMap (
133130 Map .Entry ::getKey ,
134131 e ->
135- e .getValue ().stream ()
136- .map (b -> new BytesWithFlag (b , true ))
137- .collect (Collectors .toCollection (ArrayList ::new )))));
132+ e .getValue ().entrySet ().stream ()
133+ .collect (
134+ Collectors .toMap (
135+ Entry ::getKey ,
136+ v -> new BytesWithFlag (v .getValue (), true ))))));
138137 }
139138
140139 public void persist () {
@@ -143,7 +142,7 @@ public void persist() {
143142 String instanceId = item .getKey ();
144143 List <HashMappingInfo > list = new ArrayList <>();
145144 result .put (instanceId , list );
146- Map <String , List < BytesWithFlag >> instanceMap = mappingInfo .get (instanceId );
145+ Map <String , Map < String , BytesWithFlag >> instanceMap = mappingInfo .get (instanceId );
147146 if (instanceMap != null ) {
148147 synchronized (instanceMap ) {
149148 item .getValue ()
@@ -162,7 +161,7 @@ public void persist() {
162161 public void afterCommit () {
163162 for (Map .Entry <String , List <PendingWrite >> item : pending .entrySet ()) {
164163 String instanceId = item .getKey ();
165- Map <String , List < BytesWithFlag >> instanceMap = mappingInfo .get (instanceId );
164+ Map <String , Map < String , BytesWithFlag >> instanceMap = mappingInfo .get (instanceId );
166165 if (instanceMap != null ) {
167166 synchronized (instanceMap ) {
168167 item .getValue ().forEach (v -> v .bytes .persist ());
@@ -176,7 +175,7 @@ public void afterRollback() {
176175 pending .clear ();
177176 }
178177
179- public void afterRemove (String instanceId ) {
178+ public static void afterRemove (String instanceId ) {
180179 mappingInfo .remove (instanceId );
181180 }
182181}
0 commit comments