4

这里的 Node.js 开发人员必须使用 Ruby,所以我对 Ruby 中的很多概念都很陌生,可以使用一些帮助。

我的用例是我必须从 S3 下载非常大的以换行符分隔的 JSON 文件,转换数据,然后将其放回 S3,所有这些都在内存中,而无需将任何内容写入磁盘。

在 Node 中,我可以这样做:

s3DownloadStream('my-file').pipe(transformStream).pipe(backToS3Stream)

这将在对象进入时即时转换对象并将它们同时放入 S3。

我很难找到一个好的行动计划来在 Ruby 中实现同样的行为。我已经看到 IO.pipe 和 Celluloid::IO 作为可能的选项,但它们似乎仍然不太可能做到这一点。

4

1 回答 1

1

Ruby 没有直接模拟 Node 中的流,但它有 Enumerable 迭代器框架,并且通过它有Lazy选项。惰性枚举器是只在必要时发出数据的枚举器,不像其他枚举器每次都会运行到完成。

如果你设置了一个惰性链,它会一点一点地评估,而不是一次全部评估。

所以你的代码看起来像:

s3_download('my-file').lazy.map do |...|
  # transform stream
end.each do |...|
  # pipe back to S3
end

这是一个可以构建的简单示例:

input = ('a'..'z')

input.lazy.map do |i|
  puts 'i=%s' % i

  i.upcase
end.each do |j|
  puts '  j=%s' % j
end

您可以看到每个值如何分别在链中波动。如果您删除lazy不是这种情况,则第一个循环会运行到完成,缓冲到一个数组中,然后第二个循环也会启动并处理它以完成。

节点流比这复杂得多,它们可以做一些事情,比如暂停/恢复、延迟操作而不阻塞等等,所以在功能方面只有这么多的重叠。如果你花时间使用纤维和线程之类的东西,Ruby 可以做到这一点,但这是很多工作。

于 2017-02-17T02:54:21.430 回答