gpt4 book ai didi

不同类之间的 Ruby TempFile 行为

转载 作者:行者123 更新时间:2023-12-05 07:04:20 24 4
gpt4 key购买 nike

我们的处理服务器主要与 TempFiles 一起工作,因为它使我们这边的事情变得更容易:无需注意删除它们,因为它们会被垃圾收集或处理名称冲突等。

最近,我们遇到了 TempFiles 在此过程中过早进行 GC 处理的问题。特别是我们的一项服务会将 Foo 文件从 url 转换为某个 Bar 文件并将其上传到我们的服务器。

为了清楚起见,我在下面添加了一个案例场景,以便于讨论并手头有一个例子。

此工作流程执行以下操作:

  1. 获取一个url作为参数
  2. 将 Foo 文件下载为临时文件
  3. 将其复制到一个新的临时文件
  4. 将相关 Assets 下载到临时文件
  5. 将相关 Assets 链接到本地​​dup TempFile
  6. 将 Foo 格式转换为 Bar 格式
  7. 上传到我们的服务器

有时转换失败,一切都表明我们的本地 Foo 文件指向转换前已创建和 GC 的相关 Assets 。

我的两个问题:

  1. 我的 TempFile 是否有可能过早被 GC 处理?我读到了 Ruby GCed 系统,它非常保守地避免了这些情况。

  2. 如何避免这种情况发生?我可以尝试从 download_and_replace_uri(node) 中保存所有相关 Assets ,并将它们作为返回值传递,以在 ConvertService 实例仍然存在时保持其事件状态。但我不确定这是否会解决问题。

我的文件.foo

{
"buffers": [
{ "uri": "http://example.com/any_file.jpg" },
{ "uri": "http://example.com/any_file.png" },
{ "uri": "http://example.com/any_file.jpmp3" }
]
}

ma​​in.rb

  ConvertService.new('http://example.com/myfile.foo')

转化服务

class ConvertService
def initialize(url)
@url = url
@bar_file = Tempfile.new
end

def call
import_foo
convert_foo
upload_bar
end

private

def import_foo
@foo_file = ImportService.new(@url).call.edited_file
end

def convert_foo
`create-bar "#{@foo_file.path}" "#{@bar_file.path}"`
end

def upload_bar
UploadBarService.new(@bar_file).call
end
end

导入服务

class ImportService
def initialize(url)
@url = url
@edited_file ||= Tempfile.new
end

def call
download
duplicate
replace
end

private

def download
@original = DownloadFileService.new(@url).call.file
end

def duplicate
FileUtils.cp(@original.path, @edited_file.path)
end

def replace
file = File.read(@edited_file.path)
json = JSON.parse(file, symbolize_names: true)
json[:buffers]&.each do |node|
node[:uri] = DownloadFileService.new(node[:uri]).call.file.path
end
write_to_disk(@edited_file.path, json.to_json)
end
end

下载文件服务

module Helper
class DownloadFileService < ApplicationHelperService
def initialize(url)
@url = url
@file = Tempfile.new
end

def call
uri = URI.parse(@url)
Net::HTTP.start(
uri.host,
uri.port,
use_ssl: uri.scheme == 'https'
) do |http|
response = http.request(Net::HTTP::Get.new(uri.path))
@file.binmode
@file.write(response.body)
@file.flush
end
end
end
end

上传栏服务

module Helper
class UploadBarService < ApplicationHelperService
def initialize(file)
@file = file
end

def call
HTTParty.post('http://example.com/upload', body: { file: @file })
# NOTE: End points returns the url for the uploaded file
end
end
end

最佳答案

由于您的代码的复杂性和遗漏的部分可能让我们感到困惑,对您的问题的简单回答是确保您的临时文件实例对象在需要它们的整个生命周期中都保留在内存中,否则它们将得到立即收集垃圾,从文件系统中删除临时文件,并将导致您遇到的丢失的临时文件状态。

Ruby Document for Tempfile states “当 Tempfile 对象被垃圾回收时,或者当 Ruby 解释器退出时,它的关联临时文件会自动删除。”

根据评论,其他人可能会发现 this conversation遇到这个问题时很有帮助。

关于不同类之间的 Ruby TempFile 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62950100/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com