From 405c8456a92230e5fcd7652c0ad7ca54df3abf54 Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Wed, 13 Apr 2016 17:21:40 -0700 Subject: [PATCH] Add Background Sample --- appengine/background/README.md | 9 ++++ appengine/background/app.yaml | 10 ++++ appengine/background/main.py | 85 +++++++++++++++++++++++++++++++ appengine/background/main_test.py | 53 +++++++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 appengine/background/README.md create mode 100644 appengine/background/app.yaml create mode 100644 appengine/background/main.py create mode 100644 appengine/background/main_test.py diff --git a/appengine/background/README.md b/appengine/background/README.md new file mode 100644 index 000000000000..10d1cd0e77ab --- /dev/null +++ b/appengine/background/README.md @@ -0,0 +1,9 @@ +# Using Background Threads from Google App Engine + +This example shows how to use manual or basic scaling to start App Engine background threads. + +See the [documentation on modules](https://cloud.google.com/appengine/docs/python/modules/) for +more information. + +Your app.yaml configuration must specify scaling as either manual or basic. The default +automatic scaling does not allow background threads. diff --git a/appengine/background/app.yaml b/appengine/background/app.yaml new file mode 100644 index 000000000000..57cdb0bf57c3 --- /dev/null +++ b/appengine/background/app.yaml @@ -0,0 +1,10 @@ +runtime: python27 +api_version: 1 +threadsafe: yes + +manual_scaling: + instances: 1 + +handlers: +- url: .* + script: main.app diff --git a/appengine/background/main.py b/appengine/background/main.py new file mode 100644 index 000000000000..1709d4a962bb --- /dev/null +++ b/appengine/background/main.py @@ -0,0 +1,85 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Sample application that demonstrates how to use the App Engine background +threads. + +app.yaml scaling must be set to manual or basic. +""" + +# [START background-imp] +from google.appengine.api import background_thread +# [END background-imp] + +import webapp2 + +val = 'Dog' + + +class MainHandler(webapp2.RequestHandler): + def get(self): + self.response.headers['Content-Type'] = 'text/plain' + self.response.write(str(val)) + + +class SetDogHandler(webapp2.RequestHandler): + """ Resets the global val to 'Dog'""" + + def get(self): + global val + val = 'Dog' + self.response.headers['Content-Type'] = 'text/plain' + self.response.write('Done') + + +class SetCatBackgroundHandler(webapp2.RequestHandler): + """ Demonstrates two ways to start new background threads + """ + + def get(self): + """ + Demonstrates using a background thread to change the global + val from 'Dog' to 'Cat' + + The auto GET parameter determines whether to start the thread + automatically or manually + """ + auto = self.request.get('auto') + + # [START background-start] + # sample function to run in a background thread + def change_val(arg): + global val + val = arg + + if auto: + # Start the new thread in one command + background_thread.start_new_background_thread(change_val, ['Cat']) + else: + # create a new thread and start it + t = background_thread.BackgroundThread( + target=change_val, args=['Cat']) + t.start() + # [END background-start] + + self.response.headers['Content-Type'] = 'text/plain' + self.response.write('Done') + +app = webapp2.WSGIApplication([ + ('/', MainHandler), + ('/dog', SetDogHandler), + ('/cat', SetCatBackgroundHandler), +], debug=True) +# [END all] diff --git a/appengine/background/main_test.py b/appengine/background/main_test.py new file mode 100644 index 000000000000..55cf5bfe47f4 --- /dev/null +++ b/appengine/background/main_test.py @@ -0,0 +1,53 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import main + +from mock import patch +import pytest +import webtest + + +@pytest.fixture +def app(cloud_config, testbed): + main.PROJECTID = cloud_config.project + return webtest.TestApp(main.app) + + +@patch("main.background_thread") +def test_background(thread, app): + app.get('/dog') + response = app.get('/') + assert response.status_int == 200 + assert response.body == 'Dog' + app.get('/cat') + # no stub for system so manually set + main.val = 'Cat' + response = app.get('/') + assert response.status_int == 200 + assert response.body == 'Cat' + + +@patch("main.background_thread") +def test_background_auto_start(thread, app): + app.get('/dog') + response = app.get('/') + assert response.status_int == 200 + assert response.body == 'Dog' + app.get('/cat?auto=True') + # no stub for system so manually set + main.val = 'Cat' + response = app.get('/') + assert response.status_int == 200 + assert response.body == 'Cat'