bpmnServer / bpmn-server

BPMN 2.0 server for Node.js , providing modeling, execution, persistence and monitoring for Workflow. along with sample UI. Intended to be developers workbench for BPMN 2.0
MIT License
186 stars 48 forks source link

V2.0 User task data still polluted by invoke input #164

Closed kstan79 closed 11 months ago

kstan79 commented 11 months ago

I notice version 2.0 the data still modify by invoke input. As discussed before this shouldn't as default behavior

ralphhanna commented 11 months ago

Yes, I know, I thought you mentioned that you want an update function as well.

If you pass empty object for data, no update will take place,same for assignment

kstan79 commented 11 months ago

I thought the invoke process trigger transformInput, and during invoke only 'data' can capture by tranformInput event. But, when use data during invoke, the instance data polluted.

kstan79 commented 11 months ago

for example, during event tranformInput, user submited input as { b: 11199 }, and data initially as { aaa: 2222, tenantId: 1, orgId: 1, branchId: 1 }. Sample of my workflow process property similar as below:

{
  workflowName: 'suspendcustomer',
  eventType: 'invoked',
  elementType: 'bpmn:UserTask',
  elementId: 'approve1',
  elementName: 'approve1',
  elementProps: {
    startedAt: 2023-12-21T15:28:39.544Z,
    assignee: 'kstan',
    candidateGroups: null,
    candidateUsers: null,
    dueDate: null,
    followUpDate: null,
    priority: null,
    formKey: 'simpleapprove'
  },
  usertaskinput: { b: 11199 },
  data: { aaa: 2222, tenantId: 1, orgId: 1, branchId: 1 },
  options: {}
}

afterwards, the usertaskinput been merge into data become:

{
aaa: 2222
tenantId: 1,
orgId: 1,
branchId: 1,
b: 11199
}

as mentioned, we need invoke submit input data, that is purely the actor input and it SHOULD NOT ASSUME AS PART OF DATA AND IT WILL MESS THE DATA.

previously we discussed, store user's input into vars as alternative in invoke but it seems not yet implemented. I'm ok to implement it and send PR, just need to get conclusion for go ahead.

ralphhanna commented 11 months ago

Please try the following logic:

  1. User provides input data, let us call it 'formData', {field1:val1,field2:val2}
  2. Your app calls api.engine.invoke({...},formData,....);
  3. Inside the model, you have a listener validate
    item.vars.field2=item.input.field2;
    delete data.field2;
  4. Now look at data: image

image

I hope this is what you are looking for.

p.s. transformInput is used only for serviceTasks

Thanks

kstan79 commented 11 months ago

Ok it seems can solve my problem.

However it is kind of hack, if every task added new properties in form data, we have to remember remove it.

Is there any place I can off merge invoke input into data?

I will try to implement it and send pr

ralphhanna commented 11 months ago

Let me think about it Sent from my iPhone

On Dec 21, 2023, at 7:45 PM, Ks Tan @.***> wrote:



Ok it seems can solve my problem.

However it is kind of hack, if every task added new properties in form data, we have to remember remove it.

Is there any place I can off merge invoke input into data?

I will try to implement it and send pr

— Reply to this email directly, view it on GitHubhttps://github.com/bpmnServer/bpmn-server/issues/164#issuecomment-1867093076, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AC2XVKCFJSJN7AEISUOKF4DYKTJ3JAVCNFSM6AAAAABA5Y6SP6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNRXGA4TGMBXGY. You are receiving this because you commented.Message ID: @.***>

ralphhanna commented 11 months ago

Ok, this should it without any code modifications to bpmn-server

In the AppDelegate class:

    async executionEvent(context, event) {

        if (event == 'transformInput') {

            // Move input to item.vars
            context.item.vars = JSON.parse(JSON.stringify(context.item.input));
            // remove input before system copies it instance.data
            context.item.input = {};
        }

This will change behaviour for all of your models, now input from users goes to item.vars instead of instance.data.

The challenge with that, you made it difficult for tasks to talk to each other. not easy to say:

getItemForTask(item,taskId) : IItem {
const items=item.token.execution.getItems();
// run a filter

}

Since sometimes, for good reason, there could be multiple items for 'Request' Task. But you can write a method in appServices or appUtils to

kstan79 commented 11 months ago

Thanks, I will try it and feed back if necessary.

kstan79 commented 11 months ago
executionEvent

no luck, I'd tried console something inexecutionEvent() but it seems never execute in both service task and user task.

kstan79 commented 11 months ago

The workable approach is implement at listener, copy property over. and set input = {}. But, the vars still not save anyway. I'm wondering why keep vars in mongodb

ralphhanna commented 11 months ago

both instance.data and item.vars are persistent. item.input and item.output` are not

kstan79 commented 11 months ago

I mean I'd transferee value from input to vars but not persist in mongodb, via listener transformInput

ralphhanna commented 11 months ago

What do you want to do with values the user has input?

kstan79 commented 11 months ago

Very basic requirement, assume there is multiple step approval, each approval have comment. We want to keep the comment and display at frontend.

Also, it for debugging purposes.

It is ok I can settle it with different way, just want to emphasize vars didn't store as your reply

ralphhanna commented 11 months ago

Are these steps in a different task or the task is repeated?

there several ways to do 1 store in instance.data in different variables 2 in data as array 3 each in item.vars

but in all cases it must be saved in database

ralphhanna commented 11 months ago

All workflows are db bound They are loaded into memory and destroyed after between steps

so you can shutdown the server and no data is lost

kstan79 commented 11 months ago

Yes, I mean I'd copy the value into 'item.vars', but it not save into database

ralphhanna commented 11 months ago

If you don’t save them in db, how are you going to display to the user later, say in few days?

if you don’t want to save data, just don’t copy to item.vars

ralphhanna commented 11 months ago

Sorry did I misunderstand you? Are you saying that item.vars didn’t save? As it should?

if this is the case please send me your code Thanks

kstan79 commented 11 months ago

Yes, base on our previous conversation bpmn server shall persist vars in db by itself, without any modification. Currently it not persist it.

ralphhanna commented 11 months ago

Can you please attach your sample code and model, because this works for me