You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails项目Heroku环境下Sidekiq任务中临时文件丢失问题排查

问题排查与解决方案

核心原因

Heroku的dyno文件系统是独立且临时的:

  • Web dyno接收上传后存在tmp/uploads,但Sidekiq运行在单独的worker dyno,两个dyno的文件系统完全隔离,worker根本无法访问web dyno里的临时文件
  • 即使是同一个dyno,Heroku会在请求结束后定期清理临时文件,Sidekiq异步执行时文件可能已被删除

页面能显示图片是因为当前web dyno的临时文件尚未被清理,但worker dyno完全访问不到该路径。

解决方案步骤

1. 替换本地临时存储为直接上传到Cloudinary

不再依赖Heroku的本地tmp目录,上传时直接把文件传到Cloudinary获取资源标识,将这些信息传给Sidekiq Job,而非本地文件路径:

# 控制器修改示例
def associate_photos
  # 直接上传到Cloudinary并收集资源信息
  photo_data = params[:photos].map do |photo|
    upload_result = Cloudinary::Uploader.upload(photo.tempfile, folder: 'tmp_ingredients', use_filename: true)
    { public_id: upload_result['public_id'], url: upload_result['secure_url'] }
  end
  AssociatePhotosJob.perform_later(ingredient_id: params[:ingredient_id], photos: photo_data)
  redirect_to review_photos_path, notice: '照片关联任务已启动'
end

2. 修改Sidekiq Job与Service,使用Cloudinary资源而非本地文件

不再读取本地tmp/uploads的文件,直接用Cloudinary的public_id完成食材关联:

# AssociatePhotosJob 修改示例
class AssociatePhotosJob < ApplicationJob
  queue_as :default

  def perform(ingredient_id:, photos:)
    ingredient = Ingredient.find(ingredient_id)
    IngredientPhotoAssociator.new(ingredient, photos).associate
  end
end

# Service 修改示例
class IngredientPhotoAssociator
  def initialize(ingredient, photos)
    @ingredient = ingredient
    @photos = photos
  end

  def associate
    @photos.each do |photo_data|
      # 直接用Cloudinary资源信息创建关联
      @ingredient.photos.create!(
        cloudinary_public_id: photo_data[:public_id],
        url: photo_data[:url]
      )
    end
    # 可选:清理Cloudinary临时目录的文件
    Cloudinary::Api.delete_resources(photos.map { |p| p[:public_id] })
  end
end

3. 移除对Heroku本地tmp目录的依赖

删除代码中所有依赖tmp/uploads的逻辑,确保所有文件操作都通过Cloudinary完成。

4. 验证Heroku配置

  • 确认Cloudinary环境变量CLOUDINARY_URL已正确设置:
    heroku config:get CLOUDINARY_URL
    
  • 确保Sidekiq worker dyno已启动:
    heroku ps:scale worker=1
    

额外注意事项

  • 若必须保留临时存储步骤,可使用Heroku的共享存储插件(如AWS S3),但直接上传到Cloudinary是更轻量的方案
  • 测试时查看Sidekiq日志确认错误消除:
    heroku logs -t -s sidekiq
    

内容的提问来源于stack exchange,提问作者Quentin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:47:03