2017-02-17 101 views
3

Node.js这里的开发人员必须和Ruby一起工作,所以我对Ruby中的很多概念都很陌生,可以使用一些帮助。内存在Ruby中转换流?

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

在节点,我可以做这样的事情:

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

这将改变在运行的对象,因为他们进来,把他们S3兼任。

我很难找到一个很好的行动计划,以在Ruby中实现相同的行为。我已经看到IO.pipe和Celluloid :: IO作为可能的选择,但他们似乎还不像他们能够做到这一点。

+0

也许这将有助于:https://aws.amazon.com/blogs/developer/downloading-objects-from-amazon-s3-using-the-aws-sdk-for-ruby/ –

+0

@AlexandreAngelim我看到了文章,但似乎是要将大文件下载到磁盘或内存IO。在那篇文章中,我没有看到任何能够通过变换来下载下载并同时回到s3的任何内容。我想我将不得不使用fork或Thread.new,但我希望得到一个真实世界的例子,这个例子有人在做一些类似的事情,我可以从中建立起来。 – aloisbarreras

+0

上面的链接可以让你获得大部分途径。查看“使用块”下的代码。不要将每个块写入文件,而是根据需要处理块,然后将结果上载到S3(使用,我假设,分段上传API)。 –

回答

0

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可以做到这一点,但这是很多工作。