Closed hectorfausm closed 6 days ago
Hi @hectorfausm ,
thanks for your finding!
Yes I analyzed the code now also in deep and it sees to be all related to the new BPMN ModelManager
used by the EJB ModelService
.
The root problem is that the XML parsers (xerces in this case) are not thread save. So operations on the Dom tree will fail.
Do you have the chance to test a small change in the class org.imixs.workflow.engine.ModelService
?
Just change the class header:
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS",
"org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS",
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS",
"org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS",
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@Singleton
@Lock(LockType.WRITE) // This is the key change
public class ModelService {
// ... existing implementation ...
}
This should have the following effect:
@ConcurrencyManagement
(which was redundant since it's the default)@Lock(LockType.WRITE)
which means:
I hope this solves the issue.
Ok, I tested it myself. This suggested change does not solve the issue. I need to investigate in more detail. Maybe we need a change in the Open-BPMN Metamodel Implementation.
The problem is the DOM tree hold by the org.openbpmn.bpmn.BPMNModel
class in the instance variable doc
which is not thread save.
Let's stay connected....
Indeed, I just tried the change you mentioned, and the error still persists. Thank you so much for the quick response and for the project. Just trying to help: maybe creating a deep copy of the object each time it is returned? I gave it a try, but the object is very complex and I haven’t quite managed to get it working.
Thanks again!
Yes I try to avoid a deep copy. I think I can implement a pool mechanism. Currently I am doing some refactoring. Looks good so far...
I tried to compile the branch and got some compilation errors. I assume it's still a work in progress. If I can help with anything, feel free to let me know.
Best regards!
Yes the branch is under heavy development ;-) - lot of refactoring (mostly junit tests ;-) I am near to the end. Yes you can help me with the critical method to create the thread save version of the BPMNModel object later. But first I need to complete the refactoring part....
Hi @hectorfausm - good news it looks like this issue is fixed with the latest snapshot version 6.2.2-SNAPSHOT (master branch)
The surprising thing is, that even my initially naive approach, of simply cloning the BPMNModel
, shows hardly any noticeable effects on performance. Overall, however, there was a lot of refactoring in the WorkflowKernel
, ModelManager
and ModelService
.
The ModelService
now only manages the model metadata and returns a new exclusive BPMN model on each request - and no longer a shared version of the BPMNModel (with its embedded DOM tree).
The relevant method for this part you can see in the method getBPMModel
I expected that constructing a complete new BPMNModel from the BPMN raw data has more impact on performance. However I also implemented a lot of new local caching in the WorkflowKernel. So even in very complex processing cycles the performance should be still high.
In the Imixs-Microservice project I also added a new junit test to run a load test (Integration Test) when the service is running: https://github.com/imixs/imixs-microservice/blob/master/src/test/java/org/imixs/workflow/rest/LoadTest.java
I would greatly appreciate your feedback on this topic!
Hello, I’ve been testing batch executions following the same procedure I used when I encountered the error, and so far I have the following results:
=== TEST REPORT === Total operations: 30 Successfully started: 30 Average init time (ms): 133 Total test time (ms): 339
=== TEST REPORT === Total operations: 50 Successfully started: 50 Average init time (ms): 174 Total test time (ms): 329
=== TEST REPORT === Total operations: 100 Successfully started: 100 Average init time (ms): 319 Total test time (ms): 552
I stopped testing here because running more than 100 threads at once is excessive.
Thanks for your feedback. How is your overall impression now?
I said "excessive" in the sense that it's "more than enough." The error has disappeared, and as you rightly said, it's a bit slower, but I still think the response times are acceptable—especially considering that, even with 100 threads launched all at once, they're still responding in under half a second.
Describe the bug I have implemented a method to test how imixs-workflow + imixs-microservices handle concurrent load. When I execute a load with 5 simultaneous threads making requests, I encounter the following error:
To Reproduce Steps to reproduce the behavior:
Expected behavior Imixs should be able to synchronize concurrent events and avoid synchronization issues with Xerces objects.
Additional context I investigated a bit and it appears to be a synchronization issue. I attempted to wrap the method that retrieves the cached BPMNModel to return a new copy every time an object is requested from the cache, but I was not successful.