我目前正在使用Twisted框架设计一个应用程序,我在计划中遇到了一些障碍。
我的应用程序有以下限制:
对我的问题的描述可能会提醒人们功能反应式编程(FRP)范例,这是一个公平的比较。事实上,我认为我的问题在这些术语中得到了很好的描述,因此我可以非常准确地总结我的问题:“我如何利用Twisted以这种方式来推理数据流?”
更具体地说,这是我已经想出来的:
collections.deque
对象,由自定义Stream
类封装。 Stream
类公开Stream.map
等方法,将非阻塞计算异步应用于:
Stream
实例的deque中已存在的所有元素。第3项中执行的操作的结果将附加到新 Stream
对象。这是因为保留原始数据很重要,因为通常需要将几个可调用的数据映射到给定的流。
冒着击败死马的风险,我想坚持这样一个事实,即映射到Stream
实例的计算应该返回Deferred
的实例。
顺便说一下,这正是我被困住的地方:我可以实施第1,2和第2项。 3非常简单,但我正在努力处理如何处理结果Stream
。困难源于我无法保证流长度,因此在我等待一些异步操作完成时,数据完全可能到达。在 O i + n 之后完成异步操作 O i 也是完全可能的,所以我不能只需添加deque.append
作为回调。
那我该如何处理这个问题呢?是否有一些狡猾,隐藏的Twisted特征尚未发现?任何曲折的开发者都有我可以应用的想法或模式吗?
答案 0 :(得分:2)
我不知道任何可以帮助你的巧妙技巧。我认为您可能只需在Stream.map
实施中实施重新排序(或订单维护,具体取决于您的看法)。
如果操作i + 1在操作之前完成,那么Stream.map
可能只需要保持该结果直到操作i完成。然后它可以将结果i和i + 1添加到输出Stream
。
这表明您可能还希望支持输入的背压。重新排序要求意味着您的应用程序中有一个额外的缓冲区。你不希望允许缓冲区无限制地增长,所以当它达到某个最大尺寸时,你可能想要告诉那些发送你输入的人你不能跟上并且他们应该退出。 Twisted中的IProducer
和IConsumer
接口是现在执行此操作的标准方法(尽管称为" tube"已经开发了一段时间以更容易地替换这些接口使用 - 但我不会建议你屏住呼吸。