我有4个任务需要时间,每个任务都取决于之前的任务。
如,
任务1 - 克隆git repo
任务2 - 使用配置文件初始化仓库
任务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
我可以朝着解决问题的任何方向前进,只想要一种重构的方法来解决这个问题。
答案 0 :(得分:1)
如果你绝对需要在方法内部启动一个线程(而不是在它们周围,这会使任务更容易),你可以为每个任务使用一个互斥锁,初始化为锁定并在相应的任务完成时释放,所以下一个依赖的线程在尝试时在开始时锁定它将等待。 如果不需要任务 - 只需在不运行的情况下解锁
编辑:添加了示例结构:
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