Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google app engine 有事务而不使用高复制数据库_Google App Engine - Fatal编程技术网

Google app engine 有事务而不使用高复制数据库

Google app engine 有事务而不使用高复制数据库,google-app-engine,Google App Engine,我有一个执行以下任务的应用程序 通过用户的电子邮件和密码对其进行身份验证 将上载的文件保存在BlobStore中 检查数据存储中的用户信息,以查看是否存在与此用户关联的旧blob。如果是,则从BlobStore中删除旧blob 更新数据存储,以将BlobStore中的新blob与此用户关联 我尝试在事务中执行步骤2、3、4 db.run_in_transaction(self.upload, email, checksum, version, content) 但是,正如预期的那样,由于我正在

我有一个执行以下任务的应用程序

  • 通过用户的电子邮件和密码对其进行身份验证
  • 将上载的文件保存在BlobStore中
  • 检查数据存储中的用户信息,以查看是否存在与此用户关联的旧blob。如果是,则从BlobStore中删除旧blob
  • 更新数据存储,以将BlobStore中的新blob与此用户关联
  • 我尝试在事务中执行步骤2、3、4

    db.run_in_transaction(self.upload, email, checksum, version, content)
    
    但是,正如预期的那样,由于我正在访问多个实体,因此我得到以下错误

    BadRequestError: can't operate on multiple entity groups in a single transaction.
    
    我不太高兴。例如,如果事务不能跨多个表(实体)执行原子操作,它有什么用?

    我被迫使用高复制数据库。(就账单而言,这将花费我)

    再次出现以下错误:

    BadRequestError: Only ancestor queries are allowed inside transactions.
    
    这在网上发生:

    blob_key = files.blobstore.get_blob_key(file_name)
    
    我的问题是:-

  • 我们有没有办法跨多个“表”执行事务,就像我通过PostgresSQL所做的那样,而不需要使用高复制数据存储?只要考虑成本,主/从数据存储会让我很高兴
  • 如何将
    blob\u key=files.blobstore.get\u blob\u key(file\u name)
    转换为祖先查询?这样它就可以在事务内部工作了?或者,简而言之,如何使
    def upload
    在事务中工作
  • 我的完整代码如下:



    我想我看到了您试图通过使用事务来完成的任务:要么创建blobstore对象和datastore对象(Human),要么两者都不创建。但是您的方法给您带来了几个问题,其中之一是您不能在事务内部执行非祖先查询。当您执行
    get\u blob\u键
    时,您会看到这一点,但您也会得到对
    Human
    s的查询。(第一个错误隐藏了第二个错误。)然后出现了一个问题,即创建一个全新的
    Human
    ,而不是更新一个现有的
    ,这将保留一个指向已删除blob的键


    最简单的方法是取消交易。存储blob,然后确定您是否了解这个人。如果是,则删除旧blob,并更新人员。如果否,则使用新存储的blob密钥创建一个新的人员。

    HR数据存储和M/S数据存储现在在新账单下的价格相同。没有理由不使用HR数据存储

    get\u blob\u key
    必须执行查询以查找与文件名对应的blob。在事务外部执行所有工作,只在事务内部执行更新。但是请注意,您所能做的任何事情都不会使整个过程成为事务性的,因为blobstore更新本身不是事务性的

    blob_key = files.blobstore.get_blob_key(file_name)
    
    import urllib
    import logging
    import model
    import zlib
    from google.appengine.api import urlfetch
    from google.appengine.ext import webapp
    from google.appengine.ext.webapp.util import run_wsgi_app
    from google.appengine.api import files
    from google.appengine.ext import db
    from google.appengine.ext import blobstore
    
    xg_on = db.create_transaction_options(xg=True)
    
    
    class Upload(webapp.RequestHandler):
        def post(self):
            email = self.request.get('Email')
            password = self.request.get('Passwd')
            checksum = int(self.request.get('Checksum'))
            version = int(self.request.get('Version'))
            logintoken = self.request.get('logintoken')
            logincaptcha = self.request.get('logincaptcha')
            content = self.request.get('file')
    
            if version == -1:
                self.response.out.write('ERROR [invalid parameter(s)]')
                return
    
            # Ensure the uploaded content is valid.
            if content is None or not content:
                self.response.out.write('ERROR [no file is uploaded]')
                return
    
            # Authentication.
            headers = {"Content-type": "application/x-www-form-urlencoded"}
            if logintoken and logincaptcha:
                form_data = urllib.urlencode({
                    'accountType': 'HOSTED_OR_GOOGLE', 
                    'Email': email,
                    'Passwd': password,
                    'service': 'mail',
                    'source': 'JStock-1.05b',
                    'logintoken': logintoken,
                    'logincaptcha': logincaptcha
                })
            else:
                form_data = urllib.urlencode({
                    'accountType': 'HOSTED_OR_GOOGLE', 
                    'Email': email,
                    'Passwd': password,
                    'service': 'mail',
                    'source': 'JStock-1.05b'
                })
            result = urlfetch.fetch(url='https://www.google.com/accounts/ClientLogin', payload=form_data, method=urlfetch.POST, headers={'Content-Type': 'application/x-www-form-urlencoded'})
            self.response.set_status(result.status_code)
            if result.status_code != 200:
                # Fail. Either incorrect password or captcha information required.
                self.response.out.write(result.content)
                return
    
            # OK! This is a valid user. Let's proceed with checksum verification.
            ##if checksum != zlib.adler32(content):
            ##    self.response.out.write('ERROR [fail in checksum]')
            ##    return            
    
            #db.run_in_transaction(self.upload, email, checksum, version, content)
            db.run_in_transaction_options(xg_on, self.upload, email, checksum, version, content)
            #self.upload(email, checksum, version, content)
    
    
        def upload(self, email, checksum, version, content):
            # Create the file
            file_name = files.blobstore.create(mime_type='application/octet-stream', _blobinfo_uploaded_filename=email)
    
            # Open the file and write to it
            with files.open(file_name, 'a') as f:
                f.write(content)
    
            # Finalize the file. Do this before attempting to read it.
            files.finalize(file_name)
    
            # Get the file's blob key
            blob_key = files.blobstore.get_blob_key(file_name)
    
            # Remove previous blob referenced by this human.
            query = model.Human.all()
            query.filter('email =', email)
            for q in query:
                blobstore.delete(q.content.key())
    
            human = model.Human(key_name=email, email=email, checksum=checksum, version=version, content=blob_key)
            human.put()
    
    
    application = webapp.WSGIApplication([
        ('/upload.py', Upload)
    ], debug=True)
    
    
    def main():
        run_wsgi_app(application)
    
    
    if __name__ == '__main__':
        main()