Have you ever wondered, where to find the best pizza in a new city? Who doesn’t like a hot slice of pepperoni pizza? (Or perhaps a square of gluten-free pesto pizza with roma tomatoes?)
Google Cloud offers some incredible elastically-scaled technology for distributed computing. The best part about it, is that you don’t have to think about how the technical infrastructure works underneath the hood.
Focus on your code, not your infrastructure.
It Started with Two Questions
- How can I show the scale of Google Cloud Tasks?
- How do I find the best pizza slice around the world programmatically?
In this section, we’ll write a script that creates multiple tasks that targets a Google Cloud Function. To make things interesting, we’ll use the Google Maps API and search for the best pizza in 13,000 cities around the world. We’ll store the results in Firestore. To visualize our data, a simple web page with an embedded Google Map shows a pin for each pizza restaurant.
How our application works
Here’s an architectural diagram of our application:
On the left, we have Cloud Tasks that queues up 13,000 HTTP requests.
Why would we want to use Cloud Tasks here? Perhaps we want to rate limit our calls to our API, or be able to pause requests to our API, or not call the API for duplicate requests. Here, it is handy to pre-load our 13,000 URL targets.
This use-case is great for Cloud Tasks.
In the center of the diagram, we have a Google Cloud Function (written in Node). This Cloud Function is our central entry point for:
- Web browser requests to render the Google Map Web UI
- API requests to get Google Maps API places data stored in Firestore
This application is powered by the Node Functions Framework which enables local development of Google Cloud Functions.
On the right, we use the Maps Geocoding API to find the lat/lng of our query and the Maps Place Search API to find the best pizza restaurant near that lat/lng. Results are stored in Firestore (on the bottom).
Set up our Application
First, some setup. Our demo shows an end-to-end app that collects data from Google Maps, stores in Firestore, and displays the data with a public URL with Cloud Functions. We need to set up the storage and compute. It’s fairly simple, but takes a few minutes.
Download the code for the application
Clone the repo github.com/GoogleCloudPlatform/cloud-tasks-pizza-map:
git clone firstname.lastname@example.org:GoogleCloudPlatform/cloud-tasks-pizza-map.git
Enable Google APIs
We can use this special link to enable all APIs for our project:
Cloud Tasks API: A queue that features deduplicatication, play/pause, retry, and other configuration
Maps Places API: Find pizza restaurants
Maps Geocoding API: Find lat/lng of restaurants given a “place id”
Firestore API: Store data
Set up a database
Set up a Firestore database for storing our Google Maps API data with these configs:
Create a Google Maps API key
Create an API key for Maps here:
Save the key in a
.env file that looks like this:
Run our Application Locally
To test our server locally, follow these instructions using our
KEY from the previous step:
KEY=... npm start
We’ll see the CLI outputs useful information about our app:
> email@example.com start /github/GoogleCloudPlatform/cloud-tasks-pizza-map
> FUNCTION_SOURCE=src npx @google-cloud/functions-frameworkServing function...
localhost:8080, we’ll see our routes for our app (I’ve annotated here):
"/tasks/start", // starts creating all Cloud Tasks
"/tasks/listnames", // lists Tasks names
"/maps/add", // adds restaurant data to the database
"/maps/get", // gets restaurant data
"/maps/listnames", // lists names of cities from a gist
"/maps/key", // prints the GMP API key for the front-end
"/target", // our Cloud Tasks target (same as /maps/add)
"/web" // our web UI for displaying our map
You’re running this Google Cloud Function locally! Great! Now how do we get those pins to show up on the Map? 🤔
There are some order of operations here to run the demo:
- Load the Cloud Tasks queue by running
/tasks/start. This will take a few minutes as it creates ~13,000 unique Tasks for every city in the world.
- Ensure the Cloud Tasks queue is unpaused by going to https://console.cloud.google.com/cloudtasks. Unpausing the queue will populate our Firestore database.
- Open our frontend at
localhost:8080/webto visualize the data in our database.
Test our Application
/web, we’ll see pins drop as the frontend UI reads our database records.
Note: We purposefully slow down the frontend to create this animation, which lasts ~20 minutes to load all 13k pins.
For example, in Midtown, Manhattan, we have a link to Joe’s Pizza with around 7k ratings averaging of 4.5 ⭐s.
Those pins that seem to be in the ocean are not mistakes. There are lots of islands around the world with pizza:
I’ve had hours of fun exploring the world of pizza on Google Maps using this app and could talk about the most unique pizza restaurants in a whole essay. But let’s go back to developing our app.
Deploy our Application
The great thing about our demo is that there is no special configuration needed to deploy our application to production.
It is easy to change our demo such that we aren’t using
localhost, but rather, using a real
https URL on Google Cloud.
We can simply run
npm run deploy, which really runs this command:
gcloud functions deploy tasks-pizza
In ~30 seconds, you’ll get a public URL like this:
Note: That’s not a real URL.
Thanks for Reading
If you liked this blogpost, check out these resources:
- 💻 Source: github.com/GoogleCloudPlatform/cloud-tasks-pizza-map
- 🌎 World City Data: simplemaps.com/data/world-cities
- 🔧 Functions Framework: github.com/GoogleCloudPlatform/functions-framework-nodejs
Thanks to this app, I won’t go hungry 😋🍕