SlideShare a Scribd company logo
1 of 34
Download to read offline
Building TweetEngine


                                  Ikai Lan
Developer Relations, Google App Engine
                      ikai.l@google.com
                            Twitter: @ikai
Goals of this talk

                     Using TweetEngine to
                     explain key concepts of
                     building cloud applications
                     Explaining App Engine as
                     a development
                     environment
                     Whet your appetite!
What is App Engine?




     App Engine is a platform

     You build & test your app

     Then upload your app to Google

     App Engine runs everything

     No need to worry about machines,
     network, storage, scalability, etc.
The king of ease-of-use




                   Extremely rapid development
                   Very low barrier of entry
                   Simple yet robust syntax
                   Rich library of
                   packages/modules
                   App Engine's first language API
Components
Getting TweetEngine




Application: http://tweetengine.net/

Code: http://github.com/Arachnid/tweetengine

Prerequisites:
   Python 2.5
   buildout
   lxml (for i18n features)
OAuth
                                        Secure method for granting
                                        permissions to third-party
                                        integrations
                                        Allows sites to use a trusted
                                        identity provider (Google,
                                        Twitter)
                                        "Valet key" for the internet




Image and "valet key" source: (http://hueniverse.com/oauth/guide/intro/)
Standard OAuth flow (User)
What does the User see?

1. Link to login with Twitter
2. User is redirected to an http:
   //twitter.com URL
3. User logs in, grants access
4. User is redirected back to site
Standard OAuth flow (Server)
What does the server do?

1. Acquire request token
2. Generate login URL
3. Redirect or link user to this
   URL
4. After user has logged in,
   Twitter will redirect to a
   callback URL on server
5. Server saves token passed to
   callback URL
TweetEngine + OAuth

 OAuth request token saved in TwitterAccount model
 Saved per Twitter Account
 oauth.py handles signing
 apis.py handles proxied Twitter API calls
Logging in to Twitter using OAuth
   # src/tweetengine/add.py
   auth_token =
     self.request.get("oauth_token")
   auth_verifier =
     self.request.get("oauth_verifier")
   user_info = client.get_user_info(auth_token,
             auth_verifier=auth_verifier)

   # Create the twitter account account = model.TwitterAccount.
   get_or_insert(
     user_info["username"],
     oauth_token=user_info["token"],
     oauth_secret=user_info["secret"],
     name=user_info["name"],
     picture=user_info["picture"])
Initializing an OAuth client

# src/oauth.py

OAuthClient.__init__(self, "twitter", consumer_key,
 consumer_secret,
 "http://twitter.com/oauth/request_token",
 "http://twitter.com/oauth/access_token",
 callback_url)
Twitter API calls
  - Web handlers user AJAX
  - Backend calls go to TwitterApiHandler
  # src/tweetengine/handlers/apis.py
  for k,v in params.items():
    if isinstance(v, unicode):
        params[k] = v.encode('utf8')

   # Join all of the params together.
   params_str = "&".join(["%s=%s" % (encode(k), encode(params[k]))

  for k in sorted(params)])
    # Join the entire message together per the OAuth specification.
    message = "&".join(["GET" if method == urlfetch.GET else "POST", encode(url),
       encode(params_str)])

  # Create a HMAC-SHA1 signature of the message.
  key = "%s&%s" % (self.consumer_secret, secret)
  # Note compulsory "&".
  signature = hmac(key, message, sha1)
  digest_base64 = signature.digest().encode("base64").strip()
  params["oauth_signature"] = digest_base64 return urlencode(params)
OAuth

 The "de facto" standard for authentication on the web
 against a third party API
 TweetEngine's support can be easily generalized to be used
 on any OAuth supporting site
 Highly recommend: New sites, do not build identity system,
 use OAuth or OpenID
i18n - internationalization
  Problem: maintaining
  localized versions
  Localization is more than
  translations
  TweetEngine already
  supports English, German
  and Italian!



                              Image source: http://www.flickr.
                              com/photos/natematias/22132919
Workflow


1.   Developer marks strings as requiring translation
2.   Translators work on .PO files
3.   These are compiled into efficient .POT files
4.   At runtime, translations are looked up when pages rendered
     using "Accepts-Header"
What does a .po file look like?

#. Default: "Collaborative tweeting"
#: tweetengine/templates/base.pt:36
msgid "subline"
msgstr "Tweeting collaborativo"

#. Default: "Welcome!"
#: tweetengine/templates/index.pt:3
msgid "title-welcome"
msgstr "Benvenuto!"
Sample template code

tweetengine/templates/index.pt:

<metal:title fill-slot="title" i18n:translate="title-welcome">Welcome!</metal:title>

tweetengine/templates/base.pt:
<h2><a href="/" i18n:translate="subline">Collaborative tweeting</a></h2>

Run from TweetEngine root: bin/i18nize
src/tweetengine/handlers/base.py
 # Instantiate Chameleon template loader
from chameleon.zpt.loader import TemplateLoader
from tweetengine import model
from tweetengine.menu import mainmenu

tpl_path = os.path.join(os.path.dirname(__file__), "..", "templates")
tpl_loader = TemplateLoader(tpl_path)

# Later on in the file
template_vars['target_language'] = self.request.headers.get('Accept-Language', None)
tpl = tpl_loader.load('base.pt')
template_vars['master'] = tpl.macros['master']
tpl = tpl_loader.load('macros.pt')
template_vars['macros'] = tpl.macros
tpl = tpl_loader.load(template_file)
self.response.out.write(tpl(**template_vars))
Remember: i18n > translations

  Resizing UI elements for languages with long/short words
  Right-to-left languages (Hebrew, Arabic) and layouts
  Time and date formats
  Metric/English system
  Much more ... this just a place to start!
App Engine is also about tooling




   Image source: http://www.flickr.com/photos/sparr0/4584964212/
Two App Engine tools
 AppStats                                                       Task Queues
    Application profile that is                                    Background queueing
    App Engine aware                                               and worker mechanism




Image source: http://www.flickr.com/photos/spbatt/3928384579/
AppStats
           Track expensive requests
           Expose bottlenecks in your
           code
           Show you what code is
           being executed the most
           for "hotspot optimization"
           Run in production with
           minimal overhead
AppStats example
AppStats example (con't)
How does it work?
 Uses Call Hooks
    pre‐call hook records start .me, request, stack
    post‐call hook records end .me, mcycles, response
 Measuring times:
    real time using Python’s wall clock API
    API megacycles using rpc.cpu_usage_mcycles
    CPU megacycles using quota.get_request_cpu_usage()
 Get stack contents from Python’s sys._getframe()
 Recording accumulates in memory object
 Written to memcache at end of each request
AppStats for TweetEngine
  Add AppStats as WSGI Middleware:
app = recording.appstats_wsgi_middleware(app)
  Add AppStats GUI to URL mapping (app.yaml):
- url: /stats.*
  script: appstats/ui.py

 Dev: http://localhost:8080/stats
 Prod (as admin): http://APPID.appspot.com/stats


                     That's it!
Task Queues

 Execute background tasks
 Throttle control
 ETA
 Can be unique!
 Invoked using a web handler
Standard async worker architecture
Task Queues in App Engine
 # Creating a task # src/tweetengine/model.py taskqueue.Task
 (eta=send_time, name=task_name, url=twitter.
 ScheduledTweetHandler.URL_PATH).add()

 # Task Handler
 # src/tweetengine/handlers/twitter.py
 class ScheduledTweetHandler(webapp.RequestHandler):

  def post(self):
   publishApprovedTweets()

  def publishApprovedTweets():
   # Iterate through unsent OutgoingTweets and send them
Task Queues in TweetEngine

 Used to schedule Tweets
 ETA parameter used to set an approximate execution time
 Tasks are named - this allows us to set times to check for
 OutgoingTweets that should be sent at this time and not
 duplicate work (we don't have to use cron)
Task Queues

 Allow developers to build asynchronous workers without
 hassle of building out queueing/polling system
 Handles task uniqueness and transactional task creation
 Can be scheduled, throttled
Summary: TweetEngine technologies

1. OAuth - "Valet key" for internet applications
2. i18n - Using templates and message bundles in web
   applications
3. AppStats - App Engine request profiling toolkit
4. Task Queues - Background work for App Engine
   applications
Questions?




Application: http://tweetengine.net/

Code: http://github.com/Arachnid/tweetengine

ikai.l@google.com
Twitter: @ikai

More Related Content

What's hot

Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)Mikkel Flindt Heisterberg
 
Social Connections VI Prague - An introduction to ibm connections as an appde...
Social Connections VI Prague - An introduction to ibm connections as an appde...Social Connections VI Prague - An introduction to ibm connections as an appde...
Social Connections VI Prague - An introduction to ibm connections as an appde...Mikkel Flindt Heisterberg
 
Microsoft identity platform community call-May 2020
Microsoft identity platform community call-May 2020Microsoft identity platform community call-May 2020
Microsoft identity platform community call-May 2020Microsoft 365 Developer
 
Talk 1: Google App Engine Development: Java, Data Models, and other things yo...
Talk 1: Google App Engine Development: Java, Data Models, and other things yo...Talk 1: Google App Engine Development: Java, Data Models, and other things yo...
Talk 1: Google App Engine Development: Java, Data Models, and other things yo...Singapore Google Technology User Group
 
Paul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncPaul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncmdevtalk
 
Plug in development
Plug in developmentPlug in development
Plug in developmentLucky Ali
 

What's hot (6)

Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)
 
Social Connections VI Prague - An introduction to ibm connections as an appde...
Social Connections VI Prague - An introduction to ibm connections as an appde...Social Connections VI Prague - An introduction to ibm connections as an appde...
Social Connections VI Prague - An introduction to ibm connections as an appde...
 
Microsoft identity platform community call-May 2020
Microsoft identity platform community call-May 2020Microsoft identity platform community call-May 2020
Microsoft identity platform community call-May 2020
 
Talk 1: Google App Engine Development: Java, Data Models, and other things yo...
Talk 1: Google App Engine Development: Java, Data Models, and other things yo...Talk 1: Google App Engine Development: Java, Data Models, and other things yo...
Talk 1: Google App Engine Development: Java, Data Models, and other things yo...
 
Paul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncPaul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & sync
 
Plug in development
Plug in developmentPlug in development
Plug in development
 

Viewers also liked

Your language doesn't scale
Your language doesn't scaleYour language doesn't scale
Your language doesn't scaleikailan
 
2011 august-gdd-mexico-city-rest-json-oauth
2011 august-gdd-mexico-city-rest-json-oauth2011 august-gdd-mexico-city-rest-json-oauth
2011 august-gdd-mexico-city-rest-json-oauthikailan
 
プログラミング言語に関する学生へのアンケート
プログラミング言語に関する学生へのアンケートプログラミング言語に関する学生へのアンケート
プログラミング言語に関する学生へのアンケートHiroto Yamakawa
 
Boot camp 2010_app_engine_101
Boot camp 2010_app_engine_101Boot camp 2010_app_engine_101
Boot camp 2010_app_engine_101ikailan
 
From 0-1 billion in 46 days
From 0-1 billion in 46 daysFrom 0-1 billion in 46 days
From 0-1 billion in 46 daysikailan
 
Intro to App Engine - Agency Dev Day NYC 2011
Intro to App Engine - Agency Dev Day NYC 2011Intro to App Engine - Agency Dev Day NYC 2011
Intro to App Engine - Agency Dev Day NYC 2011ikailan
 
Eme4401 Digautobio
Eme4401 DigautobioEme4401 Digautobio
Eme4401 DigautobioStef2
 
札幌のJavaコミュニティ Java Doを立ち上げた話
札幌のJavaコミュニティ Java Doを立ち上げた話札幌のJavaコミュニティ Java Doを立ち上げた話
札幌のJavaコミュニティ Java Doを立ち上げた話Hiroto Yamakawa
 
2011 june-kuala-lumpur-gtug-hackathon
2011 june-kuala-lumpur-gtug-hackathon2011 june-kuala-lumpur-gtug-hackathon
2011 june-kuala-lumpur-gtug-hackathonikailan
 

Viewers also liked (9)

Your language doesn't scale
Your language doesn't scaleYour language doesn't scale
Your language doesn't scale
 
2011 august-gdd-mexico-city-rest-json-oauth
2011 august-gdd-mexico-city-rest-json-oauth2011 august-gdd-mexico-city-rest-json-oauth
2011 august-gdd-mexico-city-rest-json-oauth
 
プログラミング言語に関する学生へのアンケート
プログラミング言語に関する学生へのアンケートプログラミング言語に関する学生へのアンケート
プログラミング言語に関する学生へのアンケート
 
Boot camp 2010_app_engine_101
Boot camp 2010_app_engine_101Boot camp 2010_app_engine_101
Boot camp 2010_app_engine_101
 
From 0-1 billion in 46 days
From 0-1 billion in 46 daysFrom 0-1 billion in 46 days
From 0-1 billion in 46 days
 
Intro to App Engine - Agency Dev Day NYC 2011
Intro to App Engine - Agency Dev Day NYC 2011Intro to App Engine - Agency Dev Day NYC 2011
Intro to App Engine - Agency Dev Day NYC 2011
 
Eme4401 Digautobio
Eme4401 DigautobioEme4401 Digautobio
Eme4401 Digautobio
 
札幌のJavaコミュニティ Java Doを立ち上げた話
札幌のJavaコミュニティ Java Doを立ち上げた話札幌のJavaコミュニティ Java Doを立ち上げた話
札幌のJavaコミュニティ Java Doを立ち上げた話
 
2011 june-kuala-lumpur-gtug-hackathon
2011 june-kuala-lumpur-gtug-hackathon2011 june-kuala-lumpur-gtug-hackathon
2011 june-kuala-lumpur-gtug-hackathon
 

Similar to Building TweetEngine

Building Push Triggers for Logic Apps
Building Push Triggers for Logic AppsBuilding Push Triggers for Logic Apps
Building Push Triggers for Logic AppsBizTalk360
 
Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...Antonio Peric-Mazar
 
How to Build Your First Web App in Go
How to Build Your First Web App in GoHow to Build Your First Web App in Go
How to Build Your First Web App in GoAll Things Open
 
App engine devfest_mexico_10
App engine devfest_mexico_10App engine devfest_mexico_10
App engine devfest_mexico_10Chris Schalk
 
API Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsAPI Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsTom Johnson
 
Using API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonyconUsing API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonyconAntonio Peric-Mazar
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Matt Raible
 
Training thethings.iO
Training thethings.iOTraining thethings.iO
Training thethings.iOMarc Pous
 
Empower every Azure Function to achieve more!!
Empower every Azure Function to achieve more!!Empower every Azure Function to achieve more!!
Empower every Azure Function to achieve more!!Massimo Bonanni
 
SgCodeJam24 Workshop Extract
SgCodeJam24 Workshop ExtractSgCodeJam24 Workshop Extract
SgCodeJam24 Workshop Extractremko caprio
 
Development of Twitter Application #3 - OAuth
Development of Twitter Application #3 - OAuthDevelopment of Twitter Application #3 - OAuth
Development of Twitter Application #3 - OAuthMyungjin Lee
 
Using HttpWatch Plug-in with Selenium Automation in Java
Using HttpWatch Plug-in with Selenium Automation in JavaUsing HttpWatch Plug-in with Selenium Automation in Java
Using HttpWatch Plug-in with Selenium Automation in JavaSandeep Tol
 
Developing Java Web Applications In Google App Engine
Developing Java Web Applications In Google App EngineDeveloping Java Web Applications In Google App Engine
Developing Java Web Applications In Google App EngineTahir Akram
 
Extending Appcelerator Titanium Mobile through Native Modules
Extending Appcelerator Titanium Mobile through Native ModulesExtending Appcelerator Titanium Mobile through Native Modules
Extending Appcelerator Titanium Mobile through Native Modulesomorandi
 
Use Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEUse Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEBenjamin Cabé
 
Let's build Developer Portal with Backstage
Let's build Developer Portal with BackstageLet's build Developer Portal with Backstage
Let's build Developer Portal with BackstageOpsta
 

Similar to Building TweetEngine (20)

Building Push Triggers for Logic Apps
Building Push Triggers for Logic AppsBuilding Push Triggers for Logic Apps
Building Push Triggers for Logic Apps
 
Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...
 
How to Build Your First Web App in Go
How to Build Your First Web App in GoHow to Build Your First Web App in Go
How to Build Your First Web App in Go
 
App engine devfest_mexico_10
App engine devfest_mexico_10App engine devfest_mexico_10
App engine devfest_mexico_10
 
Codeigniter
CodeigniterCodeigniter
Codeigniter
 
flask.pptx
flask.pptxflask.pptx
flask.pptx
 
API Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsAPI Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIs
 
Using API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonyconUsing API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonycon
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017
 
Introduction to Google App Engine
Introduction to Google App EngineIntroduction to Google App Engine
Introduction to Google App Engine
 
Training thethings.iO
Training thethings.iOTraining thethings.iO
Training thethings.iO
 
Empower every Azure Function to achieve more!!
Empower every Azure Function to achieve more!!Empower every Azure Function to achieve more!!
Empower every Azure Function to achieve more!!
 
Google Cloud Enpoints
Google Cloud EnpointsGoogle Cloud Enpoints
Google Cloud Enpoints
 
SgCodeJam24 Workshop Extract
SgCodeJam24 Workshop ExtractSgCodeJam24 Workshop Extract
SgCodeJam24 Workshop Extract
 
Development of Twitter Application #3 - OAuth
Development of Twitter Application #3 - OAuthDevelopment of Twitter Application #3 - OAuth
Development of Twitter Application #3 - OAuth
 
Using HttpWatch Plug-in with Selenium Automation in Java
Using HttpWatch Plug-in with Selenium Automation in JavaUsing HttpWatch Plug-in with Selenium Automation in Java
Using HttpWatch Plug-in with Selenium Automation in Java
 
Developing Java Web Applications In Google App Engine
Developing Java Web Applications In Google App EngineDeveloping Java Web Applications In Google App Engine
Developing Java Web Applications In Google App Engine
 
Extending Appcelerator Titanium Mobile through Native Modules
Extending Appcelerator Titanium Mobile through Native ModulesExtending Appcelerator Titanium Mobile through Native Modules
Extending Appcelerator Titanium Mobile through Native Modules
 
Use Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEUse Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDE
 
Let's build Developer Portal with Backstage
Let's build Developer Portal with BackstageLet's build Developer Portal with Backstage
Let's build Developer Portal with Backstage
 

More from ikailan

2011 aug-gdd-mexico-city-high-replication-datastore
2011 aug-gdd-mexico-city-high-replication-datastore2011 aug-gdd-mexico-city-high-replication-datastore
2011 aug-gdd-mexico-city-high-replication-datastoreikailan
 
2011 july-nyc-gtug-go
2011 july-nyc-gtug-go2011 july-nyc-gtug-go
2011 july-nyc-gtug-goikailan
 
2011 july-gtug-high-replication-datastore
2011 july-gtug-high-replication-datastore2011 july-gtug-high-replication-datastore
2011 july-gtug-high-replication-datastoreikailan
 
2011 June - Singapore GTUG presentation. App Engine program update + intro to Go
2011 June - Singapore GTUG presentation. App Engine program update + intro to Go2011 June - Singapore GTUG presentation. App Engine program update + intro to Go
2011 June - Singapore GTUG presentation. App Engine program update + intro to Goikailan
 
Rapid web development using tornado web and mongodb
Rapid web development using tornado web and mongodbRapid web development using tornado web and mongodb
Rapid web development using tornado web and mongodbikailan
 
Introducing the App Engine datastore
Introducing the App Engine datastoreIntroducing the App Engine datastore
Introducing the App Engine datastoreikailan
 
What is App Engine? O
What is App Engine? OWhat is App Engine? O
What is App Engine? Oikailan
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
 

More from ikailan (8)

2011 aug-gdd-mexico-city-high-replication-datastore
2011 aug-gdd-mexico-city-high-replication-datastore2011 aug-gdd-mexico-city-high-replication-datastore
2011 aug-gdd-mexico-city-high-replication-datastore
 
2011 july-nyc-gtug-go
2011 july-nyc-gtug-go2011 july-nyc-gtug-go
2011 july-nyc-gtug-go
 
2011 july-gtug-high-replication-datastore
2011 july-gtug-high-replication-datastore2011 july-gtug-high-replication-datastore
2011 july-gtug-high-replication-datastore
 
2011 June - Singapore GTUG presentation. App Engine program update + intro to Go
2011 June - Singapore GTUG presentation. App Engine program update + intro to Go2011 June - Singapore GTUG presentation. App Engine program update + intro to Go
2011 June - Singapore GTUG presentation. App Engine program update + intro to Go
 
Rapid web development using tornado web and mongodb
Rapid web development using tornado web and mongodbRapid web development using tornado web and mongodb
Rapid web development using tornado web and mongodb
 
Introducing the App Engine datastore
Introducing the App Engine datastoreIntroducing the App Engine datastore
Introducing the App Engine datastore
 
What is App Engine? O
What is App Engine? OWhat is App Engine? O
What is App Engine? O
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 

Building TweetEngine

  • 1. Building TweetEngine Ikai Lan Developer Relations, Google App Engine ikai.l@google.com Twitter: @ikai
  • 2. Goals of this talk Using TweetEngine to explain key concepts of building cloud applications Explaining App Engine as a development environment Whet your appetite!
  • 3. What is App Engine? App Engine is a platform You build & test your app Then upload your app to Google App Engine runs everything No need to worry about machines, network, storage, scalability, etc.
  • 4. The king of ease-of-use Extremely rapid development Very low barrier of entry Simple yet robust syntax Rich library of packages/modules App Engine's first language API
  • 6. Getting TweetEngine Application: http://tweetengine.net/ Code: http://github.com/Arachnid/tweetengine Prerequisites: Python 2.5 buildout lxml (for i18n features)
  • 7. OAuth Secure method for granting permissions to third-party integrations Allows sites to use a trusted identity provider (Google, Twitter) "Valet key" for the internet Image and "valet key" source: (http://hueniverse.com/oauth/guide/intro/)
  • 8. Standard OAuth flow (User) What does the User see? 1. Link to login with Twitter 2. User is redirected to an http: //twitter.com URL 3. User logs in, grants access 4. User is redirected back to site
  • 9. Standard OAuth flow (Server) What does the server do? 1. Acquire request token 2. Generate login URL 3. Redirect or link user to this URL 4. After user has logged in, Twitter will redirect to a callback URL on server 5. Server saves token passed to callback URL
  • 10. TweetEngine + OAuth OAuth request token saved in TwitterAccount model Saved per Twitter Account oauth.py handles signing apis.py handles proxied Twitter API calls
  • 11. Logging in to Twitter using OAuth # src/tweetengine/add.py auth_token = self.request.get("oauth_token") auth_verifier = self.request.get("oauth_verifier") user_info = client.get_user_info(auth_token, auth_verifier=auth_verifier) # Create the twitter account account = model.TwitterAccount. get_or_insert( user_info["username"], oauth_token=user_info["token"], oauth_secret=user_info["secret"], name=user_info["name"], picture=user_info["picture"])
  • 12. Initializing an OAuth client # src/oauth.py OAuthClient.__init__(self, "twitter", consumer_key, consumer_secret, "http://twitter.com/oauth/request_token", "http://twitter.com/oauth/access_token", callback_url)
  • 13. Twitter API calls - Web handlers user AJAX - Backend calls go to TwitterApiHandler # src/tweetengine/handlers/apis.py for k,v in params.items(): if isinstance(v, unicode): params[k] = v.encode('utf8') # Join all of the params together. params_str = "&".join(["%s=%s" % (encode(k), encode(params[k])) for k in sorted(params)]) # Join the entire message together per the OAuth specification. message = "&".join(["GET" if method == urlfetch.GET else "POST", encode(url), encode(params_str)]) # Create a HMAC-SHA1 signature of the message. key = "%s&%s" % (self.consumer_secret, secret) # Note compulsory "&". signature = hmac(key, message, sha1) digest_base64 = signature.digest().encode("base64").strip() params["oauth_signature"] = digest_base64 return urlencode(params)
  • 14. OAuth The "de facto" standard for authentication on the web against a third party API TweetEngine's support can be easily generalized to be used on any OAuth supporting site Highly recommend: New sites, do not build identity system, use OAuth or OpenID
  • 15. i18n - internationalization Problem: maintaining localized versions Localization is more than translations TweetEngine already supports English, German and Italian! Image source: http://www.flickr. com/photos/natematias/22132919
  • 16. Workflow 1. Developer marks strings as requiring translation 2. Translators work on .PO files 3. These are compiled into efficient .POT files 4. At runtime, translations are looked up when pages rendered using "Accepts-Header"
  • 17. What does a .po file look like? #. Default: "Collaborative tweeting" #: tweetengine/templates/base.pt:36 msgid "subline" msgstr "Tweeting collaborativo" #. Default: "Welcome!" #: tweetengine/templates/index.pt:3 msgid "title-welcome" msgstr "Benvenuto!"
  • 18. Sample template code tweetengine/templates/index.pt: <metal:title fill-slot="title" i18n:translate="title-welcome">Welcome!</metal:title> tweetengine/templates/base.pt: <h2><a href="/" i18n:translate="subline">Collaborative tweeting</a></h2> Run from TweetEngine root: bin/i18nize
  • 19. src/tweetengine/handlers/base.py # Instantiate Chameleon template loader from chameleon.zpt.loader import TemplateLoader from tweetengine import model from tweetengine.menu import mainmenu tpl_path = os.path.join(os.path.dirname(__file__), "..", "templates") tpl_loader = TemplateLoader(tpl_path) # Later on in the file template_vars['target_language'] = self.request.headers.get('Accept-Language', None) tpl = tpl_loader.load('base.pt') template_vars['master'] = tpl.macros['master'] tpl = tpl_loader.load('macros.pt') template_vars['macros'] = tpl.macros tpl = tpl_loader.load(template_file) self.response.out.write(tpl(**template_vars))
  • 20. Remember: i18n > translations Resizing UI elements for languages with long/short words Right-to-left languages (Hebrew, Arabic) and layouts Time and date formats Metric/English system Much more ... this just a place to start!
  • 21. App Engine is also about tooling Image source: http://www.flickr.com/photos/sparr0/4584964212/
  • 22. Two App Engine tools AppStats Task Queues Application profile that is Background queueing App Engine aware and worker mechanism Image source: http://www.flickr.com/photos/spbatt/3928384579/
  • 23. AppStats Track expensive requests Expose bottlenecks in your code Show you what code is being executed the most for "hotspot optimization" Run in production with minimal overhead
  • 26. How does it work? Uses Call Hooks pre‐call hook records start .me, request, stack post‐call hook records end .me, mcycles, response Measuring times: real time using Python’s wall clock API API megacycles using rpc.cpu_usage_mcycles CPU megacycles using quota.get_request_cpu_usage() Get stack contents from Python’s sys._getframe() Recording accumulates in memory object Written to memcache at end of each request
  • 27. AppStats for TweetEngine Add AppStats as WSGI Middleware: app = recording.appstats_wsgi_middleware(app) Add AppStats GUI to URL mapping (app.yaml): - url: /stats.* script: appstats/ui.py Dev: http://localhost:8080/stats Prod (as admin): http://APPID.appspot.com/stats That's it!
  • 28. Task Queues Execute background tasks Throttle control ETA Can be unique! Invoked using a web handler
  • 29. Standard async worker architecture
  • 30. Task Queues in App Engine # Creating a task # src/tweetengine/model.py taskqueue.Task (eta=send_time, name=task_name, url=twitter. ScheduledTweetHandler.URL_PATH).add() # Task Handler # src/tweetengine/handlers/twitter.py class ScheduledTweetHandler(webapp.RequestHandler): def post(self): publishApprovedTweets() def publishApprovedTweets(): # Iterate through unsent OutgoingTweets and send them
  • 31. Task Queues in TweetEngine Used to schedule Tweets ETA parameter used to set an approximate execution time Tasks are named - this allows us to set times to check for OutgoingTweets that should be sent at this time and not duplicate work (we don't have to use cron)
  • 32. Task Queues Allow developers to build asynchronous workers without hassle of building out queueing/polling system Handles task uniqueness and transactional task creation Can be scheduled, throttled
  • 33. Summary: TweetEngine technologies 1. OAuth - "Valet key" for internet applications 2. i18n - Using templates and message bundles in web applications 3. AppStats - App Engine request profiling toolkit 4. Task Queues - Background work for App Engine applications