In a previous article I wrote about the need to update your Datastore indexes on App Engine before deploying code that relies on them. To simplify the deployment process, I put together a script that waits for your indexes to be built before deploying new code.
#!/usr/bin/env python
# Need to import and fix the sys path before importing other things.
import remote_api_shell
remote_api_shell.fix_sys_path()
import time
from google.appengine.api import datastore_admin
from google.appengine.ext.remote_api import remote_api_stub
from google.appengine.tools import appengine_rpc
APP_ID = 'your-app-id'
def configure_remote_api():
def auth_func():
return ('your.email@gmail.com', 'your.application.specific.password')
remote_api_stub.ConfigureRemoteApi(
APP_ID, '/_ah/remote_api', auth_func,
servername='%s.appspot.com' % APP_ID,
save_cookies=True, secure=False,
rpc_server_factory=appengine_rpc.HttpRpcServer)
remote_api_stub.MaybeInvokeAuthentication()
def main():
print 'Checking indexes...'
configure_remote_api()
interval = 10 # seconds.
building = True
while building:
# Start with a fresh run: maybe we're done building?
building = False
for index in datastore_admin.GetIndices('s~%s' % APP_ID):
# If any single index is building, we're not done.
# Sleep for a bit and then this cycle should repeat.
if not index.has_state() or index.state() != index.READ_WRITE:
building = True
print 'Indexes are still building... Waiting %s seconds.' % interval
time.sleep(interval)
break
print 'All indexes are up to date.'
if __name__ == '__main__':
main()
Since this script will “block” until all indexes are built and ready, you can add this line to your deployment script, which should look something like...
$ appcfg.py update_indexes .
$ ./wait_for_indexes.py # (The script above...)
$ appcfg.py update .