Hi David,
Thanks for starting this discussion. You are right because of the current cache
behavior of the implementation also with relation to the usage of API is not
easy to understand.
Basic idea behind the cache behavior can be described in 3 steps:
1) query for an object and specify filters and put it in the cache
2) read from the cached object and write to the cached object while using
convenient micro operations (set and get property).
3) write back changes of the cached objet to the persistency (save)
For 2) only that information is available that was specified by the filter in
1). Additional information would require another query.
I would like to keep this behavior because it makes it easier to use API within
another framework where someone has to implement a callback not having the
context for a full service call or cannot influence how many times the callback
is executed just to return the same information.
Confusing is that there are some methods calls on CmisObject level that
bypasses the cache. updateProperties() for instance.
What do you think to come up with this rule set:
1) All methods on CmisObject level operate always on cache data. The
programming paradigm would be query - modify -save.
2) All modification operations on the Session level are not cached and will be
directly routed to the backend.
Here is some pseudo code of a cached scenario:
Session s = ...;
Document doc = s.getObject( ... with filter ... );
doc.setProperty( ... );
doc.updateProperties( ... );
if (ok) {
doc.save();
}
If doc is not saved then the corresponding object in the backend is not
modified.
A non cached pseudo code looks like this:
Session s = ...;
s.updateProperties( objecteId, .... );
If we could agree on such a rule then we have to re-work CmisObject to remove
methods that cannot be cached and add that methods to the Session class. Some
methods could be exist twice, one at the CmisObject (cached) and one at the
Session (not cached).
WDYT?
Regards,
Stephan
-----Original Message-----
From: David Caruana [mailto:[email protected]]
Sent: Dienstag, 12. Oktober 2010 18:19
To: [email protected]
Subject: Re: Proposal to clarify CmisObject caching behaviour
On 12 Oct 2010, at 16:22, Florent Guillaume wrote:
> Hi David,
>
> I'm a bit confused by some of the vocabulary I must confess. Could we
> make sure we don't confuse the term "cache" and the term "transient
> space", as they have different uses.
Of course.
>
> So do you want to remove completely any transient space and only have
> methods that write to the remote side on each method call? So, do you
> want to remove the fact that we can do:
> object.setProperty("foo1", "bar1");
> object.setProperty("foo2", "bar2");
> ...
> object.updateProperties();
> i.e. today there's a mini transient space tied to the properties of
> the object, flushed on updateProperties. I think this is quite useful
> as it avoids having the user building a map by hand and passing it to
> updateProperties, which is ugly for a high-level interface.
Yes, the proposal is to remove the mini transient space. The reason is to
simplify behaviour if we were to introduce a CmisObject implementation that
always refreshed its cache on updates. For example, with a transient space,
what is the behaviour when setProperty has been called and an "update" method
is then called prior to updateProperties. Are the transient changes discarded,
flushed, or just left as is?
>
> I'm ok with most methods that can do remote writes returning a CmisObject.
>
> But I don't like removing convenience methods on CmisObject like
> getRelationships, getAcl, etc. as they provide convenient access to
> the users.
There would still be the methods getRelationships() and getAcl(), but they
would only return what has already been cached (as they do today). Currently,
there's also getRelationships(boolean, RelationshipDirection, ObjectType,
OperationContext) and getAcls(boolean) which go direct to the repository. It's
these that I propose are moved to Session.
>
> OTOH I'm completely for clarifying the caching aspects, for instance
> it's not clear today when caches are invalidated or updated, or what
> happens when you ask for a property that's not in the initial property
> filter that led to the creation of the object (in a number of my unit
> tests in Nuxeo I have to refresh() explicitly but this shouldn't be
> needed when all the writes were mine).
Indeed, this is the confusion I'm trying to remove with this proposal.
Admittedly, there is much to discuss, and the proposal is only a starting
point, but I wanted to open up the discussion early to determine if this
problem is severe enough to tackle.
Regards,
Dave
>
> Florent
>
>
>
> On Tue, Oct 12, 2010 at 12:49 PM, David Caruana
> <[email protected]> wrote:
>> Currently, we only have one implementation of Session -
>> PersistentSessionImpl. However, the OpenCMIS client API suggests transient
>> behaviour both in its API definition and behaviour, which I believe can be
>> confusing for users. In particular, when does OpenCMIS read information from
>> the cache vs from the repository, and when does OpenCMIS implicitly update
>> an item in its cache.
>>
>> I'd like to present the following changes in an attempt to clarify the above
>> and trigger discussion on how to improve things in this area...
>>
>> 1) All methods on CmisObject operate against the cache. This means that
>> reading a value from an item reads the value from the item in the cache, and
>> updates to the item change the cache i.e. refresh the item in the cache.
>> Methods that read directly from the repository move to Session. So, the
>> proposal is:
>>
>> Remove the following from CmisObject...
>> CmisObject.setName(String)
>> CmisObject.setProperty(String, Object)
>> CmisObject.updateProperties()
>>
>> Change CmisObject.updateProperties...
>> CmisObject CmisObject.updateProperties(Map<String, ?>) (Note: return
>> CmisObject instead of ObjectId)
>>
>> Note: If the repository creates a new version, a new CmisObject is returned,
>> otherwise the existing CmisObject is refreshed in the cache and returned.
>>
>> The following 'update' methods are also modified to refresh the item in the
>> cache after update:
>>
>> void CmisObject.applyPolicy(ObjectId...) (Note: accept vararg of policy
>> ids)
>> void CmisObject.removePolicy(ObjectId...) (Note: accept vararg of policy
>> ids)
>> Acl CmisObject.applyAcl(List<Ace>, List<Ace>, AclPropagation)
>> Acl CmisObject.addAcl(List<Ace>, AclPropagation) (Note: also return Acl to
>> be consistent with applyAcl)
>> Acl CmisObject.removeAcl(List<Ace>, AclPropagation) (Note: also return Acl
>> to be consistent with applyAcl)
>>
>> Note: applyPolicy and removePolicy are also changed to accept a vararg of
>> ObjectIds.
>>
>> For use cases where the refresh of an item after update is not necessary,
>> the Session interface is used instead. So, the proposal is...
>>
>> Move following methods from CmisObject to Session...
>>
>> ItemIterable<Relationship> Session.getRelationships(ObjectId, boolean,
>> RelationshipDirection, ObjectType, OperationContext)
>> Acl Session.getAcl(ObjectId, boolean)
>>
>> Add...
>>
>> ObjectId Session.updateProperties(ObjectId, Map<String, ?>)
>> void applyPolicy(ObjectId, ObjectId...)
>> void removePolicy(ObjectId, ObjectId...)
>> Acl applyAcl(ObjectId, List<Ace> addAces, List<Ace> removeAces,
>> AclPropagation aclPropagation)
>> Acl getAcl(ObjectId, boolean onlyBasicPermissions)
>>
>> 2) Following the pattern in 1), setting content on a Document alters
>> slightly too.
>>
>> Document setContentStream(ContentStream contentStream, boolean overwrite)
>> Document deleteContentStream()
>>
>> Instead of returning ObjectId, the proposal is to return Document. Depending
>> on the repository, the document may be the same item as before (updated in
>> the cache), or a new Document, to represent a new version.
>>
>> Also add to Session...
>>
>> ObjectId setContentStream(ObjectId, ContentStream contentStream, boolean
>> overwrite)
>> ObjectId deleteContentStream(ObjectId)
>>
>> 3) Remove transient methods from Session.
>>
>> Until we've thought through transient session behaviour I propose we remove
>> the following methods:
>>
>> Session.save()
>> Session.cancel()
>>
>> Regards,
>> Dave
>
>
>
> --
> Florent Guillaume, Director of R&D, Nuxeo
> Open Source, Java EE based, Enterprise Content Management (ECM)
> http://www.nuxeo.com http://www.nuxeo.org +33 1 40 33 79 87