Skip to content

Commit 21d5485

Browse files
committed
optimize queries, mod9 switch to DS
1 parent 6a9a560 commit 21d5485

File tree

23 files changed

+46
-52
lines changed

23 files changed

+46
-52
lines changed

Diff for: README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Modernizing Google Cloud serverless compute applications
22
### To the latest Cloud services and serverless platforms
33

4-
This is the corresponding repository to the [Serverless Migration Station](https://bit.ly/3xk2Swi) video series whose goal is to help users on a Google Cloud serverless compute platform modernize to newer Cloud products or other serverless compute platforms. Each modernization migration aims to feature a video, codelab (self-paced, hands-on tutorial), and code samples. The content initially focuses on App Engine and Google's earliest Cloud users.
4+
This is the corresponding repository to the [Serverless Migration Station](https://bit.ly/3xk2Swi) video series whose goal is to help users on a Google Cloud serverless compute platform modernize to newer Cloud products or other serverless compute platforms. Each modernization migration aims to feature a video, codelab (self-paced, hands-on tutorial), and code samples. The content initially focuses on App Engine and Google's earliest Cloud users. Read more about the [codelabs in this announcement](https://developers.googleblog.com/2021/03/modernizing-your-google-app-engine-applications.html?utm_source=ext&utm_medium=partner&utm_campaign=CDR_wes_aap-serverless_modernizegae_codelabsannounce_201031&utm_content=-) as well as [this one introducing the video series](https://developers.googleblog.com/2021/06/introducing-serverless-migration.html?utm_source=blog&utm_medium=partner&utm_campaign=CDR_wes_aap-serverless_smsintro_201023).
55

66
[Google App Engine](https://cloud.google.com/appengine) (Standard) has undergone significant changes between the legacy and next generation platforms. To address this, we've created a set of codelabs (free, online, self-paced, hands-on tutorials) and corresponding videos (when available) to show developers how to perform individual migrations they can apply to modernize their apps for the latest runtimes, with this repo managing the samples from those codelabs. Codelab content typically falls into one of these three topics:
77

@@ -142,7 +142,7 @@ If there is a logical codelab to do immediately after completing one, they will
142142
- **Module 9 codelab** (TBD): **Migrate a Python 2 Cloud NDB & Cloud Tasks (v1) app to a Python 3 Cloud Datastore & Cloud Tasks (v2) app**
143143
- **Optional** migrations
144144
- Migrating to Python 3 is not required but recommended as Python 2 has been sunset
145-
- Migrating to Cloud Firestore is *very* optional as Cloud NDB works on 3.x and most importantly, Cloud Firestore requires a completely new GCP project
145+
- Migrating to Cloud Datastore is optional as Cloud NDB works on 3.x
146146
- Python 2
147147
- START: [Module 8 code - Cloud Tasks](/mod8-cloudtasks) (2.x)
148148
- Python 3
@@ -202,7 +202,7 @@ If there is a logical codelab to do immediately after completing one, they will
202202
- Recommende for small apps or for breaking up large apps into multiple microservices
203203
- Python 3 only
204204
- START: [Module 2 code - Cloud NDB](/mod2b-cloudndb) (3.x)
205-
- FINISH: [Module 11 code - Cloud Firestore](/mod11-functions) (3.x)
205+
- FINISH: [Module 11 code - Cloud Functions](/mod11-functions) (3.x)
206206
- RECOMMENDED:
207207
- Module 7 - add App Engine (push) tasks
208208
- OTHER OPTIONS (in somewhat priority order):

Diff for: mod0-baseline/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ def store_visit(remote_addr, user_agent):
2828

2929
def fetch_visits(limit):
3030
'get most recent visits'
31-
return (v.to_dict() for v in Visit.query().order(
32-
-Visit.timestamp).fetch(limit))
31+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3332

3433
class MainHandler(webapp2.RequestHandler):
3534
'main application (GET) handler'

Diff for: mod1-flask/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ def store_visit(remote_addr, user_agent):
2828

2929
def fetch_visits(limit):
3030
'get most recent visits'
31-
return (v.to_dict() for v in Visit.query().order(
32-
-Visit.timestamp).fetch(limit))
31+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3332

3433
@app.route('/')
3534
def root():

Diff for: mod11-functions/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ def store_visit(remote_addr, user_agent):
3030
def fetch_visits(limit):
3131
'get most recent visits'
3232
with ds_client.context():
33-
return (v.to_dict() for v in Visit.query().order(
34-
-Visit.timestamp).fetch(limit))
33+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3534

3635
def visitme(request):
3736
'main application (GET) handler'

Diff for: mod12-memcache/main.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ def store_visit(remote_addr, user_agent):
3030

3131
def fetch_visits(limit):
3232
'get most recent visits'
33-
return (v.to_dict() for v in Visit.query().order(
34-
-Visit.timestamp).fetch(limit))
33+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3534

3635
@app.route('/')
3736
def root():
@@ -42,7 +41,7 @@ def root():
4241
visits = memcache.get('visits')
4342

4443
# register visit & run DB query if cache empty or new visitor
45-
if not visits or visits[0]['visitor'] != visitor:
44+
if not visits or visits[0].visitor != visitor:
4645
store_visit(ip_addr, usr_agt)
4746
visits = list(fetch_visits(10))
4847
memcache.set('visits', visits, HOUR) # set() not add()

Diff for: mod12b-memcache/main.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def store_visit(remote_addr, user_agent):
3131

3232
def fetch_visits(limit):
3333
'get most recent visits'
34-
return (v.to_dict() for v in Visit.query().order(
35-
-Visit.timestamp).fetch(limit))
34+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3635

3736
@app.route('/')
3837
def root():
@@ -43,7 +42,7 @@ def root():
4342
visits = memcache.get('visits')
4443

4544
# register visit & run DB query if cache empty or new visitor
46-
if not visits or visits[0]['visitor'] != visitor:
45+
if not visits or visits[0].visitor != visitor:
4746
store_visit(ip_addr, usr_agt)
4847
visits = list(fetch_visits(10))
4948
memcache.set('visits', visits, HOUR) # set() not add()

Diff for: mod13a-memorystore/app.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ handlers:
2020
- url: /.*
2121
script: main.app
2222

23+
libraries:
24+
- name: grpcio
25+
version: 1.0.0
26+
- name: setuptools
27+
version: 36.6.0
28+
2329
env_variables:
2430
REDIS_HOST: 'YOUR_REDIS_HOST'
2531
REDIS_PORT: 'YOUR_REDIS_PORT'

Diff for: mod13a-memorystore/appengine_config.py

+3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import pkg_resources
1516
from google.appengine.ext import vendor
1617

1718
# Set PATH to your libraries folder.
1819
PATH = 'lib'
1920
# Add libraries installed in the PATH folder.
2021
vendor.add(PATH)
22+
# Add libraries to pkg_resources working set to find the distribution.
23+
pkg_resources.working_set.add_entry(PATH)

Diff for: mod13a-memorystore/main.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ def store_visit(remote_addr, user_agent):
3838
def fetch_visits(limit):
3939
'get most recent visits'
4040
with ds_client.context():
41-
return (v.to_dict() for v in Visit.query().order(
42-
-Visit.timestamp).fetch(limit))
41+
return Visit.query().order(-Visit.timestamp).fetch(limit)
4342

4443
@app.route('/')
4544
def root():
@@ -51,7 +50,7 @@ def root():
5150
visits = pickle.loads(rsp) if rsp else None
5251

5352
# register visit & run DB query if cache empty or new visitor
54-
if not visits or visits[0]['visitor'] != visitor:
53+
if not visits or visits[0].visitor != visitor:
5554
store_visit(ip_addr, usr_agt)
5655
visits = list(fetch_visits(10))
5756
REDIS.set('visits', pickle.dumps(visits), ex=HOUR)

Diff for: mod13b-memorystore/main.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ def store_visit(remote_addr, user_agent):
3838
def fetch_visits(limit):
3939
'get most recent visits'
4040
with ds_client.context():
41-
return (v.to_dict() for v in Visit.query().order(
42-
-Visit.timestamp).fetch(limit))
41+
return Visit.query().order(-Visit.timestamp).fetch(limit)
4342

4443
@app.route('/')
4544
def root():
@@ -51,7 +50,7 @@ def root():
5150
visits = pickle.loads(rsp) if rsp else None
5251

5352
# register visit & run DB query if cache empty or new visitor
54-
if not visits or visits[0]['visitor'] != visitor:
53+
if not visits or visits[0].visitor != visitor:
5554
store_visit(ip_addr, usr_agt)
5655
visits = list(fetch_visits(10))
5756
REDIS.set('visits', pickle.dumps(visits), ex=HOUR)

Diff for: mod1b-flask/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ def store_visit(remote_addr, user_agent):
3030

3131
def fetch_visits(limit):
3232
'get most recent visits'
33-
return (v.to_dict() for v in Visit.query().order(
34-
-Visit.timestamp).fetch(limit))
33+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3534

3635
@app.route('/')
3736
def root():

Diff for: mod2a-cloudndb/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def store_visit(remote_addr, user_agent):
3131
def fetch_visits(limit):
3232
'get most recent visits'
3333
with ds_client.context():
34-
return (v.to_dict() for v in Visit.query().order(
35-
-Visit.timestamp).fetch(limit))
34+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3635

3736
@app.route('/')
3837
def root():

Diff for: mod2b-cloudndb/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def store_visit(remote_addr, user_agent):
3131
def fetch_visits(limit):
3232
'get most recent visits'
3333
with ds_client.context():
34-
return (v.to_dict() for v in Visit.query().order(
35-
-Visit.timestamp).fetch(limit))
34+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3635

3736
@app.route('/')
3837
def root():

Diff for: mod2b-cloudndb/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
flask
2-
google-cloud-ndb==1.11.1
2+
google-cloud-ndb

Diff for: mod4a-rundocker/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def store_visit(remote_addr, user_agent):
3131
def fetch_visits(limit):
3232
'get most recent visits'
3333
with ds_client.context():
34-
return (v.to_dict() for v in Visit.query().order(
35-
-Visit.timestamp).fetch(limit))
34+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3635

3736
@app.route('/')
3837
def root():

Diff for: mod4a-rundocker/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
gunicorn==19.10.0
1+
gunicorn
22
flask
33
google-cloud-ndb==1.11.1

Diff for: mod5-runbldpks/main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def store_visit(remote_addr, user_agent):
3131
def fetch_visits(limit):
3232
'get most recent visits'
3333
with ds_client.context():
34-
return (v.to_dict() for v in Visit.query().order(
35-
-Visit.timestamp).fetch(limit))
34+
return Visit.query().order(-Visit.timestamp).fetch(limit)
3635

3736
@app.route('/')
3837
def root():

Diff for: mod5-runbldpks/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
gunicor
1+
gunicorn
22
flask
33
google-cloud-ndb

Diff for: mod7-gaetasks/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def fetch_visits(limit):
3737
oldest_str = time.ctime(oldest)
3838
logging.info('Delete entities older than %s' % oldest_str)
3939
taskqueue.add(url='/trim', params={'oldest': oldest})
40-
return (v.to_dict() for v in data), oldest_str
40+
return data, oldest_str
4141

4242
@app.route('/trim', methods=['POST'])
4343
def trim():

Diff for: mod7b-gaetasks/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def fetch_visits(limit):
3838
oldest_str = time.ctime(oldest)
3939
logging.info('Delete entities older than %s' % oldest_str)
4040
taskqueue.add(url='/trim', params={'oldest': oldest})
41-
return (v.to_dict() for v in data), oldest_str
41+
return data, oldest_str
4242

4343
@app.route('/trim', methods=['POST'])
4444
def trim():

Diff for: mod8-cloudtasks/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def fetch_visits(limit):
5656
}
5757
}
5858
ts_client.create_task(parent=QUEUE_PATH, task=task)
59-
return (v.to_dict() for v in data), oldest_str
59+
return data, oldest_str
6060

6161
@app.route('/trim', methods=['POST'])
6262
def trim():

Diff for: mod9-py3fstasks/main.py

+10-13
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def fetch_visits(limit):
5252
'get most recent visits & add task to delete older visits'
5353
query = ds_client.query(kind='Visit')
5454
query.order = ['-timestamp']
55-
visits = query.fetch(limit=limit)
55+
visits = list(query.fetch(limit=limit))
5656
oldest = time.mktime(visits[-1]['timestamp'].timetuple())
5757
oldest_str = time.ctime(oldest)
5858
print('Delete entities older than %s' % oldest_str)
@@ -69,22 +69,19 @@ def fetch_visits(limit):
6969
ts_client.create_task(parent=QUEUE_PATH, task=task)
7070
return visits, oldest_str
7171

72-
def _delete_docs(visits):
73-
'app-internal generator deleting old FS visit documents'
74-
for visit in visits:
75-
visit.reference.delete()
76-
yield visit.id
77-
7872
@app.route('/trim', methods=['POST'])
7973
def trim():
8074
'(push) task queue handler to delete oldest visits'
8175
oldest = float(request.get_json().get('oldest'))
82-
query = ds_client.collection('Visit')
83-
visits = query.where('timestamp', '<',
84-
datetime.fromtimestamp(oldest)).stream()
85-
dlist = ', '.join(str(v_id) for v_id in _delete_docs(visits))
86-
if dlist:
87-
print('Deleting %d entities: %s' % (dlist.count(',')+1, dlist))
76+
query = ds_client.query(kind='Visit')
77+
query.add_filter('timestamp', '<', datetime.fromtimestamp(oldest))
78+
query.keys_only()
79+
keys = list(visit.key for visit in query.fetch())
80+
nkeys = len(keys)
81+
if nkeys:
82+
print('Deleting %d entities: %s' % (
83+
nkeys, ', '.join(str(k.id) for k in keys)))
84+
ds_client.delete_multi(keys)
8885
else:
8986
print('No entities older than: %s' % time.ctime(oldest))
9087
return '' # need to return SOME string w/200

Diff for: mod9-py3fstasks/requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
flask
2-
google-cloud-firestore==2.3.4
3-
google-cloud-tasks==2.7.1
2+
google-cloud-datastore
3+
google-cloud-tasks

0 commit comments

Comments
 (0)