Ruby on rails 在Ruby中运行线程的链接方法

Ruby on rails 在Ruby中运行线程的链接方法,ruby-on-rails,ruby,multithreading,Ruby On Rails,Ruby,Multithreading,我有4个需要时间的任务,每个任务取决于前一个任务 e、 g 任务1-克隆git回购 任务2-使用配置文件初始化repo 任务3-处理回购协议 任务4-处理后将结果存储在db中 现在,所有这些任务都将在线程上运行,我正在尝试用不同的方法将所有这4个任务分开,这些方法运行线程并启动任务 我不知道如何将这4种方法链接在一起,但仍然可以从上一种方法得到结果,以便在下一种方法中使用 在方法中分离这些步骤的主要原因是,我可以直接从步骤3开始,在某些情况下完全跳过上一步 def clone_repo(url)

我有4个需要时间的任务,每个任务取决于前一个任务

e、 g

任务1-克隆git回购

任务2-使用配置文件初始化repo

任务3-处理回购协议

任务4-处理后将结果存储在db中

现在,所有这些任务都将在线程上运行,我正在尝试用不同的方法将所有这4个任务分开,这些方法运行线程并启动任务

我不知道如何将这4种方法链接在一起,但仍然可以从上一种方法得到结果,以便在下一种方法中使用

在方法中分离这些步骤的主要原因是,我可以直接从步骤3开始,在某些情况下完全跳过上一步

def clone_repo(url)
  Thread.new do
    # clone the repo
    # change the status in db
  end
end

def init_repo(repo)
  Thread.new do
    # init config files
    # change the status in db
  end
end

def process_repo(repo)
  Thread.new do
    # process repo
    # change the status in db
    # return or do something with the results to use it in next method
  end
end

def store_results(results)
  Thread.new do
    # store in db
    # change the status in db
  end
end

我可以朝解决问题的任何方向前进,只需要一种重构的方法来解决这个问题。

如果您确实需要在方法内部启动线程(而不是在方法周围,这将使任务更容易),您可以为每个任务使用互斥锁,在相应的任务完成时初始化为锁定和释放,所以,下一个试图在开始时锁定它的依赖线程将等待。 如果不需要任务-只需解锁而不运行

编辑:添加示例结构:

class SomeRepoJob

  def perform_in_thread
    Thread.new do
      perform
    end
  end

  def perform
    clone_repo
    init_config
    results = process_repo
    store_results results if results
  rescue => e
    #do some error reporting if needed
  end


  private

  def set_db_status status
    # here you can mark task as "#{status}_started"
    yield
    # change the status in db
  rescue
    # revert status on failure
    raise
  end

  def repo_is_cloned?
    File.exists?(...)
  end

  def clone_repo(url)
    set_db_status(:cloned){
      unless repo_is_cloned?
        # clone the repo
      end
    }
  end

  def config_exists_and_valid?
    File.exists? ...
    # some config check and validation
  end

  def init_config(repo)
    set_db_status(:inited_config){
      unless config_exists_and_valid?
        # init config files
      end
    }
  end

  def processed?
    # somehow check if processing is needed, or always return false
  end

  def process_repo(repo)
    set_db_status(:processed_not_stored){
      unless processed?
        # process repo
        results
      else
        results = read_results
      end
      return results
    }
  end

  def results_stored? results
    #...
  end

  def store_results(results)
    set_db_status(:stored_results){
      unless results_stored? results
        # store in db
      end
    }
  end
end

我可以使用你建议的任何东西,这将有助于完成所需的工作。我建议将可选任务设为幂等(这样即使不需要也可以运行它们-例如克隆任务可以检查repo是否已经存在,等等),并将它们链接到一个线程中,使用我想到的单一入口点,因为我每一步都在改变状态,所以我可以检查一下。但是对于重构代码,我采用了这种方法。无论如何,没有必要让单独的线程永远不能并行运行。那么,如何重构运行线程并执行所有这4项任务的方法呢?因为这肯定会超过100 LOC。