gpt4 book ai didi

google-app-engine - 如果一个用户撤消访问权限,则对多个用户的批量请求会失败

转载 作者:行者123 更新时间:2023-12-02 08:36:16 24 4
gpt4 key购买 nike

我正在使用镜像 API 进行玻璃器皿项目。

我的应用类似于新闻应用,它会在文章发布时向所有订阅用户发送文章时间轴卡片。随着我的用户群的增长,这将成为一个问题,因为就目前的应用程序而言,它正在为每个文章卡片的每个用户进行一次 API 调用。根据用户的设置,我们每天最多可以发送 50 篇文章。考虑到 Google 每天只有 1000 次 Mirror API 调用的礼貌限制,我已经达到了只有 20 个用户的要求。我知道当我的应用程序获得批准后,这会增加,但我仍然想优化我的代码。

问题 1:我假设实现批处理会减少 API 调用的数量是否正确我在这里找不到答案:https://developers.google.com/glass/batch假设我进行单个批处理调用以将单个时间线项目发布到我用户的玻璃时间线中的 1000 个,这算作 1 个 Mirror API 请求还是 1000 个 Mirror API 请求?如果是后者,(问题 1.1)我假设批处理的唯一好处是减少我的应用程序的流量是否正确?

我遇到的问题是,如果用户在批处理运行时从 ( https://security.google.com/settings/security/permissions ) 撤消对我的应用程序的访问权限,则会引发异常并失败。它最终将用户(仍然具有权限)注销,并且他们被迫重新进行身份验证。根据我的测试,我认为它不会在整个批处理中失败,所以我不确定它是否将时间线卡发送给所有其他没有删除访问权限的用户。

目前,在没有批处理的情况下,我能够捕获此错误并在用户撤销访问权限时将其从我的数据库中删除。 问题 2:如何在我的代码中捕获此错误并确定它对应于哪个用户。示例代码如下:

def _insert_item_all_users(self):
"""Insert a timeline item to all authorized users."""
logging.info('Inserting timeline item to all users')
users = Credentials.all()
total_users = users.count()

if total_users > 10:
return 'Total user count is %d. Aborting broadcast to save your quota' % (
total_users)
body = {
'text': 'Hello Everyone!',
'notification': {'level': 'DEFAULT'}
}

batch_responses = _BatchCallback()
batch = BatchHttpRequest(callback = batch_responses.callback)
for user in users:
creds = StorageByKeyName(
Credentials, user.key().name(), 'credentials').get()
mirror_service = util.create_service('mirror', 'v1', creds)
batch.add(
mirror_service.timeline().insert(body = body),
request_id = user.key().name())

batch.execute(httplib2.Http())
return 'Successfully sent cards to %d users (%d failed).' % (
batch_responses.success, batch_responses.failure)

我得到的错误是这样的:

INFO         2014-01-15 22:42:06,031 client.py:699] Failed to retrieve access token: {
"error" : "invalid_grant"
}

访问 token 刷新失败并引发了 oauth2client.client.AccessTokenRefreshError

重现步骤:

  1. 下载、安装并运行适用于 Python 的 Glassware 入门项目 https://developers.google.com/glass/develop/mirror/quickstart/python
  2. 打开 2 个浏览器(或 2 个 chrome 隐私浏览窗口)并使用 2 个不同的 Google 帐户(我将它们称为帐户一和帐户二)登录(完成 auth2 身份验证)。您应该会在两个用户供稿中看到一张欢迎时间轴卡片。
  3. 在第一个用户帐户上,点击最后一个显示“为所有用户插入卡”的按钮。如果您刷新两个帐户页面,您应该会看到插入了一张卡片,上面写着“大家好!”
  4. 现在在帐户二的浏览器中,打开一个新选项卡并转到 https://security.google.com/settings/security/permissions找到该应用并点击“撤销访问权限”
  5. 在帐户的浏览器中,单击最后一个显示“向所有用户插入卡”的按钮。现在应该将您注销并转到 Google 誓言屏幕以重新登录。一旦您重新登录,您可以看到您确实收到了时间线卡,但是如果您随后重新验证帐户二,他们没有.

应用项目日志

--Send timeline card to all users (before revoking access)
INFO 2014-01-15 22:41:41,217 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:41,217 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:41,217 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:41:41,999 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:41,999 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:41,999 client.py:680] Refreshing access_token
INFO 2014-01-15 22:41:42,519 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:42,519 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:42,521 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:42,521 appengine.py:265] get: Got type <class 'model.Credentials'>
INFO 2014-01-15 22:41:42,523 main_handler.py:275] Inserting timeline item to all users
INFO 2014-01-15 22:41:42,529 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:42,530 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:42,532 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:42,532 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:42,532 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:41:42,945 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/timeline?alt=json
INFO 2014-01-15 22:41:42,946 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:42,946 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:42,949 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:42,950 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:42,950 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:41:43,666 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/timeline?alt=json
WARNING 2014-01-15 22:41:43,666 util.py:125] execute() takes at most 1 positional argument (2 given)
INFO 2014-01-15 22:41:44,641 module.py:617] default: "POST / HTTP/1.1" 302 -
INFO 2014-01-15 22:41:44,648 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:44,648 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:44,649 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:41:45,092 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:45,093 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:45,093 client.py:680] Refreshing access_token
INFO 2014-01-15 22:41:45,841 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:41:45,841 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:45,842 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:41:45,843 appengine.py:265] get: Got type <class 'model.Credentials'>
INFO 2014-01-15 22:41:45,850 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/contacts/python-quick-start?alt=json
WARNING 2014-01-15 22:41:45,852 urlfetch_stub.py:482] Stripped prohibited headers from URLFetch request: ['content-length']
INFO 2014-01-15 22:41:46,472 main_handler.py:93] Unable to find Python Quick Start contact.
INFO 2014-01-15 22:41:46,492 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/timeline?maxResults=3&alt=json
WARNING 2014-01-15 22:41:46,494 urlfetch_stub.py:482] Stripped prohibited headers from URLFetch request: ['content-length']
INFO 2014-01-15 22:41:47,028 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/subscriptions?alt=json
WARNING 2014-01-15 22:41:47,031 urlfetch_stub.py:482] Stripped prohibited headers from URLFetch request: ['content-length']
INFO 2014-01-15 22:41:47,562 module.py:617] default: "GET / HTTP/1.1" 200 8163
INFO 2014-01-15 22:41:47,664 module.py:617] default: "GET /static/bootstrap/css/bootstrap-responsive.min.css HTTP/1.1" 304 -
INFO 2014-01-15 22:41:47,665 module.py:617] default: "GET /static/bootstrap/css/bootstrap.min.css HTTP/1.1" 304 -
INFO 2014-01-15 22:41:47,666 module.py:617] default: "GET /static/main.css HTTP/1.1" 304 -
INFO 2014-01-15 22:41:47,668 module.py:617] default: "GET /static/images/chipotle-tube-640x360.jpg HTTP/1.1" 304 -
INFO 2014-01-15 22:41:47,672 module.py:617] default: "GET /static/bootstrap/js/bootstrap.min.js HTTP/1.1" 304 -




--Send timeline card to all users (after revoking access)
INFO 2014-01-15 22:42:02,892 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:02,893 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:02,893 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:42:03,278 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:03,279 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:03,279 client.py:680] Refreshing access_token
INFO 2014-01-15 22:42:03,829 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:03,829 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:03,830 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:03,830 appengine.py:265] get: Got type <class 'model.Credentials'>
INFO 2014-01-15 22:42:03,834 main_handler.py:275] Inserting timeline item to all users
INFO 2014-01-15 22:42:03,844 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:03,844 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:03,846 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:03,847 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:03,847 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:42:04,270 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/timeline?alt=json
INFO 2014-01-15 22:42:04,271 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:04,271 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:04,275 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:04,276 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:04,276 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest?userIp=127.0.0.1
INFO 2014-01-15 22:42:04,705 discovery.py:709] URL being requested: https://www.googleapis.com/mirror/v1/timeline?alt=json
WARNING 2014-01-15 22:42:04,705 util.py:125] execute() takes at most 1 positional argument (2 given)
INFO 2014-01-15 22:42:05,531 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:05,531 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:05,532 client.py:680] Refreshing access_token
INFO 2014-01-15 22:42:06,031 client.py:699] Failed to retrieve access token: {
"error" : "invalid_grant"
}
INFO 2014-01-15 22:42:06,035 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:06,035 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:06,038 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:06,038 appengine.py:265] get: Got type <class 'model.Credentials'>
INFO 2014-01-15 22:42:06,043 appengine.py:276] make: Got type <class 'google.appengine.api.datastore_types.Blob'>
INFO 2014-01-15 22:42:06,043 appengine.py:289] validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
INFO 2014-01-15 22:42:06,056 module.py:617] default: "POST / HTTP/1.1" 302 -
INFO 2014-01-15 22:42:06,066 module.py:617] default: "GET /auth HTTP/1.1" 302 -

最佳答案

两个问题的两个答案,收集 self 们在上面评论中讨论的内容。

Q1 - 批处理是否节省 API 配额?

没有。批处理中的 API 请求仍然算作一个完整的 API 请求。

批处理是为了提高性能。它减少了您必须打开的套接字数量并节省了带宽,尤其是当您使用 gzip 并将相同的有效负载发送给许多用户时。

如果您想要更多配额,请填写 Glassware submission form .即使您只需要更多配额来继续开发,也可以使用它。

Q2 - 为什么过期的 token 会破坏我的整个批处理请求?

如您所见,它是 a bug在 Python API 客户端库中。即使请求失败,它也应该调用您的回调。你像这样修补它:

--- /google-api-python-client-1ab344e0a34d/apiclient/http.py
+++ /google-api-python-client-patched/apiclient/http.py
@@ -50,7 +50,7 @@
from model import JsonModel
from oauth2client import util
from oauth2client.anyjson import simplejson
-
+from oauth2client.client import AccessTokenRefreshError

DEFAULT_CHUNK_SIZE = 512*1024

@@ -1299,10 +1299,13 @@
for request_id in self._order:
resp, content = self._responses[request_id]
if resp['status'] == '401':
- redo_order.append(request_id)
- request = self._requests[request_id]
- self._refresh_and_apply_credentials(request, http)
- redo_requests[request_id] = request
+ try:
+ request = self._requests[request_id]
+ self._refresh_and_apply_credentials(request, http)
+ redo_order.append(request_id)
+ redo_requests[request_id] = request
+ except AccessTokenRefreshError:
+ pass

if redo_requests:
self._execute(http, redo_order, redo_requests)

关于google-app-engine - 如果一个用户撤消访问权限,则对多个用户的批量请求会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21150275/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com