I mentioned last week that I'd follow up with some pointers to our LockService 
implementation once it was done in Rave (see earlier messages in this thread 
for more details) -- here are those pointers:

++ LockService interface/implementation

http://svn.apache.org/viewvc/incubator/rave/trunk/rave-commons/src/main/java/org/apache/rave/service/LockService.java?view=markup

http://svn.apache.org/viewvc/incubator/rave/trunk/rave-commons/src/main/java/org/apache/rave/service/impl/DefaultLockService.java?view=markup

++ Unit tests showing demo usage

http://svn.apache.org/viewvc/incubator/rave/trunk/rave-commons/src/test/java/org/apache/rave/service/impl/DefaultLockServiceTest.java?view=markup

++ An annotation and aspect for annotating methods that should be synchronize 
using this strategy (which we'll probably try to contribute back to Spring at 
some point):

http://svn.apache.org/viewvc/incubator/rave/trunk/rave-commons/src/main/java/org/apache/rave/synchronization/annotation/Synchronized.java?view=markup

http://svn.apache.org/viewvc/incubator/rave/trunk/rave-commons/src/main/java/org/apache/rave/synchronization/SynchronizingAspect.java?view=markup

++ Sample usage (search for @Synchronized):

http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultRegionWidgetService.java?view=markup

>-----Original Message-----
>From: Ciancetta, Jesse E.
>Sent: Wednesday, September 14, 2011 11:11 AM
>To: shindig; [email protected]
>Subject: RE: osapi services and asychronous calls
>
>>We¹ve implemented our own userprefs osapi service (yes, we dumped the
>>whole
>>idea of sitting on top of appdata).  As I understand it the calls to our
>>service will be asynchronous.  Recently Dan Dumont made some changes to
>>the
>>common container layer to support a callback for GET_PREFERENCES so that
>>we
>>didn¹t try to render the gadget before the GET had completed.
>>
>>I need some help understanding the SET side of things.  A gadget could call
>>SET for each userpref in rapid succession.  It¹s possible 2 of these could
>>be handled simultaneously at the service layer (it¹s not only possible, we
>>are hitting it EVERYTIME with the horoscope gadget).  Thus it¹s possible we
>>could get a constraint violation on the database side (we are creating a
>>master record that references the userpref values).  Two values could try to
>>create the master record simultaneously.  Even if we flattened that out and
>>didn¹t do the master record, the gadget COULD still set the same value twice
>>in rapid succession and we¹d run into the same problem.
>>
>>So, it the right solution to return a 409 (conflict) from the service and
>>have our container userprefs layer retry?
>
>Huh -- while reading through your question and thinking through how I might
>solve it, I realized that I have this same exact problem in at least two 
>places!  :-
>)
>
>I think the way I'm planning to solve it is to introduce some intelligent
>synchronization.  So within Rave we have a method in our
>RegionWidgetService layer to save a RegionWidgetPreference which looks
>something like this:
>
>       public RegionWidgetPreference saveRegionWidgetPreference(long
>regionWidgetId, RegionWidgetPreference preference) {
>               //fetch the region widget from the database
>               //pull the preferences out of it and add or update the
>preference we were passed
>               //save the region widget with its updated preferences back to
>the database
>       }
>
>So I think my solution is going to look something like this:
>
>       public RegionWidgetPreference saveRegionWidgetPreference(long
>regionWidgetId, RegionWidgetPreference preference) {
>               //fetch a lock object for this RegionWidget instance using the
>regionWidgetId as a key (I'm looking at the java.util.concurrent.locks.Lock
>interface)
>               //lock on the lock object
>               //fetch the region widget from the database
>               //pull the preferences out of it and add or update the
>preference we were passed
>               //save the region widget with its updated preferences back to
>the database
>               //release the lock on the lock object
>       }
>
>Fetching/releasing the lock will be delegated off to a generic LockService
>which will have synchronized methods for fetching/releasing the locks -- this
>way the only synchronization overhead that *all* threads will incur is
>fetching/releasing the locks -- and the only time two (or more) threads will
>need to wait for each others database operations is if they are trying to set
>preferences for the same RegionWidget instance.
>
>I'll post a follow up when I have this implemented in Rave with pointers to the
>implementation for reference.
>
>> And doesn¹t this same issue exist
>>from gadgets who are calling appdata (or any osapi write service for that
>>matter)?  Should our services be trying to prevent this or only reporting
>>errors?  Is there some shindig construct that helps with this?
>
>I think all the code in Shindig that manipulates persistent data ends up doing
>so by delegating the actual data manipulation work off to an implementation
>of one of their SPI interfaces -- so I think it would be up to the implementer 
>of
>those interfaces to do something like what I've outlined above.
>
>>Your help is appreciated.
>>
>>Thanks,
>>Doug

Reply via email to