如何在Firebase Firestore数据库中检测实时侦听器错误?

时间:2019-04-26 23:55:13

标签: python firebase google-cloud-firestore

Firestore listeners将在一段时间(可能是由于不活动)后随机关闭,并且在python中,没有简单的方法来捕获它们引发的错误,因为它们将它们引发在单独的线程中。就我而言,我想维持一个持久的侦听器,该侦听器由于不活动或服务器端错误而永远不会关闭。

我尝试将所有内容包装起来-除外,然后将所有内容包装在while(True)循环中,但这并不能捕获错误,因为错误是在单独的线程中抛出的。

该错误在10分钟后发生-24小时不活动(我不确定是否为不活动,可能是随机的,但是我发现的最短间隔是启动后10分钟),在Linux和Windows设备上。我没有尝试过Mac或任何其他设备,但是我怀疑它是特定于设备的。

查看gRPC(侦听器用来在客户端和服务器之间进行通信的事物)规范,python api没有默认超时(并且超时不会解释为什么在不同的时间量后断开连接),也没有超时它在Firestores侦听器代码中的任何位置设置。

发生的具体错误是:

google.api_core.exceptions.InternalServerError:500收到了RST_STREAM,错误代码为0

有时

google.api_core.exceptions.InternalServerError:500收到了RST_STREAM,错误代码为2

显示该问题的最小代码(在一个名为info的虚拟集合上运行一段时间,该集合仅在其中包含一个文档)

class TestWatchInfo():
  def __init__(self):
    self.query_watch = db.collection(u'info').on_snapshot(self.on_snapshot)

  def on_snapshot(self, col_snapshot, changes, read_time):
    try:
      for change in changes:
        pass
    except Exception as err:
      print(err)
      print("Error occurred at " + str(time.ctime()))
      traceback.print_exc()

if __name__ == '__main__':
  try:
    test_object = TestWatchInfo()
    while(True):
      time.sleep(60)
  except Exception as err:
    print(err)
    print("Error occurred at " + str(time.ctime()))
    traceback.print_exc()

理想情况下,我将能够捕获在python主线程中发生的实际错误,但据我所知,由于我不是生成线程的人,因此我无法向其中添加线程/ gRPC特定代码捕获该错误。另外,我希望能够在gRPC连接由于服务器端而关闭后自动重新启动。

实际上,Firestore侦听器只是在其创建的线程中引发错误并关闭该侦听器。

1 个答案:

答案 0 :(得分:1)

我想出了另一种方法来检测侦听器错误并在服务器端关闭后重新启动侦听器。我不知道如何捕获实际错误,但是我想出了如何检测Firestore何时只是随机关闭侦听器连接。

在Firebase侦听器代码中,它们跟踪私有变量“ _closed”,如果由于某种原因连接被关闭,则该私有变量将变为true。因此,如果我们定期进行检查,则可以重新启动侦听器并保持愉快的状态。

使用之前的代码,我添加了一个新方法start_snapshot,以便在出错时重新启动失败的侦听器表达式,并且在长时间运行的代码中,我对侦听器添加了检查以查看其是否关闭,然后重新启动它如果是这样。

class TestWatchInfo():
  def __init__(self):
    self.start_snapshot()

  def start_snapshot(self):
    self.query_watch = db.collection(u'info').on_snapshot(self.on_snapshot)

  def on_snapshot(self, col_snapshot, changes, read_time):
    try:
      for change in changes:
        pass
    except Exception as err:
      print(err)
      print("Error occurred at " + str(time.ctime()))
      traceback.print_exc()

if __name__ == '__main__':
  try:
    test_object = TestWatchInfo()
    while(True):
      if test_object.query_watch._closed:
        test_object.start_snapshot()
      # code here
  except Exception as err:
    print(err)
    print("Error occurred at " + str(time.ctime()))
    traceback.print_exc()
相关问题