GoogleCloudPlatform/compute-appengine-demo-suite-python — pull request #9 by marcacohen (2013-08-29 18:41:44+00:00)
Title: Add caching of discovery document to avoid downloading on each request

Thanks for the suggestions, JoeG.

Not loving the periodic cron job as it adds complexity (need a transaction vs. race conditions) and if I ever really need a new version of the disc doc, I'll take up to an hour.

The memcache approach seems like a reasonably happy medium. Don't love the extra round trip but like that most of the time I won't pay for the download and if/when I do need a new version, I'll get it right away. Just added the memcaching to my app.

Marc

On Wed, Aug 28, 2013 at 6:58 PM, Joe Gregorio wrote:
Yeah, httplib2 can take a memcache instance, so that would avoid the time
to transfer the entire contents because it would know the etag, but that still requires
a round trip every time. If you wanted to be absolutely optimal I'd build a datastore
entry that held the latest discovery doc that was refreshed in a cron job every hour,
and use ndb so that the datastore was fronted with memcache.

Also realize that build_from_document can take either the raw JSON or the deserialized version
of the discovery doc, so you could actually store that in memcache and it wouldn't need
to be deserialized every time, presuming that pickle is faster that JSON loads().

http://google-api-python-client.googlecode.com/hg/docs/epy/apiclient.discovery-module.html#build_from_document

-joe

On Wed, Aug 28, 2013 at 7:56 PM, Marc Cohen wrote:
Sorry I missed the GAE wrinkle - I kept thinking about requests from the client but it makes sense that each status request that gets proxied through app engine triggers another costly call to build(). This makes me want to revert to checking in a copy of the current disc doc and building from a file (though that feels totally wrong). Any advice here, JoeG?
On Aug 28, 2013 4:46 PM, "Joe Beda" wrote:
+joe

I think we are talking past each other.

I agree with Joe -- the download of the discovery doc only happens when .build() is called.

However, .build() is typically (in a GAE app) called on every request to the GAE app. I know it is in the example app. With polling for GCE cluster status this happens pretty darn often.

Having an easy way to, say, cache the discovery doc in memcache or perhaps share the built API objects across requests would help this dramatically but that is more complicated and brings up questions around multi-threading (is the built API object thread safe?).

Joe

On Wed, Aug 28, 2013 at 4:40 PM, Marc Cohen wrote:
Per JoeG, sounds like I pay for the download only once. I'm still vulnerable to a potentially changing API (and I appreciate the value of locking down a demo :) but it sounds like I don't pay the disc doc download on every request, which was my main concern.

---------- Forwarded message ----------
From: Joe Gregorio
Date: Wed, Aug 28, 2013 at 4:37 PM
Subject: Re: question for you
To: Marc Cohen

Yes, it only downloads it on build(), not for every call.

On Wed, Aug 28, 2013 at 7:15 PM, Marc Cohen wrote:
Joe Beda claims the Google python client lib downloads the discovery doc *on every request*.

He was using discovery.build_from_document() with a local copy of the compute engine discovery doc to get around this problem. I'm assuming that I can use discovery.build() as a replacement for build_from_doument(), to dynamically download the discovery doc (once), and that won't result in a new disc doc download on every subsequent request. Can you confirm?

--
Marc Cohen
marccohen@google.com
http://about.me/marc1