为了支持我的google.chat机器人,我通过多重处理产生了许多进程。 其中之一使用pubsub API的StreamingPull请求来侦听消息,并将传入的消息放置到incomingMessagesQueue。
其他人从入站消息队列中获取消息,并将其传递给处理程序。一些处理程序正在写入Gsheets。 挑战在于
当处理程序对象尝试通过apiclient.discovery.build('sheets','v4',凭据= self.credentials,requestBuilder = self来构建资源对象时,
future会在任何消息进入队列之前初始化。 build_request) 该行永远被卡住,不会引发异常。看起来某个地方发生了线程锁。
当我首先将一些消息放入入库消息队列,然后启动使用future的侦听过程->一切运行正常。完美创建了所有Gsheet资源对象。
似乎我在某处缺少线程锁定,我不知道在哪里。当然,我可以使用场景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(不要问我为什么:)