[appengine-java] Re: Storing query results in memcache

2011-09-29 Thread Ian Marshall
Hi Cristian,

If I am correct (and I could be wrong), you want to update more than
one entity group in the datastore by performing a set of sequential
writes to the datastore. You may then want to read from the datastore.
The writes and subsequent read are to be delayed so that the datastore
write/read will take into account the already-written data.

If I am right in my interpretation of what you ask, memcache is not a
guaranteed data store, in that data can be deleted from it by the GAE
framework at any time.

I personally create queued tasks to perform sequential writes to the
datastore to the same entity group. I set the interval between
successive writes to be long enough for the HRD to cope correctly.
Queued tasks do not get deleted, and act as my delayed datastore write
queue.

Does this help you?

Ian


On Sep 28, 5:27 pm, "nicanor.babula"  wrote:
> Hi,
>
>   I just moved my app to HRD and I am trying to use the memcache to overcome
> the eventual consistency problem.. When it comes to get-by-id queries the
> solution is very simple. The problem appears when I insert an entity and I
> want to appear in the results of more complex queries.
> Because using entity groups is not the answer in certain situations I had to
> use some sort of foreign keys..
> So far I thought of a system that gets an unique id from the query based on
> its FilterPredicates (eg: "MEMCACHE_PHONE_NUMBERS_contactId_12345") and then
> uses that to update or read the entities from there. I would build this
> system by doing my own implementation of the DatastoreService interface and
> attach the memcache management on the various put/delete/get methods.
> I don't want to reinvent the wheel. Is there anything already done that I
> could use?
>
> If anybody has any suggestions feel free to enlighten me ;)
>
> Thanks,
> Cristian.

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



[appengine-java] Re: Storing query results in memcache

2011-09-29 Thread nicanor.babula
Hi Ian,

Thanks for sharing your strategy.. I am not sure if I understand exactly how 
could I use your system to solve my problem. Actually, the memcache concept 
is working nice solving similar, but simpler situations. I think I explained 
poorly my situation. Here it is:

An application manages contacts. It actually has thousands of them. On the 
GUI side we have a listview, an editview and a createview. The list view has 
4 columns, and is paged (30 records per page) and by default is sorted 
ascending by the first column. I can search the listview by issuing queries 
serverside (I want the results always ordered and paged accordingly). 
Now, a user clicks on "new contact". The application goes into createView. 
Data input then save. Application goes to list view. The contact should have 
been in the first page, but it isn't. After a few seconds, it appears. 

The previous example with phone numbers is kind of the same issue, but with 
simpler queries:
User modifies a contact by adding some phone numbers. Hits save and goes to 
list view, then he remembers that one number was wrong and goes back to 
editing the same contact. The phone numbers inserted seconds ago aren't 
there. In this case, (since for other reasons I the phone numbers entities 
cannot be children of the contact entity) every phone number entity has a 
property called "contactId" that points to the father contact. The solution 
employed in this simple case is storing in the memcache the phone numbers by 
using contact-based keys so that for example
[code]
memcache.get("MEMCACHE_phones_contactId_1234")
[/code]
would give me an all the phone numbers for contact having id=1234. Somehow 
(too long and boring to explain how) I manage to keep this array always up 
to date so when the user returns lightning-fast to the editview the newly 
inserted phone number are there, only that they are read from the memcache. 
Analogically, how could this be done for the fore-mentioned listview 
situation, where the query is much more complex?

Hope I didn't confused you more..

Thanks,
Cristian

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/google-appengine-java/-/3kOA7GAMTQUJ.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



[appengine-java] Re: Storing query results in memcache

2011-09-29 Thread Nichole
use the level 2 cache?



"Objects are placed in the L2 cache when you commit() the transaction
of a PersistenceManager. This means that you only have datastore-
persisted objects in that cache. Also, if an object is deleted during
a transaction then at commit it will be removed from the L2 cache if
it is present."

http://www.datanucleus.org/products/accessplatform/jdo/cache.html#level2


On Sep 29, 3:59 am, "nicanor.babula"  wrote:
> Hi Ian,
>
> Thanks for sharing your strategy.. I am not sure if I understand exactly how
> could I use your system to solve my problem. Actually, the memcache concept
> is working nice solving similar, but simpler situations. I think I explained
> poorly my situation. Here it is:
>
> An application manages contacts. It actually has thousands of them. On the
> GUI side we have a listview, an editview and a createview. The list view has
> 4 columns, and is paged (30 records per page) and by default is sorted
> ascending by the first column. I can search the listview by issuing queries
> serverside (I want the results always ordered and paged accordingly).
> Now, a user clicks on "new contact". The application goes into createView.
> Data input then save. Application goes to list view. The contact should have
> been in the first page, but it isn't. After a few seconds, it appears.
>
> The previous example with phone numbers is kind of the same issue, but with
> simpler queries:
> User modifies a contact by adding some phone numbers. Hits save and goes to
> list view, then he remembers that one number was wrong and goes back to
> editing the same contact. The phone numbers inserted seconds ago aren't
> there. In this case, (since for other reasons I the phone numbers entities
> cannot be children of the contact entity) every phone number entity has a
> property called "contactId" that points to the father contact. The solution
> employed in this simple case is storing in the memcache the phone numbers by
> using contact-based keys so that for example
> [code]
> memcache.get("MEMCACHE_phones_contactId_1234")
> [/code]
> would give me an all the phone numbers for contact having id=1234. Somehow
> (too long and boring to explain how) I manage to keep this array always up
> to date so when the user returns lightning-fast to the editview the newly
> inserted phone number are there, only that they are read from the memcache.
> Analogically, how could this be done for the fore-mentioned listview
> situation, where the query is much more complex?
>
> Hope I didn't confused you more..
>
> Thanks,
> Cristian

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



[appengine-java] Re: Storing query results in memcache

2011-09-30 Thread Ian Marshall
Hi Christian,

If Nichole's tip doesn't help you, then for your list view, you could
back it up with an array (in memcache?). Upon any create, edit, delete
operation, you will have to test the relevant entity (using logic
equivalent to your query) to see whether its entry in the array should
be added, edited or removed.

You would have to think about whether you want subsequent updates by
other users or your system should be reflected at once or if a
snapshot at first list view would suffice.

(Note that for postings to this group, there is a delay of a few tens
of seconds before a new post is visible in the list. That is OK for a
technical forum, but I see that this is unacceptable for your app.)

Good luck!

Ian


On Sep 30, 7:49 am, Nichole  wrote:
> use the level 2 cache?
>
> 
>
> "Objects are placed in the L2 cache when you commit() the transaction
> of a PersistenceManager. This means that you only have datastore-
> persisted objects in that cache. Also, if an object is deleted during
> a transaction then at commit it will be removed from the L2 cache if
> it is present."
>
> http://www.datanucleus.org/products/accessplatform/jdo/cache.html#level2
>
> On Sep 29, 3:59 am, "nicanor.babula"  wrote:
>
>
>
>
>
>
>
> > Hi Ian,
>
> > Thanks for sharing your strategy.. I am not sure if I understand exactly how
> > could I use your system to solve my problem. Actually, the memcache concept
> > is working nice solving similar, but simpler situations. I think I explained
> > poorly my situation. Here it is:
>
> > An application manages contacts. It actually has thousands of them. On the
> > GUI side we have a listview, an editview and a createview. The list view has
> > 4 columns, and is paged (30 records per page) and by default is sorted
> > ascending by the first column. I can search the listview by issuing queries
> > serverside (I want the results always ordered and paged accordingly).
> > Now, a user clicks on "new contact". The application goes into createView.
> > Data input then save. Application goes to list view. The contact should have
> > been in the first page, but it isn't. After a few seconds, it appears.
>
> > The previous example with phone numbers is kind of the same issue, but with
> > simpler queries:
> > User modifies a contact by adding some phone numbers. Hits save and goes to
> > list view, then he remembers that one number was wrong and goes back to
> > editing the same contact. The phone numbers inserted seconds ago aren't
> > there. In this case, (since for other reasons I the phone numbers entities
> > cannot be children of the contact entity) every phone number entity has a
> > property called "contactId" that points to the father contact. The solution
> > employed in this simple case is storing in the memcache the phone numbers by
> > using contact-based keys so that for example
> > [code]
> > memcache.get("MEMCACHE_phones_contactId_1234")
> > [/code]
> > would give me an all the phone numbers for contact having id=1234. Somehow
> > (too long and boring to explain how) I manage to keep this array always up
> > to date so when the user returns lightning-fast to the editview the newly
> > inserted phone number are there, only that they are read from the memcache.
> > Analogically, how could this be done for the fore-mentioned listview
> > situation, where the query is much more complex?
>
> > Hope I didn't confused you more..
>
> > Thanks,
> > Cristian

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



[appengine-java] Re: Storing query results in memcache

2011-10-03 Thread nicanor.babula
Thanks for your help. I'll go with Ian's suggestion, storing arrays in the 
memcache.

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/google-appengine-java/-/8R5rRrRrb00J.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



[appengine-java] Re: Storing query results in memcache

2011-10-04 Thread Nichole
Level2 cache might be what you want, but anyway, just to add to the
dialog, I tinkered
with what's available in datanucleus-core v1.1.5.
Choices in datanucleus are: none, soft, and weak
(jcache is not available in any version, but see below for
customization)

In addition to those, one can make a class that implements
Level2Cache
by adopting the connectors that you see in the src code for
WeakLevel2Cache.java.
If implementing your own Level2Cache, you can, for example, use
Google's MapMaker in
Guava for finer control of expiration:
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html
If you pursue a custom implementation, you'll have to edit
datanucleus-core-1.1.5.jar's plugin.xml to add the new class and name
for it.
http://www.datanucleus.org/extensions/level2_cache.html
 
http://grepcode.com/file_/repo1.maven.org/maven2/org.datanucleus/datanucleus-core/1.1.5/org/datanucleus/cache/WeakLevel2Cache.java/?v=source

Here's a quick check I used in development and production to assert
that the
level2 cache works in appengine (presumably by container, and not yet
distributed, not sure...)

/*
 * Level 1 Cache - caching of instances within a
PersistenceManager
 * Level 2 Cache - caching of instances within all
PersistenceManagers of a PersistenceManagerFactory,
 */
/*
 * Add this to jdoconfig.xml or change yours for the level2
entries:
 *
 *  










 */

PersistenceManagerFactory pmf = null;
PersistenceManager pm = null;
Transaction tx = null;
Event event1 = null;

try {
pmf = JDOHelper.getPersistenceManagerFactory("l2cache");
pm = pmf.getPersistenceManager();
tx = pm.currentTransaction();

DataStoreCache l2Cache = pmf.getDataStoreCache();
l2Cache.pinAll(true, Event.class);

tx.begin();

event1 = createEvent1();

pm.makePersistent(event1);

tx.commit();
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace(out);
} finally {
if (tx.isActive()) {
tx.rollback();
}
if (pm != null) {
pm.close();
}
log.info("wrote 1 event to PM");
}

Level2Cache l2Cache =
((JDODataStoreCache)pmf.getDataStoreCache()).getLevel2Cache();

int nObjectsInCache = l2Cache.getSize();
int nPinnedObjects = l2Cache.getNumberOfPinnedObjects();
int nUnpinnedObjects = l2Cache.getNumberOfUnpinnedObjects();

log.info("tx is closed:");
log.info("number of objects in Level2Cache is " +
nObjectsInCache);
log.info("number of pinned objects in Level2Cache is " +
nPinnedObjects);
log.info("number of unpinned objects in Level2Cache is " +
nUnpinnedObjects);

l2Cache.evictAll();

nObjectsInCache = l2Cache.getSize();
nPinnedObjects = l2Cache.getNumberOfPinnedObjects();
nUnpinnedObjects = l2Cache.getNumberOfUnpinnedObjects();

log.info("number of objects in Level2Cache is " +
nObjectsInCache);
log.info("number of pinned objects in Level2Cache is " +
nPinnedObjects);
log.info("number of unpinned objects in Level2Cache is " +
nUnpinnedObjects);

On Oct 3, 5:14 am, "nicanor.babula"  wrote:
> Thanks for your help. I'll go with Ian's suggestion, storing arrays in the
> memcache.

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.