美文网首页
一个超时轮询的工作任务

一个超时轮询的工作任务

作者: 东方胖 | 来源:发表于2024-07-01 10:26 被阅读0次

设想有一个轮询任务
我们需要从一个第三方系统监视一个状态,等待它变成我们期待的预期值

由于状态存在永远不会达到预期的可能,我们需要为这个任务设置一个忍耐的上限,即超时时间

这个任务写成接口的定义
···
def watch_job(expect_state, interval, timeout):
···

interval 是向第三方系统轮询的间隔 假设这里有一个API

表达这个任务的方式有几种
假设这个 API 是 request_state() , 它返回一个状态

伪代码写成

def watch_job(expect_state, interval, timeout):
      acc_time = 0 # 表示累计轮询的时间
      while acc_time < timeout:
           s = request_state()
           if s in expect_state:
                 return True, s
           time.sleep(interval)
           acc_time += interval
    else:
          return False, s

另一种写法

def watch_job(expect_state, interval, timeout):
      times = timeout // interval # 表示预期轮询的轮数
      cnt = 0 # 表示累计轮询的次数
      while cnt < times:
           s = request_state()
           if s in expect_state:
                 return True, s
           time.sleep(interval)
           cnt += 1
     else:
          return False, s

以下对比两种写法的微妙差异:

  • 第一种方法当 interval 传入0 值之后,有可能陷入一个死循环,而第二种会引起一个除零错误——这会被立刻发现
  • 对于interval 负值的情况,第一种仍然是一个死循环,而第二种马上会结束
    第二种写法,只会出现异常,而不会引起死循环。

当然,第一种写法节省了一个变量

在安全性方面,似乎第二种写法更具有稳定性
现在考虑另一个问题 —— timeout是60s 的话,实际轮询时间会是多少?
这取决于 request_state 接口的好是,两种写法都没有考虑把 request_state 的耗时纳入考量,这显得 timeout 实际上是个假时间,如果确切一点的话,这个命名可以改成次数上限一类的名字

写成下面的的样子

def watch_job(expect_state, interval, times):
      cnt = 0 # 表示累计轮询的次数
      while cnt < times:
           s = request_state()
           if s in expect_state:
                 return True, s
           time.sleep(interval)
           cnt += 1
     else:
          return False, s

request_state 会可能耗时很长,可能触发异常
那么实际轮询的上限时间会不太确定,只是大概能估计它的范围而已。

考虑稳定性,我们可能还需要对 request_state 包上try-except 语句块,让它在爆出异常的时候不会立刻结束轮询

总之,对于一个长时间的控制块,设计程序时应当尽量避免死循环,内存泄露等等让人难以debug的错误引入。

相关文章

网友评论

      本文标题:一个超时轮询的工作任务

      本文链接:https://www.haomeiwen.com/subject/hadmcjtx.html