
|
If you were logged in you would be able to see more operations.
|
|
|
|
File Attachments:
|
1.
TestApp.zip (3 kB)
|
|
Environment:
|
Mule embedded, Spring-based configuration
|
|
Issue Links:
|
Block
|
|
|
|
This issue is blocked by:
|
|
MULE-3974
Values of maxThreadsActive and maxThreadsIdle are not accurate for SedaService (maxThreadsActive= maxThreadsActive-1)
|
|
|
|
|
MULE-3975
doThreading attribute even if configured is not used with Seda service threading profile
|
|
|
|
|
|
|
| Labels: |
|
| User impact: |
High
|
| Effort points: |
1
|
Back in 1.3, I had a simple component of which there was one instance. If it was busy, the incoming messages would be queued in the vmQueue connector. So I could hold a lot of state in my component and not worry about thread safety nor about having to load all that state multiple times.
Since moving to 2.0 I don't seem to be able to replicate this behavior. I am using a singleton spring bean, so there is only one instance in the context, but I haven't been able to make it so that there is only one thread running through this code at one time.
Here is my previous, working config (relevant parts):
<connector name="vmQueue" className="org.mule.providers.vm.VMConnector">
<properties>
<property name="queueEvents" value="true"/>
</properties>
</connector>
...
<mule-descriptor name="JobWorker" implementation="com.mycompany.JobWorker">
<inbound-router>
<endpoint address="vm://JobWorkerQueue" connector="vmQueue"/>
</inbound-router>
<pooling-profile maxActive="1" maxIdle="1" initialisationPolicy="INITIALISE_FIRST"
exhaustedAction="WAIT" maxWait="0"/>
</mule-descriptor>
And the new one:
<vm:connector name="vmQueue" queueEvents="true"> -->
<vm:queueProfile maxOutstandingMessages="0" persistent="false"/>
</vm:connector>
<vm:endpoint name="jobWorkerQueueEndpoint" address="vm://JobWorkerQueue" connector-ref="vmQueue"/>
...
<mule:service name="jobWorkerService">
<mule:inbound>
<mule:inbound-endpoint ref="jobWorkerQueueEndpoint"/>
</mule:inbound>
<mule:component>
<mule:spring-object bean="jobWorker"/>
</mule:component>
</mule:service>
...
<bean name="jobWorker" class="com.mycompany.JobWorker"/>
Among other things, I tried switching to a pooled-component with a 1-object pooling-profile (basically doesn't work and seems to replicated spring-object functionality). Then I tried adding the following component-threading-profile to the jobWorkerService definition:
<mule:component-threading-profile maxThreadsActive="1" maxThreadsIdle="1" poolExhaustedAction="WAIT" />
The JobTester class is a JUnit test which uses DefaultJobSubmitter to push DefaultJob objects into the mule endpoint. The JobWorker listens via that endpoint (configured as "jobWorkerService").
JobWorker will have startJob() called by Mule, at which point it will spawn a thread to "run" the Job. The DefaultJob just sleeps for 10 seconds. When finished it triggers a listener which the JobWorker is waiting for, at which point the JobWorker will return from the startJob() call and the next one should go through. If a job is currently running when startJob() is called again, it will throw an IllegalStateException.
- If you run the test case as it is now, it will throw the IllegalStateException to the console once the second job is submitted.
- If you tweak the JobTester.WAIT_PERIOD value to 15000, it will not throw any exception.
- If you uncomment the component-threading-profile tag in the jobWorkerService definition, you can see it throw an exception as soon as the first job is submitted.
The preferred behavior is for the VM Connector to queue up events and have one thread consume the queue and call startJob() serially, rather than multiple threads doing so in parallel.
Does this seem like a tricky problem, or fairly straightforward? I could get Mule source and poke around if you think it's likely to be effective.
Thanks,
Ben
|
|
Description
|
Back in 1.3, I had a simple component of which there was one instance. If it was busy, the incoming messages would be queued in the vmQueue connector. So I could hold a lot of state in my component and not worry about thread safety nor about having to load all that state multiple times.
Since moving to 2.0 I don't seem to be able to replicate this behavior. I am using a singleton spring bean, so there is only one instance in the context, but I haven't been able to make it so that there is only one thread running through this code at one time.
Here is my previous, working config (relevant parts):
<connector name="vmQueue" className="org.mule.providers.vm.VMConnector">
<properties>
<property name="queueEvents" value="true"/>
</properties>
</connector>
...
<mule-descriptor name="JobWorker" implementation="com.mycompany.JobWorker">
<inbound-router>
<endpoint address="vm://JobWorkerQueue" connector="vmQueue"/>
</inbound-router>
<pooling-profile maxActive="1" maxIdle="1" initialisationPolicy="INITIALISE_FIRST"
exhaustedAction="WAIT" maxWait="0"/>
</mule-descriptor>
And the new one:
<vm:connector name="vmQueue" queueEvents="true"> -->
<vm:queueProfile maxOutstandingMessages="0" persistent="false"/>
</vm:connector>
<vm:endpoint name="jobWorkerQueueEndpoint" address="vm://JobWorkerQueue" connector-ref="vmQueue"/>
...
<mule:service name="jobWorkerService">
<mule:inbound>
<mule:inbound-endpoint ref="jobWorkerQueueEndpoint"/>
</mule:inbound>
<mule:component>
<mule:spring-object bean="jobWorker"/>
</mule:component>
</mule:service>
...
<bean name="jobWorker" class="com.mycompany.JobWorker"/>
Among other things, I tried switching to a pooled-component with a 1-object pooling-profile (basically doesn't work and seems to replicated spring-object functionality). Then I tried adding the following component-threading-profile to the jobWorkerService definition:
<mule:component-threading-profile maxThreadsActive="1" maxThreadsIdle="1" poolExhaustedAction="WAIT" />
The JobTester class is a JUnit test which uses DefaultJobSubmitter to push DefaultJob objects into the mule endpoint. The JobWorker listens via that endpoint (configured as "jobWorkerService").
JobWorker will have startJob() called by Mule, at which point it will spawn a thread to "run" the Job. The DefaultJob just sleeps for 10 seconds. When finished it triggers a listener which the JobWorker is waiting for, at which point the JobWorker will return from the startJob() call and the next one should go through. If a job is currently running when startJob() is called again, it will throw an IllegalStateException.
- If you run the test case as it is now, it will throw the IllegalStateException to the console once the second job is submitted.
- If you tweak the JobTester.WAIT_PERIOD value to 15000, it will not throw any exception.
- If you uncomment the component-threading-profile tag in the jobWorkerService definition, you can see it throw an exception as soon as the first job is submitted.
The preferred behavior is for the VM Connector to queue up events and have one thread consume the queue and call startJob() serially, rather than multiple threads doing so in parallel.
Does this seem like a tricky problem, or fairly straightforward? I could get Mule source and poke around if you think it's likely to be effective.
Thanks,
Ben
|
Show » |
|
The JobTester class is a JUnit test which uses DefaultJobSubmitter to push DefaultJob objects into the mule endpoint. The JobWorker listens to that endpoint (configured as "jobWorkerService").
JobWorker will have startJob() called by Mule, at which point it will spawn a thread to "run" the Job. The DefaultJob just sleeps for 10 seconds. When finished it triggers a listener which the JobWorker is waiting for, at which point the JobWorker will return from the startJob() call and the next one should go through. If a job is currently running when startJob() is called again, it will throw an IllegalStateException.
The preferred behavior is for the VM Connector to queue up events and have one thread consume the queue and call startJob() serially, rather than multiple threads doing so in parallel.