I have the code below to update an entity in the Google data store.
I'm now getting an internal error on the model.Collection.put(vhighest)
sync.yaml
service: sync
instance_class: F2
automatic_scaling:
max_instances: 1
runtime: python312
app_engine_apis: true
entrypoint: gunicorn -b :$PORT sync:app
#inbound_services:
#- warmup
#libraries:
#- name: jinja2
# version: latest
#- name: ssl
# version: latest
# taskqueue and cron tasks can access admin urls
handlers:
- url: /.*
script: sync.app
secure: always
redirect_http_response_code: 301
env_variables:
MEMCACHE_USE_CROSS_COMPATIBLE_PROTOCOL: "True"
NDB_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: "True"
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: "True"
CURRENT_VERSION_TIMESTAMP: "1677721600"
google.cloud.ndb.tasklets.Return: Key('Collection', 6266129674665984)
Can I ask for some guidance, did something with how i should use these methods?
import flask
import config
import util
app = flask.Flask(__name__)
from google.appengine.api import taskqueue, search, memcache
from apiclient.discovery import build, HttpError
from google.cloud import ndb
from apiclient.http import MediaIoBaseUpload
from datetime import datetime, timedelta
from functools import partial
from io import BytesIO
import os
from os.path import splitext, basename
from model import Config
from model import VideosToCollections
from pytz import timezone
import datetime
import httplib2
import iso8601
import time
from flask import request
from operator import attrgetter
import model
from model import CallBack
import re
import config
import google.appengine.api
client = ndb.Client()
def ndb_wsgi_middleware(wsgi_app):
def middleware(environ, start_response):
with client.context():
return wsgi_app(environ, start_response)
return middleware
app.wsgi_app = ndb_wsgi_middleware(app.wsgi_app)
#
################################################################################
## Flush all caches, rebuild search index, and sync all videos
################################################################################
#
@app.route('/rx/', methods=['GET'])
def rx():
GAE_APP_ID = os.environ['GOOGLE_CLOUD_PROJECT']
index = search.Index('general-index')
while True:
document_ids = [
document.doc_id
for document
in index.get_range(ids_only=True)]
#
# If no IDs were returned, we've deleted everything.
if not document_ids:
break
#
# Delete the documents for the given IDs
index.delete(document_ids)
#
# flush memcache
memcache.flush_all()
#
# # get/put all collections so they are reindexed
collections_dbs_keys, cursor = model.Collection.get_dbs(keys_only=True, limit=-1)
collections_dbs = ndb.get_multi(collections_dbs_keys)
for collection in collections_dbs:
collection.search_update_index()
#
# # sync all videos
taskqueue.add(url=flask.url_for('sync_video'),
params={'syncthumb': True},
method='GET')
#
return 'ok. flushed everything and started video sync.'
#
#
################################################################################
## Sync video(s) task worker
################################################################################
#
@app.route('/sync/', methods=['GET'])
@app.route('/sync/<yt_video_id>', methods=['POST','GET'])
def sync_video(yt_video_id=None):
GAE_APP_ID = os.environ['GOOGLE_CLOUD_PROJECT']
syncthumb = util.param('syncthumb', bool)
if not syncthumb:
syncthumb = False
if yt_video_id:
util.sync_video_worker(yt_video_id, syncthumb=syncthumb)
success = 'ok: synced ' + yt_video_id
return success
index = search.Index('general-index')
while True:
document_ids = [
document.doc_id
for document
in index.get_range(ids_only=True)]
# If no IDs were returned, we've deleted everything.
if not document_ids:
break
# Delete the documents for the given IDs
index.delete(document_ids)
# get/put all collections so they are reindexed
collections_dbs_keys, cursor = model.Collection.get_dbs(keys_only=True, limit=-1)
collections_dbs = ndb.get_multi(collections_dbs_keys)
for collection in collections_dbs:
collection.search_update_index()
video_dbs, video_cursor = model.Video.get_dbs(limit=-1)
tasks = [taskqueue.Task(
url='/sync/' + video_db.yt_video_id,
params={'syncthumb': syncthumb},
) for video_db in video_dbs]
for batches in [tasks[i:i + 5] for i in range(0, len(tasks), 5)]:
rpc = taskqueue.Queue('sync').add_async(batches)
rpc.wait()
success = 'ok: dispatched ' + str(len(tasks)) + ' videos for sync tasks'
return success
###############################################################################
# Populate Collections
###############################################################################
@app.route('/collectionsync/', methods=['GET'])
#@ndb.transactional
def collectionsync():
GAE_APP_ID = os.environ['GOOGLE_CLOUD_PROJECT']
vnew=model.Collection.query(model.Collection.slug=='new').get()
for p in model.VideosToCollections.query(model.VideosToCollections.collection_key==vnew.key):
p.key.delete()
#populate newest collection
tot=0
ct=0
for p in model.Video.query().order(-model.Video.launch_date):
#print(p)
if(p.launch_date):
if p.get_launch_date().date() > (datetime.datetime.now(timezone("UTC")).date()):
continue
if(p.yt_date_added is not None):
if(p.yt_date_added > (datetime.datetime.today() - timedelta(days=30))):
ct+=1
vc = VideosToCollections()
vc.video_key = p.key
vc.collection_key = vnew.key
vc.order = ct
vc.launch_date = datetime.datetime.now(timezone("UTC")).date()
model.VideosToCollections.put(vc)
if(ct==1):
vnew.featured_primary=p.key
model.Collection.put(vnew)
if(ct==2):
vnew.featured_secondary=p.key
model.Collection.put(vnew)
if(ct>=25):
break
tot+=ct
#populate highest rated collection
ct=0
vhighest=model.Collection.query(model.Collection.slug=='highest-rated').get()
for p in model.VideosToCollections.query(model.VideosToCollections.collection_key==vhighest.key):
p.key.delete()
for p in model.Video.query().order(-model.Video.approval):
if(p.launch_date):
if p.get_launch_date().date() > (datetime.datetime.now(timezone("UTC")).date()):
continue
if(p.yt_views > 25000):
ct+=1
vc = VideosToCollections()
vc.video_key = p.key
vc.collection_key = vhighest.key
vc.launch_date = datetime.datetime.now(timezone("UTC")).date()
vc.order = ct
model.VideosToCollections.put(vc)
if(ct==1):
vhighest.featured_primary=p.key
model.Collection.put(vhighest)
if(ct==2):
vhighest.featured_secondary=p.key
model.Collection.put(vhighest)
if(ct>=25):
break
tot+=ct
# flush memcache
#memcache.flush_all()
success = 'ok: dispatched ' + str(tot) + ' videos into collections'
return success
2025年05月16日 15:24:21 sync[20250516t112108] "GET /collectionsync/ HTTP/1.1" 500
2025年05月16日 15:24:21 sync[20250516t112108] [2025年05月16日 15:24:21 +0000] [11] [INFO] Starting gunicorn 22.0.0
2025年05月16日 15:24:21 sync[20250516t112108] [2025年05月16日 15:24:21 +0000] [11] [INFO] Listening at: http://0.0.0.0:8081 (11)
2025年05月16日 15:24:21 sync[20250516t112108] [2025年05月16日 15:24:21 +0000] [11] [INFO] Using worker: sync
2025年05月16日 15:24:21 sync[20250516t112108] [2025年05月16日 15:24:21 +0000] [15] [INFO] Booting worker with pid: 15
2025年05月16日 15:24:25 sync[20250516t112108] [2025年05月16日 15:24:25,568] ERROR in app: Exception on /collectionsync/ [GET]
2025年05月16日 15:24:25 sync[20250516t112108] Traceback (most recent call last): File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 323, in _advance_tasklet yielded = self.generator.send(send_value)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/model.py", line 5518, in put
2025年05月16日 15:24:25 sync[20250516t112108] raise tasklets.Return(self._key)
2025年05月16日 15:24:25 sync[20250516t112108] google.cloud.ndb.tasklets.Return: Key('Collection', 6266129674665984)
2025年05月16日 15:24:25 sync[20250516t112108] During handling of the above exception, another exception occurred:
2025年05月16日 15:24:25 sync[20250516t112108] Traceback (most recent call last): File "/layers/google.python.pip/pip/lib/python3.12/site-packages/flask/app.py", line 2529, in wsgi_app response = self.full_dispatch_request()
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/flask/app.py", line 1825, in full_dispatch_request
2025年05月16日 15:24:25 sync[20250516t112108] rv = self.handle_user_exception(e)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/flask/app.py", line 1823, in full_dispatch_request
2025年05月16日 15:24:25 sync[20250516t112108] rv = self.dispatch_request()
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/flask/app.py", line 1799, in dispatch_request
2025年05月16日 15:24:25 sync[20250516t112108] return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/workspace/sync.py", line 210, in collectionsync
2025年05月16日 15:24:25 sync[20250516t112108] model.Collection.put(vhighest)
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/_options.py", line 102, in wrapper
2025年05月16日 15:24:25 sync[20250516t112108] return wrapped(*pass_args, **kwargs)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/utils.py", line 118, in wrapper
2025年05月16日 15:24:25 sync[20250516t112108] return wrapped(*args, **new_kwargs)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/utils.py", line 150, in positional_wrapper
2025年05月16日 15:24:25 sync[20250516t112108] return wrapped(*args, **kwds)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/model.py", line 5449, in _put
2025年05月16日 15:24:25 sync[20250516t112108] return self._put_async(_options=kwargs["_options"]).result()
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 210, in result
2025年05月16日 15:24:25 sync[20250516t112108] self.check_success()
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 154, in check_success
2025年05月16日 15:24:25 sync[20250516t112108] self.wait()
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 145, in wait
2025年05月16日 15:24:25 sync[20250516t112108] if not _eventloop.run1():
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/_eventloop.py", line 390, in run1
2025年05月16日 15:24:25 sync[20250516t112108] return loop.run1()
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/_eventloop.py", line 326, in run1
2025年05月16日 15:24:25 sync[20250516t112108] delay = self.run0()
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/_eventloop.py", line 286, in run0
2025年05月16日 15:24:25 sync[20250516t112108] if self._run_current() or self.run_idle():
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/_eventloop.py", line 276, in _run_current
2025年05月16日 15:24:25 sync[20250516t112108] callback(*args, **kwargs)
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 337, in _advance_tasklet
2025年05月16日 15:24:25 sync[20250516t112108] self.set_result(_get_return_value(stop))
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 170, in set_result
2025年05月16日 15:24:25 sync[20250516t112108] self._finish()
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/cloud/ndb/tasklets.py", line 199, in _finish
2025年05月16日 15:24:25 sync[20250516t112108] callback(self)
2025年05月16日 15:24:25 sync[20250516t112108] File "/workspace/NdbSearchableBase/SearchableModel.py", line 203, in _post_put_hook
2025年05月16日 15:24:25 sync[20250516t112108] self.search_update_index()
2025年05月16日 15:24:25 sync[20250516t112108] File "/workspace/NdbSearchableBase/SearchableModel.py", line 144, in search_update_index
2025年05月16日 15:24:25 sync[20250516t112108] index.put(document)
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/datastore/datastore_rpc.py", line 94, in positional_wrapper
2025年05月16日 15:24:25 sync[20250516t112108] return wrapped(*args, **kwds)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/api/search/search.py", line 3610, in put
2025年05月16日 15:24:25 sync[20250516t112108] return self.put_async(documents, deadline=deadline).get_result()
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/datastore/datastore_rpc.py", line 94, in positional_wrapper
2025年05月16日 15:24:25 sync[20250516t112108] return wrapped(*args, **kwds)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/api/search/search.py", line 3667, in put_async
2025年05月16日 15:24:25 sync[20250516t112108] return _PutOperationFuture(self, request, response, deadline, hook)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/api/search/search.py", line 281, in __init__
2025年05月16日 15:24:25 sync[20250516t112108] super(_PutOperationFuture, self).__init__('IndexDocument', request,
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/api/search/search.py", line 265, in __init__
2025年05月16日 15:24:25 sync[20250516t112108] self._rpc = apiproxy_stub_map.UserRPC('search', deadline=deadline)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/api/apiproxy_stub_map.py", line 444, in __init__
2025年05月16日 15:24:25 sync[20250516t112108] self.__rpc = CreateRPC(service, stubmap)
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025年05月16日 15:24:25 sync[20250516t112108] File "/layers/google.python.pip/pip/lib/python3.12/site-packages/google/appengine/api/apiproxy_stub_map.py", line 69, in CreateRPC
2025年05月16日 15:24:25 sync[20250516t112108] assert stub, 'No api proxy found for service "%s"' % service
2025年05月16日 15:24:25 sync[20250516t112108] ^^^^
2025年05月16日 15:24:26 sync[20250516t112108] AssertionError: No api proxy found for service "search"
asked May 16 at 15:26
ffejrekaburb
7752 gold badges13 silver badges36 bronze badges
lang-py
dev_appserver.pyfrom google.appengine, it means you're using a version of the API/library that is bundled with appengine (Google has done the heavy lifting underneath so that it works in app engine without your having to create a client and specify a project, etc; it will only work within appengine). Instead of using that version, you can use the cloud version which works anywhere (GAE, GCE, Cloud Run, etc) but you have to handle initializing the client and specifying your project, etcExample for a Flask app:. Actually read the entire thing underUsing the SDK