Skip to content

Commit 632c9e4

Browse files
authored
Merge pull request #374 from hjotha/submit/writer-change-items-storage-list
fix: write valid change-action item storage lists
2 parents fb69f79 + 6bfd659 commit 632c9e4

3 files changed

Lines changed: 130 additions & 6 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
-- ============================================================================
2+
-- Bug #373: Writer emitted invalid ChangeActionItem list markers
3+
-- ============================================================================
4+
--
5+
-- Symptom (before fix):
6+
-- The microflow BSON writer serialized `CreateChangeAction.Items` and
7+
-- `ChangeAction.Items` arrays with the COUNT of member changes as the
8+
-- first BSON array element. Mendix storage lists use a constant
9+
-- storage-list MARKER there. For ChangeActionItem lists this marker is
10+
-- `2`, independent of how many items the list contains. Writing the
11+
-- item count produced unstable microflow BSON for create/change object
12+
-- actions and could lead to invalid action payloads when Studio Pro
13+
-- re-loaded the model.
14+
--
15+
-- Additionally, `ChangeAction` was missing its default
16+
-- `ErrorHandlingType: Rollback` field, so the written shape did not
17+
-- match the expected action payload.
18+
--
19+
-- After fix:
20+
-- - Writer emits `bson.A{int32(2)}` for both CreateChangeAction.Items
21+
-- and ChangeAction.Items.
22+
-- - Writer emits the default `ErrorHandlingType: Rollback` for
23+
-- ChangeAction.
24+
--
25+
-- Usage:
26+
-- mxcli exec mdl-examples/bug-tests/373-change-action-items-storage-list.mdl -p app.mpr
27+
-- mxcli -p app.mpr -c "describe microflow BugTest373.MF_CreateAndChange"
28+
-- `mx check` against the resulting MPR must report 0 errors.
29+
-- ============================================================================
30+
31+
create module BugTest373;
32+
33+
create entity BugTest373.Order (
34+
Name : string(100),
35+
Status : string(50)
36+
);
37+
/
38+
39+
-- Create-with-members and change-with-members both exercise the
40+
-- ChangeActionItem storage list. After exec, the MPR must load cleanly
41+
-- in Studio Pro (`mx check` reports 0 errors).
42+
create microflow BugTest373.MF_CreateAndChange (
43+
$Name: string
44+
)
45+
returns BugTest373.Order as $Order
46+
begin
47+
$Order = create BugTest373.Order (Name = $Name);
48+
change $Order (Status = 'Processed');
49+
end;
50+
/
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package mpr
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/model"
9+
"github.com/mendixlabs/mxcli/sdk/microflows"
10+
"go.mongodb.org/mongo-driver/bson"
11+
)
12+
13+
func TestSerializeCreateObjectActionItemsUseStorageListMarker(t *testing.T) {
14+
action := &microflows.CreateObjectAction{
15+
BaseElement: model.BaseElement{ID: "create-1"},
16+
EntityQualifiedName: "SampleModule.Order",
17+
OutputVariable: "Order",
18+
Commit: microflows.CommitTypeNo,
19+
InitialMembers: []*microflows.MemberChange{
20+
{
21+
BaseElement: model.BaseElement{ID: "member-1"},
22+
AttributeQualifiedName: "SampleModule.Order.Name",
23+
Type: microflows.MemberChangeTypeSet,
24+
Value: "'Sample'",
25+
},
26+
},
27+
}
28+
29+
doc := serializeMicroflowAction(action)
30+
31+
items, ok := getBSONField(doc, "Items").(bson.A)
32+
if !ok {
33+
t.Fatalf("Items is %T, want bson.A", getBSONField(doc, "Items"))
34+
}
35+
if len(items) != 2 {
36+
t.Fatalf("Items length = %d, want marker plus one item", len(items))
37+
}
38+
if marker, ok := items[0].(int32); !ok || marker != 2 {
39+
t.Fatalf("Items marker = %#v, want int32(2)", items[0])
40+
}
41+
}
42+
43+
func TestSerializeChangeObjectActionItemsUseStorageListMarkerAndDefaultErrorHandling(t *testing.T) {
44+
action := &microflows.ChangeObjectAction{
45+
BaseElement: model.BaseElement{ID: "change-1"},
46+
ChangeVariable: "Order",
47+
Commit: microflows.CommitTypeNo,
48+
Changes: []*microflows.MemberChange{
49+
{
50+
BaseElement: model.BaseElement{ID: "member-1"},
51+
AttributeQualifiedName: "SampleModule.Order.Status",
52+
Type: microflows.MemberChangeTypeSet,
53+
Value: "'Processed'",
54+
},
55+
},
56+
}
57+
58+
doc := serializeMicroflowAction(action)
59+
60+
if got := getBSONField(doc, "ErrorHandlingType"); got != "Rollback" {
61+
t.Fatalf("ErrorHandlingType = %#v, want Rollback", got)
62+
}
63+
items, ok := getBSONField(doc, "Items").(bson.A)
64+
if !ok {
65+
t.Fatalf("Items is %T, want bson.A", getBSONField(doc, "Items"))
66+
}
67+
if len(items) != 2 {
68+
t.Fatalf("Items length = %d, want marker plus one item", len(items))
69+
}
70+
if marker, ok := items[0].(int32); !ok || marker != 2 {
71+
t.Fatalf("Items marker = %#v, want int32(2)", items[0])
72+
}
73+
}

sdk/mpr/writer_microflow_actions.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ func serializeMicroflowAction(action microflows.MicroflowAction) bson.D {
6565
}
6666
// ErrorHandlingType is required (default to Rollback)
6767
doc = append(doc, bson.E{Key: "ErrorHandlingType", Value: "Rollback"})
68-
// Serialize Items (ChangeActionItem) for InitialMembers
69-
// IMPORTANT: Mendix BSON arrays include the count as the first element
70-
items := bson.A{int32(len(a.InitialMembers))} // Start with count
68+
// Serialize Items (ChangeActionItem) for InitialMembers. Mendix stores
69+
// this list with storage-list marker 2, not with the item count.
70+
items := bson.A{int32(2)}
7171
for _, change := range a.InitialMembers {
7272
item := bson.D{
7373
{Key: "$ID", Value: idToBsonBinary(string(change.ID))},
@@ -99,10 +99,11 @@ func serializeMicroflowAction(action microflows.MicroflowAction) bson.D {
9999
{Key: "$Type", Value: "Microflows$ChangeAction"}, // storageName differs from qualifiedName
100100
{Key: "ChangeVariableName", Value: a.ChangeVariable},
101101
{Key: "Commit", Value: string(a.Commit)},
102+
{Key: "ErrorHandlingType", Value: "Rollback"},
102103
}
103-
// Serialize Items (ChangeActionItem)
104-
// IMPORTANT: Mendix BSON arrays include the count as the first element
105-
items := bson.A{int32(len(a.Changes))} // Start with count
104+
// Serialize Items (ChangeActionItem). Mendix stores this list with
105+
// storage-list marker 2, not with the item count.
106+
items := bson.A{int32(2)}
106107
for _, change := range a.Changes {
107108
item := bson.D{
108109
{Key: "$ID", Value: idToBsonBinary(string(change.ID))},

0 commit comments

Comments
 (0)