如何将异步操作映射到有序的数据流并获得相同排序的结果?

时间:2014-11-06 22:36:23

标签: python stream twisted frp

我目前正在使用Twisted框架设计一个应用程序,我在计划中遇到了一些障碍。

问题的形式描述

我的应用程序有以下限制:

  1. 数据按顺序到达,但是异步。我不知道下一条数据何时到达
  2. 必须在申请流程的整个生命周期内保留数据到达的顺序。
  3. 必须将其他异步操作映射到此“数据流”。
  4. 对我的问题的描述可能会提醒人们功能反应式编程(FRP)范例,这是一个公平的比较。事实上,我认为我的问题在这些术语中得到了很好的描述,因此我可以非常准确地总结我的问题:“我如何利用Twisted以这种方式来推理数据流?”

    更具体地说,这是我已经想出来的:

    1. 数据到达并被解压缩到自定义类的实例中,此后称为“基准实例”
    2. 新到达的基准实例附加到collections.deque对象,由自定义Stream类封装。
    3. Stream类公开Stream.map等方法,将非阻塞计算异步应用于:

      1. Stream实例的deque中已存在的所有元素。
      2. 所有未来的元素,当它们到达时。
    4. 第3项中执行的操作的结果将附加到 Stream对象。这是因为保留原始数据很重要,因为通常需要将几个可调用的数据映射到给定的流。

    5. 冒着击败死马的风险,我想坚持这样一个事实,即映射到Stream实例的计算应该返回Deferred的实例。

      问题

      顺便说一下,这正是我被困住的地方:我可以实施第1,2和第2项。 3非常简单,但我正在努力处理如何处理结果Stream。困难源于我无法保证流长度,因此在我等待一些异步操作完成时,数据完全可能到达。在 O i + n 之后完成异步操作 O i 也是完全可能的,所以我不能只需添加deque.append作为回调。

      那我该如何处理这个问题呢?是否有一些狡猾,隐藏的Twisted特征尚未发现?任何曲折的开发者都有我可以应用的想法或模式吗?

1 个答案:

答案 0 :(得分:2)

我不知道任何可以帮助你的巧妙技巧。我认为您可能只需在Stream.map实施中实施重新排序(或订单维护,具体取决于您的看法)。

如果操作i + 1在操作之前完成,那么Stream.map可能只需要保持该结果直到操作i完成。然后它可以将结果i和i + 1添加到输出Stream

这表明您可能还希望支持输入的背压。重新排序要求意味着您的应用程序中有一个额外的缓冲区。你不希望允许缓冲区无限制地增长,所以当它达到某个最大尺寸时,你可能想要告诉那些发送你输入的人你不能跟上并且他们应该退出。 Twisted中的IProducerIConsumer接口是现在执行此操作的标准方法(尽管称为" tube"已经开发了一段时间以更容易地替换这些接口使用 - 但我不会建议你屏住呼吸。