首先,哇,Rails 1.2.7。我有一个同样老旧的应用程序正在工作,我正在慢慢升级到 Rails 3。这些东西变化得有多快。
绝对是一个有趣的问题。你可以采取很多方向,我不确定哪个是最好的,因为我不确定我是否理解你的过程。所以我会推荐一对。我的理解是1)上传文件,2)开始转换,3)通过ajax轮询报告转换状态。
首先,正如您所发现的,在 Rails 控制器操作中运行转换实用程序绝对不是可行的方法。 1) 您的 Web 服务器或浏览器可能会终止请求,并且 2) 大多数 Rails 部署允许每个应用程序一次仅 1 个请求,这意味着如果您想要 5 个同时上传的用户,您需要运行 5 个应用程序副本。显然这不会扩展。
您的“上传”操作应该尽可能快。它应该 1) 上传文件,以及 2) 安排或启动“转换作业”,由其他进程处理。然后,您的轮询操作将仅报告该作业的状态。当然,问题是其他流程应该是什么。
想法 1
http://geekblog.vodpod.com/2007/08/17/background-processing-in-rails/ 可能是一个很好的起点,尽管我不能保证这种方法。
想法 2
我做过类似的事情,所以我可以提供更多细节。它可能会更好地扩展。使用 Sinatra 或 Async Sinatra 构建轻量级配套应用程序。您的 Rails 应用程序会在您的数据库中记录上传文件的作业,但随后它的部分就完成了。您的 Sinatra 应用程序使用 EventMachine 每隔几秒轮询一次数据库并开始新的工作。您可能希望将其限制为 n 个并发作业,这样您就不会 DOS 自己的盒子 :) 您的用户然后可以轮询您的 Sinatra 应用程序以获取他们的转换状态。
想法 3
与 2 类似,但它不是一个配套的 Web 应用程序,它只是一个使用 EventMachine 的小型 Ruby 程序。你只需在你的服务器上启动这个程序,让它永远运行。每个作业都会将其状态写回数据库,您的用户可以通过您的 Rails 应用程序轮询该数据库。我想这是我最喜欢的。线框:
#!/usr/bin/env ruby
require 'rubygems'
require 'eventmachine'
# Returns new jobs from the database
def new_jobs
[]
end
# Convert the file
def convert(job)
`convert #{job.path}`
job
end
# Callback when conversion is complete
def callback(job)
puts "Finished #{job.path}!"
end
EventMachine::run do
# Run every 5 seconds
EventMachine::add_periodic_timer(5) do
new_jobs.each { |job| EventMachine::defer convert(job), callback(job) }
end
end
诚然,这些建议是从 10,000 英尺的角度来看的,但我希望其中有一些东西可以帮助您入门。