-
1. Re: The cache is per session?
hchiorean Jan 3, 2017 3:15 AM (in response to mfed)The only in-memory cache ModeShape uses explicitly is called a workspace cache and is a read-only cache shared by all the sessions that belong to a workspace. So multiple sessions share the same in-memory cache.
Each time I create a new session, I incur DB transaction costs even if I've already loaded the given node and it hasn't changed in any way.
If you create a new JCR session for a particular workspace and a node has been loaded (i.e. read) by another session and it has has not been evicted by the workspace cache (the eviction algorithm is a simple LRU algorithm) then this node will be read from the in-memory workspace cache and not from the DB.
However, when you refer to DB transactions I assume you refer to write-transactions: each time a JCR session performs a #save operation it
1. loads a fresh copy of all the changed nodes from the DB after exclusively locking the nodes
2. evicts these nodes at the end of the #save method from the workspace cache
Both (1) and (2) are mandatory to ensure the equivalent of strong serializable consistency between JCR sessions which is required in order to be JCR compliant. This means that whenever there are multiple writing sessions which change the same nodes, the "caching function" of the workspace cache is limited as entries will be frequently evicted.
-
2. Re: The cache is per session?
mfed Jan 3, 2017 8:10 AM (in response to hchiorean)Thanks for the reply. That's definitely not the behavior I'm seeing though - i must be doing something wrong. I'm not doing any write operations. When I run my code, the DB already has all of the data. I have the modeshape logs set to trace and I've set my cacheSize in my config to be much larger than needed. Each time that I load the node with a new session, I clearly see in the logs something like this:
DEBUG [15:31:52,226]: New transaction '300b1747-8e66-42b6-91f3-3142091f2b67' started by ModeShape...
DEBUG [15:31:52,275]: New DB connection allocated for tx '300b1747-8e66-42b6-91f3-3142091f2b67'
TRACE [15:31:52,276]: Created & stored new ModeShape synchronized transaction 'NestableThreadLocalTransaction[id='300b1747-8e66-42b6-91f3-3142091f2b67']'
TRACE [15:31:52,276]: Begin transaction org.modeshape.jcr.txn.LocalTransaction@c1f871a9
TRACE [15:31:52,276]: Save #5 (part of transaction 'org.modeshape.jcr.txn.LocalTransaction@c1f871a9') by session <anonymous>(fe8e0463f) is persisting the following changes:
TRACE [15:31:52,276]: Save #5 (part of transaction 'org.modeshape.jcr.txn.LocalTransaction@c1f871a9') by session <anonymous>(fe8e0463f) completed persisting changes to 0 nodes
DEBUG [15:31:52,276]: Altered 0 node(s)
TRACE [15:31:52,276]: Commit transaction 'org.modeshape.jcr.txn.LocalTransaction@c1f871a9'
DEBUG [15:31:52,276]: Received committed notification for transaction '300b1747-8e66-42b6-91f3-3142091f2b67'
DEBUG [15:31:52,276]: Committing the active connection for transaction 300b1747-8e66-42b6-91f3-3142091f2b67 with the changes: {}
DEBUG [15:31:52,292]: Releasing DB connection for transaction 300b1747-8e66-42b6-91f3-3142091f2b67
I'm doing something roughly equivalent to this:
val engine: ModeShapeEngine = new ModeShapeEngine
engine.start()
engine.deploy(config)
....
val repository = engine.getRepository(repositoryName)
...
for(i <- 1 to 15) {
val session = repository.login(workspace)
session.getNode("/foo")
session.save()
session.logout()
}
Given what you said above, I removed the session.save() and boom i stopped going to the DB. This behavior seems odd to me. If I have no changes to persist, I would expect save to be logically equivalent to a no-op, thus not hitting the DB or making any changes to the cache state if it is. For now, I'll just be smarter with my saves. Thanks for the help.
-
3. Re: The cache is per session?
hchiorean Jan 3, 2017 8:39 AM (in response to mfed)This behavior seems odd to me. If I have no changes to persist, I would expect save to be logically equivalent to a no-op, thus not hitting the DB or making any changes to the cache state if it is.
That's a fair point and this might very well be a bug. Please open a JIRA and link this conversation and I'll investigate this issue some more. Thanks.
-
4. Re: The cache is per session?
mfed Jan 3, 2017 9:51 AM (in response to hchiorean)done. Thanks again. https://issues.jboss.org/projects/MODE/issues/MODE-2655
-
5. Re: The cache is per session?
mfed Jan 3, 2017 10:30 AM (in response to hchiorean)I also seem to be getting this for each node on each read:
LOGGER.trace("Node '{0}' is not found in the '{1}' workspace cache; looking in store", key, workspaceName);
Do i need to do something special to mark nodes as cacheable? It looks like it should default to true but I don't understand why I'd get this each time.
-
6. Re: The cache is per session?
hchiorean Jan 3, 2017 10:36 AM (in response to mfed)No, as explained above unless there are #saves() (or nodes are not evicted from the ws cache as per LRU), nodes should be found in the workspace cache from multiple sessions (or the same read-only session)
There are several ways in which you can test this:
1. use a single session that does several #getNode calls on the same node (without saving). Only the first call should load the node from the DB
2. use several sessions to the same workspace (again, without saving either of them). Only one of them should load the node from the DB while the other should find the node in the cache
If either (1) or (2) are not working in your local environment then there's a bug somewhere so please attach the test case to MODE-2655.
-
7. Re: The cache is per session?
hchiorean Jan 4, 2017 3:36 AM (in response to hchiorean)I'm unable to reproduce your test case. See https://issues.jboss.org/browse/MODE-2655?focusedCommentId=13342875&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13342875 for more information.
-
8. Re: The cache is per session?
jacobilsoe Jun 14, 2017 7:12 AM (in response to hchiorean)I have a similar issue where I read nodes, never call save() and still the nodes are reread in each new session.
I did some debugging and found that TransactionalWorkspaceCache is used instead of WorkspaceCache because I run my code in a user transaction. Thus, a new cache is used for each transaction. Is there any way to work around this except from not running in a transaction?
Also it seems that RepositoryCache.createSession will create a ReadOnlySessionCache unless the current user has the READWRITE or ADMIN role. Is there any other way of "marking" the transaction as readonly?
Furthermore I tried using a READONLY user and now I get an exception when trying to read ACLs from a node due to the session being read-only. AccessControlManagerImpl.getApplicablePolicies throws an exception in case of a read-only session. Why is this the case?