Skip to content

Commit 2051ed8

Browse files
authored
Merge pull request #126 from mxlint/bugfix/memory-usage-2
more memory optimizations
2 parents 0a2f264 + f8856d0 commit 2051ed8

22 files changed

Lines changed: 706 additions & 2262 deletions

‎mpr/export_stream.go‎

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,19 @@ func buildExportPlanV2(inputDirectory string, mprPath string) (*exportPlan, erro
213213
func appendUnitDescriptor(unit MxUnit, contents bson.M, modules *[]MxModule, folders *[]MxFolder, documents *[]exportDocumentDescriptor) {
214214
if unit.ContainmentName == "Modules" {
215215
name, _ := contents["Name"].(string)
216+
fromAppStore, _ := contents["FromAppStore"].(bool)
217+
appStoreVersion, _ := contents["AppStoreVersion"].(string)
218+
appStoreGuid, _ := contents["AppStoreGuid"].(string)
219+
appStoreVersionGuid, _ := contents["AppStoreVersionGuid"].(string)
220+
appStorePackageId, _ := contents["AppStorePackageId"].(string)
216221
*modules = append(*modules, MxModule{
217-
Name: name,
218-
ID: unit.UnitID,
219-
Attributes: contents,
222+
Name: name,
223+
ID: unit.UnitID,
224+
FromAppStore: fromAppStore,
225+
AppStoreVersion: appStoreVersion,
226+
AppStoreGuid: appStoreGuid,
227+
AppStoreVersionGuid: appStoreVersionGuid,
228+
AppStorePackageId: appStorePackageId,
220229
})
221230
}
222231

@@ -226,10 +235,9 @@ func appendUnitDescriptor(unit MxUnit, contents bson.M, modules *[]MxModule, fol
226235
name, _ = contents["Name"].(string)
227236
}
228237
*folders = append(*folders, MxFolder{
229-
Name: name,
230-
ID: unit.UnitID,
231-
ParentID: unit.ContainerID,
232-
Attributes: contents,
238+
Name: name,
239+
ID: unit.UnitID,
240+
ParentID: unit.ContainerID,
233241
})
234242
}
235243

@@ -281,13 +289,7 @@ func exportDocumentsFromPlan(plan *exportPlan, outputDirectory string, raw bool,
281289
}
282290

283291
if docType, _ := attributes["$Type"].(string); docType == microflowDocumentType {
284-
enriched := enrichMicroflowDocument(MxDocument{
285-
Name: document.Name,
286-
Type: document.Type,
287-
Path: document.Path,
288-
Attributes: attributes,
289-
})
290-
attributes = enriched.Attributes
292+
addMicroflowPseudocode(document.Name, attributes)
291293
}
292294

293295
if err := writeDocumentToDisk(document, outputDirectory, cleanData(attributes, raw)); err != nil {

‎mpr/microflow.go‎

Lines changed: 7 additions & 268 deletions
Original file line numberDiff line numberDiff line change
@@ -1,276 +1,15 @@
11
package mpr
22

3-
const microflowDocumentType = "Microflows$Microflow"
4-
5-
func enrichMicroflowDocument(mf MxDocument) MxDocument {
6-
mf = addMicroflowPseudocode(mf)
7-
mf = transformMicroflow(mf)
8-
return mf
9-
}
10-
11-
func transformMicroflow(mf MxDocument) MxDocument {
12-
log.Infof("Transforming microflow %s", mf.Name)
3+
import "go.mongodb.org/mongo-driver/bson"
134

14-
cleanedData := bsonToMap(mf.Attributes)
15-
objs, flows, ok := extractMicroflowGraphData(mf.Name, cleanedData)
16-
if !ok {
17-
return mf
18-
}
19-
startEvent, ok := getMxMicroflowObjectByType(objs, "Microflows$StartEvent")
20-
if !ok {
21-
log.Warnf("StartEvent not found for microflow %s, skipping transformation", mf.Name)
22-
return mf
23-
}
24-
25-
root := MxMicroflowNode{
26-
Type: startEvent.Type,
27-
ID: startEvent.ID,
28-
Attributes: startEvent.Attributes,
29-
}
30-
buildDAG(&root, nil, flows, objs)
31-
mainFlow := make([]map[string]interface{}, 0)
32-
labels := make(map[string]interface{}, 0)
33-
extractMainFlow(&mainFlow, &root, &labels)
34-
mf.Attributes["MainFunction"] = mainFlow
35-
// remove ObjectCollection
36-
delete(mf.Attributes, "ObjectCollection")
37-
return mf
38-
}
5+
const microflowDocumentType = "Microflows$Microflow"
396

40-
func addMicroflowPseudocode(mf MxDocument) MxDocument {
41-
cleanedData := bsonToMap(mf.Attributes)
42-
pseudocode, err := generateMicroflowPseudocode(mf.Name, cleanedData)
7+
func addMicroflowPseudocode(name string, attributes bson.M) {
8+
cleanedData := bsonToMap(attributes)
9+
pseudocode, err := generateMicroflowPseudocode(name, cleanedData)
4310
if err != nil {
44-
log.Warnf("Could not generate pseudocode for microflow %s: %v", mf.Name, err)
45-
return mf
46-
}
47-
mf.Attributes["pseudocode"] = pseudocode
48-
return mf
49-
}
50-
51-
func extractMicroflowGraphData(name string, cleanedData map[string]interface{}) ([]MxMicroflowObject, []MxMicroflowEdge, bool) {
52-
objsCollectionRaw, ok := cleanedData["ObjectCollection"]
53-
if !ok || objsCollectionRaw == nil {
54-
log.Warnf("ObjectCollection not found for microflow %s, skipping transformation", name)
55-
return nil, nil, false
56-
}
57-
58-
objsCollection, ok := objsCollectionRaw.(map[string]interface{})
59-
if !ok {
60-
log.Warnf("ObjectCollection is not a map for microflow %s, skipping transformation", name)
61-
return nil, nil, false
62-
}
63-
64-
objectsRaw, ok := objsCollection["Objects"]
65-
if !ok || objectsRaw == nil {
66-
log.Warnf("Objects not found in ObjectCollection for microflow %s, skipping transformation", name)
67-
return nil, nil, false
68-
}
69-
70-
objects, ok := objectsRaw.([]interface{})
71-
if !ok {
72-
log.Warnf("Objects is not a slice for microflow %s, skipping transformation", name)
73-
return nil, nil, false
74-
}
75-
76-
flowsRaw, ok := cleanedData["Flows"]
77-
if !ok || flowsRaw == nil {
78-
log.Warnf("Flows not found for microflow %s, skipping transformation", name)
79-
return nil, nil, false
80-
}
81-
82-
flowsSlice, ok := flowsRaw.([]interface{})
83-
if !ok {
84-
log.Warnf("Flows is not a slice for microflow %s, skipping transformation", name)
85-
return nil, nil, false
86-
}
87-
88-
return convertToMxMicroflowObjects(objects), convertToMxMicroflowEdges(flowsSlice), true
89-
}
90-
91-
func extractMainFlow(mainFlow *[]map[string]interface{}, current *MxMicroflowNode, labels *map[string]interface{}) {
92-
c := convertMxMicroflowNodeToMap(current)
93-
*mainFlow = append(*mainFlow, c)
94-
if current.Type == "Microflows$EndEvent" {
95-
return
96-
}
97-
98-
if current.Type == "Microflows$ExclusiveMerge" {
99-
id, ok := c["ID"].(string)
100-
if !ok {
101-
log.Warn("ID is not a string or is nil")
102-
return
103-
}
104-
// check if label already exists
105-
if _, ok := (*labels)[id]; !ok {
106-
(*labels)[id] = c
107-
// continue expanding this subflow
108-
} else {
109-
log.Infof("Loop detected; not traversing")
110-
return
111-
}
112-
}
113-
114-
children := current.Children
115-
//current.Children = nil
116-
if children == nil {
117-
return
118-
}
119-
if len(*children) == 0 {
11+
log.Warnf("Could not generate pseudocode for microflow %s: %v", name, err)
12012
return
121-
} else if len(*children) == 1 {
122-
// sequence
123-
child := (*children)[0]
124-
extractMainFlow(mainFlow, &child, labels)
125-
} else {
126-
// split
127-
splits := make([]interface{}, 0)
128-
for _, child := range *children {
129-
subflow := make([]map[string]interface{}, 0)
130-
extractMainFlow(&subflow, &child, labels)
131-
splits = append(splits, subflow)
132-
}
133-
c["Splits"] = splits
134-
}
135-
}
136-
137-
func buildDAG(current *MxMicroflowNode, parent *MxMicroflowNode, flows []MxMicroflowEdge, objects []MxMicroflowObject) {
138-
139-
current.Parent = parent
140-
children := make([]MxMicroflowNode, 0)
141-
142-
switch current.Type {
143-
case "Microflows$ExclusiveMerge":
144-
start := backtrack(current, current.Parent)
145-
if start == nil {
146-
// no loop
147-
edges := getMxMicroflowEdgesByOrigin(flows, current.ID)
148-
149-
for _, edge := range edges {
150-
edgeNode := MxMicroflowNode{
151-
Type: edge.Type,
152-
ID: edge.ID,
153-
Attributes: edge.Attributes,
154-
}
155-
156-
buildDAG(&edgeNode, current, flows, objects)
157-
children = append(children, edgeNode)
158-
}
159-
} else {
160-
log.Infof("Loop detected; not traversing")
161-
return
162-
}
163-
case "Microflows$SequenceFlow":
164-
destination, _ := current.Attributes["DestinationPointer"].(string)
165-
obj, ok := getMxMicroflowObjectByID(objects, destination)
166-
if !ok {
167-
log.Warnf("Destination object %s not found for sequence flow %s", destination, current.ID)
168-
return
169-
}
170-
objectNode := MxMicroflowNode{
171-
Type: obj.Type,
172-
ID: obj.ID,
173-
Attributes: obj.Attributes,
174-
}
175-
buildDAG(&objectNode, current, flows, objects)
176-
children = append(children, objectNode)
177-
default:
178-
edges := getMxMicroflowEdgesByOrigin(flows, current.ID)
179-
180-
for _, edge := range edges {
181-
edgeNode := MxMicroflowNode{
182-
Type: edge.Type,
183-
ID: edge.ID,
184-
Attributes: edge.Attributes,
185-
}
186-
187-
buildDAG(&edgeNode, current, flows, objects)
188-
children = append(children, edgeNode)
189-
}
190-
}
191-
current.Children = &children
192-
}
193-
194-
func backtrack(current *MxMicroflowNode, parent *MxMicroflowNode) *MxMicroflowNode {
195-
if parent == nil {
196-
return nil
197-
}
198-
if parent.ID == current.ID {
199-
return parent
200-
}
201-
return backtrack(current, parent.Parent)
202-
}
203-
204-
func getMxMicroflowEdgesByOrigin(edges []MxMicroflowEdge, originId string) []MxMicroflowEdge {
205-
result := make([]MxMicroflowEdge, 0)
206-
for _, edge := range edges {
207-
if edge.Origin == originId {
208-
result = append(result, edge)
209-
}
210-
}
211-
return result
212-
}
213-
214-
func getMxMicroflowObjectByType(objs []MxMicroflowObject, objType string) (MxMicroflowObject, bool) {
215-
for _, obj := range objs {
216-
if obj.Type == objType {
217-
return obj, true
218-
}
219-
}
220-
return MxMicroflowObject{}, false
221-
}
222-
223-
func getMxMicroflowObjectByID(objs []MxMicroflowObject, objID string) (MxMicroflowObject, bool) {
224-
for _, obj := range objs {
225-
if obj.ID == objID {
226-
return obj, true
227-
}
228-
}
229-
return MxMicroflowObject{}, false
230-
}
231-
232-
func convertToMxMicroflowObjects(objs []interface{}) []MxMicroflowObject {
233-
result := make([]MxMicroflowObject, 0, len(objs))
234-
for _, o := range objs {
235-
castedObject, ok := o.(map[string]interface{})
236-
if !ok {
237-
continue
238-
}
239-
objType, _ := castedObject["$Type"].(string)
240-
id := readMicroflowID(castedObject["$ID"])
241-
if objType == "" || id == "" {
242-
continue
243-
}
244-
result = append(result, MxMicroflowObject{
245-
Type: objType,
246-
ID: id,
247-
Attributes: castedObject,
248-
})
249-
}
250-
return result
251-
}
252-
253-
func convertToMxMicroflowEdges(flows []interface{}) []MxMicroflowEdge {
254-
result := make([]MxMicroflowEdge, 0, len(flows))
255-
for _, f := range flows {
256-
castedFlow, ok := f.(map[string]interface{})
257-
if !ok {
258-
continue
259-
}
260-
flowType, _ := castedFlow["$Type"].(string)
261-
id := readMicroflowID(castedFlow["$ID"])
262-
origin := readMicroflowID(castedFlow["OriginPointer"])
263-
destination := readMicroflowID(castedFlow["DestinationPointer"])
264-
if flowType == "" || id == "" || origin == "" || destination == "" {
265-
continue
266-
}
267-
result = append(result, MxMicroflowEdge{
268-
Type: flowType,
269-
ID: id,
270-
Origin: origin,
271-
Destination: destination,
272-
Attributes: castedFlow,
273-
})
27413
}
275-
return result
14+
attributes["pseudocode"] = pseudocode
27615
}

0 commit comments

Comments
 (0)