cancel
Showing results for 
Search instead for 
Did you mean: 

Putting Job(/Message/Timer)Entity on queue instead of jobId

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
I'm thinking about one more optimization regarding the JobExecutor related to reducing the number of queries. Currently when a job is excecuted, it is retrieved from the DB based on its id. I did not find any caching for this. So we could do two things.
- Create some caching mechanism (not sure MyBatis has some kind of second level cache that you can turn on selectively
- Putting the entity in the queue instead of the id.

If this is in effect, it would have reduced the number of queries for the job executor under normal circumstances from 1 big query to retrieve all jobs and 2 selects and 2 updates PER JOB to just one update per job (if it is a cache hit). I've already tried putting the job in the queue and this works, but there might be downsides to this that I do not know of (since I do not know MyBatis that well and the doc mostly points to older versions, A JPA persistency layer anyone? Would be a nice challenge for me :-))

Thoughts?
5 REPLIES 5

tombaeyens
Champ in-the-making
Champ in-the-making
putting the entity ONLY in the queue is not a good idea.  as the mgmt service wants to show the backlog jobs.
but you could consider storing the already-locked job it in the table AND then putting the whole object on the queue.
then just pushing the whole job object on the queue is i believe a simple form of caching that you're looking for.  right?
i don't recall any mybatis caching similar to hibernate's second level cache.

jbarrez
Star Contributor
Star Contributor
MyBatis does have a second level cache, but it is not enabled currently.

Here is the text from the MyBatis userguide:

MyBatis has includes a powerful query caching feature which is very configurable and customizable.
A lot of changes have been made in the MyBatis 3 cache implementation to make it both more powerful and far easier to configure.

By default, there is no caching enabled, except for local session caching, which improves performance and is required to resolve circular dependencies. To enable a second level of caching, you simply need to add one line to your SQL Mapping file:

<cache/>

Literally that’s it. The effect of this one simple statement is as follows:

• All results from select statements in the mapped statement file will be cached.
• All insert, update and delete statements in the mapped statement file will flush the cache.
• The cache will use a Least Recently Used (LRU) algorithm for eviction.
• The cache will not flush on any sort of time based schedule (i.e. no Flush Interval).
• The cache will store 1024 references to lists or objects (whatever the query method returns).
• The cache will be treated as a read/write cache, meaning objects retrieved are not shared and can be safely modified by the caller, without interfering with other potential modifications by other callers or threads.

All of these properties are modifiable through the attributes of the cache element. For example:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
This more advanced configuration creates a FIFO cache that flushes once every 60 seconds, stores up to 512 references to result objects or lists, and objects returned are considered read-only, thus modifying them could cause conflicts between callers in different threads.
The available eviction policies available are: LRU, FIFO, WEAK

Using a Custom Cache
In addition to customizing the cache in these ways, you can also completely override the cache behavior by implementing your own cache, or creating an adapter to other 3rd party caching solutions.
<cache type=”com.domain.something.MyCustomCache”/>

frederikw
Champ in-the-making
Champ in-the-making
I added the "<cache/>"-tag to job.mapping.xml but still got an extra "select job"-query for when the job was to be executed. I tested this by running the "OneMessageTest.java" (available in attached jobcache.zip) and looking at the queries.log of my local MySQL database.

I've added an extra jobCache to DbSqlSession which does prevent the extra select-query (see "jobCache-changes.txt" in attached jobcache.zip). This does the trick but I'm not sure this is a proper solution.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
putting the entity ONLY in the queue is not a good idea.  as the mgmt service wants to show the backlog jobs.
but you could consider storing the already-locked job it in the table AND then putting the whole object on the queue.
then just pushing the whole job object on the queue is i believe a simple form of caching that you're looking for.  right?
i don't recall any mybatis caching similar to hibernate's second level cache.

Duh… SURE I'd also put it in the DB…. come on, give me some credit 😛 It's not that I've lost my mind the past months… although…. 😄

But yes, that was the idea.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
I added the "<cache/>"-tag to job.mapping.xml but still got an extra "select job"-query for when the job was to be executed. I tested this by running the "OneMessageTest.java" (available in attached jobcache.zip) and looking at the queries.log of my local MySQL database.

Was this query also visble in the DB? Or just in the java log file? In addition, I'm not sure what kind of impact this would have on the rest of Activiti

I've added an extra jobCache to DbSqlSession which does prevent the extra select-query (see "jobCache-changes.txt" in attached jobcache.zip). This does the trick but I'm not sure this is a proper solution

Ok, lets see what performs better under load. Using a jobCache seems nice, but has the drawback that tuning/sizing/flushing etc it is needed. While with putting the entity on the queue already gives you that option.