2017-02-17 25 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可以做到這一點,但這是很多工作。