创建异步流媒体拉动未来将进一步阻止为Sheets API v4创建资源对象

时间:2019-05-28 13:15:52

标签: python google-api multiprocessing google-sheets-api google-cloud-pubsub

为了支持我的google.chat机器人,我通过多重处理产生了许多进程。 其中之一使用pubsub API的StreamingPull请求来侦听消息,并将传入的消息放置到incomingMessagesQueue。

其他人从入站消息队列中获取消息,并将其传递给处理程序。一些处理程序正在写入Gsheets。 挑战在于

  
      当处理程序对象尝试通过apiclient.discovery.build('sheets','v4',凭据= self.credentials,requestBuilder = self来构建资源对象时,
  1. future会在任何消息进入队列之前初始化。 build_request)   该行永远被卡住,不会引发异常。看起来某个地方发生了线程锁。

  2.   
  3. 当我首先将一些消息放入入库消息队列,然后启动使用future的侦听过程->一切运行正常。完美创建了所有Gsheet资源对象。

  4.   

似乎我在某处缺少线程锁定,我不知道在哪里。当然,我可以使用场景2来使工作正常进行,但我真的很想了解发生了什么。

仅供参考。我所有的Resource对象都是线程安全的,建议由Google实施。为每个线程独立创建http传输时。

监听机器人消息的类:

class MessageHandlerBase(object):
    def __init__(self, project_id, subscription_name, pathToSecretsFile, **kwargs):

        self.project_id = project_id
        self.subscription_name = subscription_name
        self.futureExecutes = Event()
        #some other logging code here

    def startListening(self, callback):
        raw_credentials = service_account.Credentials.from_service_account_file(self.secrets['google_API'])
        self.subscriber = pubsub.SubscriberClient(credentials = raw_credentials)
        self.subscription_path = self.subscriber.subscription_path(self.project_id, self.subscription_name)

        self.future = self.subscriber.subscribe(self.subscription_path, callback=callback)
        self.futureExecutes.set()

    def stop(self):
        if self.futureExecutes.is_set():
            self.future.cancel()

回调给MessageHandler

def putIncomingMessageToQueue(logQueue):
    def f(message):
        incomigMessagesQueue.put(json.loads(message.data))
        logger.info(u'Put message to Queue ' +  unicode(json.loads(message.data)))
        message.ack() 
    return f

卡住样本的处理程序:

class registrationHandler(object):
    def __init__(self, **kwargs):
        pathToSecretsFile = kwargs.get('settings')

        # messages queue that later on will be handled by main process
        self.messagesQueue = kwargs.get('messagesQueue')


        self.logger.info('i am in the registration handler init 2')
        try:
            self.databaseSheet = DynamicSpreadSheet(spreadsheet=self.secrets['bot_config_sheet_id'], sheet_name='bot users', Credentials_file_name=self.secrets['google_API'], **{'logQueue':logQueue})
        except Exception, e:
            self.logger.info('registrationHandler: failed to init a Spreadsheet')
            self.logger.info("".join(traceback.format_exception(*sys.exc_info())))
        self.logger.info('message handler created')

在调用apiclient发现的初始化阶段,DynamicSpreadSheet的创建被永久锁定。

class DynamicSpreadSheet(object):
    def __init__(self, spreadsheet, sheet_name, Credentials_file_name, **kwargs):
        raw_credentials = service_account.Credentials.from_service_account_file(Credentials_file_name)

        self.credentials = raw_credentials.with_scopes(['https://www.googleapis.com/auth/spreadsheets','https://www.googleapis.com/auth/drive'])
        self.service = apiclient.discovery.build('sheets', 'v4', credentials = self.credentials, requestBuilder=self.build_request) 
        self.sheet_name = sheet_name

所以如果你这样打

ProcessHandleMessages = Process(group=None, target = HandleMessages)
incomingMessagesListener = MessageHandlerBase(project_id, subscription_name, 'config/secrets.txt', **{'logQueue': logQueue})

ProcessHandleMessages.start()
incomingMessagesListener.startListening(callback = putIncomingMessageToQueue(logQueue))

然后将消息写入应该处理程序的bot->一切都卡住了

但是,如果您这样做

ProcessHandleMessages = Process(group=None, target = HandleMessages)
ProcessHandleMessages.start()

incomingMessagesQueue.put(message)

incomingMessagesListener = MessageHandlerBase(project_id, subscription_name, 'config/secrets.txt', **{'logQueue': logQueue})
incomingMessagesListener.startListening(callback = putIncomingMessageToQueue(logQueue))

然后,从机器人发出的所有其他消息都会被正确使用

我使用的是python 2.7(不要问我为什么:)

0 个答案:

没有答案