Class: Pindo::TaskSystem::PindoTask
- Inherits:
-
Object
- Object
- Pindo::TaskSystem::PindoTask
- Defined in:
- lib/pindo/module/task/pindo_task.rb
Overview
PindoTask 基类(简化版,所有任务在主线程中执行)
Direct Known Subclasses
AppStoreTask, BuildTask, GitTask, IpaLocalResignTask, JPSTask, UnityTask
Instance Attribute Summary collapse
-
#callbacks_setup ⇒ Object
标记回调是否已经设置.
-
#context ⇒ Object
Returns the value of attribute context.
-
#created_at ⇒ Object
readonly
Returns the value of attribute created_at.
-
#dependencies ⇒ Object
readonly
Returns the value of attribute dependencies.
-
#error ⇒ Object
Returns the value of attribute error.
-
#finished_at ⇒ Object
readonly
Returns the value of attribute finished_at.
-
#id ⇒ Object
Returns the value of attribute id.
-
#max_retry_count ⇒ Object
readonly
max_retry_count: 初始最大重试次数.
-
#metadata ⇒ Object
Returns the value of attribute metadata.
-
#name ⇒ Object
Returns the value of attribute name.
-
#priority ⇒ Object
readonly
Returns the value of attribute priority.
-
#result ⇒ Object
Returns the value of attribute result.
-
#retry_count ⇒ Object
剩余重试次数.
-
#retry_delay ⇒ Object
readonly
max_retry_count: 初始最大重试次数.
-
#retry_mode ⇒ Object
readonly
max_retry_count: 初始最大重试次数.
-
#skip_count ⇒ Object
因资源不足被跳过的次数.
-
#started_at ⇒ Object
readonly
Returns the value of attribute started_at.
-
#status ⇒ Object
Returns the value of attribute status.
-
#task_key ⇒ Object
readonly
Returns the value of attribute task_key.
-
#task_manager ⇒ Object
TaskManager 实例(依赖注入).
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Class Method Summary collapse
- .default_retry_count ⇒ Object
- .default_retry_delay ⇒ Object
-
.default_retry_mode ⇒ Object
默认重试配置.
- .task_key ⇒ Object
-
.task_type ⇒ Object
子类必须实现的方法.
Instance Method Summary collapse
- #before_retry ⇒ Object
-
#cancel ⇒ Object
取消任务.
-
#cancelled? ⇒ Boolean
检查是否已取消(不抛异常).
-
#check_cancelled! ⇒ Object
检查是否已取消,如果已取消则抛出异常.
-
#data_param ⇒ Hash
获取任务的数据参数(用于传递给其他任务).
-
#do_task ⇒ Object
执行任务(在主线程中同步执行).
-
#execution_time ⇒ Object
执行时间.
-
#finished? ⇒ Boolean
检查是否完成.
-
#get_all_data_params ⇒ Array<Hash>
获取所有依赖任务的数据参数.
-
#get_all_data_params_by_key(task_key) ⇒ Array<Hash>
获取所有指定 task_key 的数据参数.
-
#get_all_dependencies_results ⇒ Hash
获取所有依赖任务的结果(按依赖顺序).
-
#get_data_param(task_id) ⇒ Hash?
获取指定数据依赖任务的数据参数.
-
#get_data_param_by_key(task_key) ⇒ Hash?
根据 task_key 获取依赖任务的数据参数.
-
#get_dependency_result(dep_task_id) ⇒ Hash?
获取指定依赖任务的结果.
-
#get_dependency_task(dep_task_id) ⇒ PindoTask?
获取指定依赖任务.
-
#initialize(name, options = {}) ⇒ PindoTask
constructor
A new instance of PindoTask.
-
#on(event, &block) ⇒ Object
添加回调.
-
#primary_data_param ⇒ Hash?
获取主数据参数(第一个依赖任务的参数).
-
#release_resource(resource_spec) ⇒ Object
提前释放资源 释放 required_resources 中声明的资源,允许其他任务使用.
-
#release_resources(resource_specs) ⇒ Object
批量释放资源(release_resource 的别名).
-
#required_resources ⇒ Array<Hash>
获取任务需要的资源(子类覆盖以声明所需资源) 资源规格格式: { type: :xcode, directory: “/path/to/project” } # 基于目录的资源 { type: :keychain } # 全局资源.
- #reset_for_retry ⇒ Object
-
#retryable? ⇒ Boolean
重试相关方法.
-
#running? ⇒ Boolean
是否正在运行.
- #should_retry?(error) ⇒ Boolean
-
#validate ⇒ Object
验证任务是否可以执行.
-
#with_resource(resource_spec, timeout: 30) { ... } ⇒ Object
临时锁定资源(块语法,推荐使用) 在代码块执行期间锁定资源,自动释放.
-
#with_resources(resource_specs, timeout: 30) { ... } ⇒ Object
批量临时锁定资源(with_resource 的别名).
Constructor Details
#initialize(name, options = {}) ⇒ PindoTask
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/pindo/module/task/pindo_task.rb', line 80 def initialize(name, = {}) @id = SecureRandom.uuid @name = name @type = self.class.task_type @task_key = self.class.task_key @priority = [:priority] || TaskPriority::HIGH @status = TaskStatus::PENDING @dependencies = [:dependencies] || [] @context = [:context] || {} @metadata = [:metadata] || {} @error = nil @result = nil @created_at = Time.now @started_at = nil @finished_at = nil @callbacks = { before: [], after: [], on_success: [], on_failure: [] } @callbacks_setup = false # 重试配置 @retry_mode = [:retry_mode] || self.class.default_retry_mode @retry_count = [:retry_count] || self.class.default_retry_count @max_retry_count = @retry_count # 保存初始最大重试次数 @retry_delay = [:retry_delay] || self.class.default_retry_delay @skip_count = 0 # 记录因资源不足被跳过的次数(用于解决饥饿问题) end |
Instance Attribute Details
#callbacks_setup ⇒ Object
标记回调是否已经设置
43 44 45 |
# File 'lib/pindo/module/task/pindo_task.rb', line 43 def callbacks_setup @callbacks_setup end |
#context ⇒ Object
Returns the value of attribute context.
39 40 41 |
# File 'lib/pindo/module/task/pindo_task.rb', line 39 def context @context end |
#created_at ⇒ Object (readonly)
Returns the value of attribute created_at.
40 41 42 |
# File 'lib/pindo/module/task/pindo_task.rb', line 40 def created_at @created_at end |
#dependencies ⇒ Object (readonly)
Returns the value of attribute dependencies.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def dependencies @dependencies end |
#error ⇒ Object
Returns the value of attribute error.
37 38 39 |
# File 'lib/pindo/module/task/pindo_task.rb', line 37 def error @error end |
#finished_at ⇒ Object (readonly)
Returns the value of attribute finished_at.
40 41 42 |
# File 'lib/pindo/module/task/pindo_task.rb', line 40 def finished_at @finished_at end |
#id ⇒ Object
Returns the value of attribute id.
37 38 39 |
# File 'lib/pindo/module/task/pindo_task.rb', line 37 def id @id end |
#max_retry_count ⇒ Object (readonly)
max_retry_count: 初始最大重试次数
42 43 44 |
# File 'lib/pindo/module/task/pindo_task.rb', line 42 def max_retry_count @max_retry_count end |
#metadata ⇒ Object
Returns the value of attribute metadata.
39 40 41 |
# File 'lib/pindo/module/task/pindo_task.rb', line 39 def @metadata end |
#name ⇒ Object
Returns the value of attribute name.
37 38 39 |
# File 'lib/pindo/module/task/pindo_task.rb', line 37 def name @name end |
#priority ⇒ Object (readonly)
Returns the value of attribute priority.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def priority @priority end |
#result ⇒ Object
Returns the value of attribute result.
37 38 39 |
# File 'lib/pindo/module/task/pindo_task.rb', line 37 def result @result end |
#retry_count ⇒ Object
剩余重试次数
41 42 43 |
# File 'lib/pindo/module/task/pindo_task.rb', line 41 def retry_count @retry_count end |
#retry_delay ⇒ Object (readonly)
max_retry_count: 初始最大重试次数
42 43 44 |
# File 'lib/pindo/module/task/pindo_task.rb', line 42 def retry_delay @retry_delay end |
#retry_mode ⇒ Object (readonly)
max_retry_count: 初始最大重试次数
42 43 44 |
# File 'lib/pindo/module/task/pindo_task.rb', line 42 def retry_mode @retry_mode end |
#skip_count ⇒ Object
因资源不足被跳过的次数
45 46 47 |
# File 'lib/pindo/module/task/pindo_task.rb', line 45 def skip_count @skip_count end |
#started_at ⇒ Object (readonly)
Returns the value of attribute started_at.
40 41 42 |
# File 'lib/pindo/module/task/pindo_task.rb', line 40 def started_at @started_at end |
#status ⇒ Object
Returns the value of attribute status.
37 38 39 |
# File 'lib/pindo/module/task/pindo_task.rb', line 37 def status @status end |
#task_key ⇒ Object (readonly)
Returns the value of attribute task_key.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def task_key @task_key end |
#task_manager ⇒ Object
TaskManager 实例(依赖注入)
44 45 46 |
# File 'lib/pindo/module/task/pindo_task.rb', line 44 def task_manager @task_manager end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def type @type end |
Class Method Details
.default_retry_count ⇒ Object
125 126 127 |
# File 'lib/pindo/module/task/pindo_task.rb', line 125 def self.default_retry_count 0 # 默认不重试 end |
.default_retry_delay ⇒ Object
129 130 131 |
# File 'lib/pindo/module/task/pindo_task.rb', line 129 def self.default_retry_delay 10 # 默认延迟 10 秒 end |
.default_retry_mode ⇒ Object
默认重试配置
121 122 123 |
# File 'lib/pindo/module/task/pindo_task.rb', line 121 def self.default_retry_mode RetryMode::IMMEDIATE end |
.task_key ⇒ Object
116 117 118 |
# File 'lib/pindo/module/task/pindo_task.rb', line 116 def self.task_key raise NotImplementedError, "Subclass must define task_key" end |
.task_type ⇒ Object
子类必须实现的方法
112 113 114 |
# File 'lib/pindo/module/task/pindo_task.rb', line 112 def self.task_type raise NotImplementedError, "Subclass must define task_type" end |
Instance Method Details
#before_retry ⇒ Object
370 371 372 |
# File 'lib/pindo/module/task/pindo_task.rb', line 370 def before_retry # 子类可重写,进行重试前的清理工作 end |
#cancel ⇒ Object
取消任务
154 155 156 157 158 159 160 161 |
# File 'lib/pindo/module/task/pindo_task.rb', line 154 def cancel if @status == TaskStatus::PENDING @status = TaskStatus::CANCELLED true else false end end |
#cancelled? ⇒ Boolean
检查是否已取消(不抛异常)
178 179 180 |
# File 'lib/pindo/module/task/pindo_task.rb', line 178 def cancelled? @status == TaskStatus::CANCELLED end |
#check_cancelled! ⇒ Object
检查是否已取消,如果已取消则抛出异常
171 172 173 174 175 |
# File 'lib/pindo/module/task/pindo_task.rb', line 171 def check_cancelled! if @status == TaskStatus::CANCELLED raise TaskCancelledException.new("任务已被取消: #{@name}") end end |
#data_param ⇒ Hash
获取任务的数据参数(用于传递给其他任务)
216 217 218 219 220 221 222 223 224 |
# File 'lib/pindo/module/task/pindo_task.rb', line 216 def data_param { task_id: @id, task_type: @type, task_key: @task_key, task_name: @name, task_param: build_task_param } end |
#do_task ⇒ Object
执行任务(在主线程中同步执行)
134 135 136 |
# File 'lib/pindo/module/task/pindo_task.rb', line 134 def do_task execute_internal end |
#execution_time ⇒ Object
执行时间
164 165 166 167 168 |
# File 'lib/pindo/module/task/pindo_task.rb', line 164 def execution_time return nil unless @started_at end_time = @finished_at || Time.now end_time - @started_at end |
#finished? ⇒ Boolean
检查是否完成
139 140 141 |
# File 'lib/pindo/module/task/pindo_task.rb', line 139 def finished? [TaskStatus::SUCCESS, TaskStatus::FAILED, TaskStatus::CANCELLED].include?(@status) end |
#get_all_data_params ⇒ Array<Hash>
获取所有依赖任务的数据参数
238 239 240 |
# File 'lib/pindo/module/task/pindo_task.rb', line 238 def get_all_data_params @dependencies.map { |task_id| get_data_param(task_id) }.compact end |
#get_all_data_params_by_key(task_key) ⇒ Array<Hash>
获取所有指定 task_key 的数据参数
256 257 258 |
# File 'lib/pindo/module/task/pindo_task.rb', line 256 def get_all_data_params_by_key(task_key) get_all_data_params.select { |param| param[:task_key] == task_key } end |
#get_all_dependencies_results ⇒ Hash
获取所有依赖任务的结果(按依赖顺序)
204 205 206 207 208 209 210 |
# File 'lib/pindo/module/task/pindo_task.rb', line 204 def get_all_dependencies_results results = {} @dependencies.each do |dep_id| results[dep_id] = get_dependency_result(dep_id) end results end |
#get_data_param(task_id) ⇒ Hash?
获取指定数据依赖任务的数据参数
229 230 231 232 233 234 |
# File 'lib/pindo/module/task/pindo_task.rb', line 229 def get_data_param(task_id) dep_task = get_dependency_task(task_id) return nil unless dep_task return nil unless dep_task.finished? && dep_task.status == TaskStatus::SUCCESS dep_task.data_param end |
#get_data_param_by_key(task_key) ⇒ Hash?
根据 task_key 获取依赖任务的数据参数
245 246 247 248 249 250 251 |
# File 'lib/pindo/module/task/pindo_task.rb', line 245 def get_data_param_by_key(task_key) @dependencies.each do |task_id| param = get_data_param(task_id) return param if param && param[:task_key] == task_key end nil end |
#get_dependency_result(dep_task_id) ⇒ Hash?
获取指定依赖任务的结果
195 196 197 198 199 200 |
# File 'lib/pindo/module/task/pindo_task.rb', line 195 def get_dependency_result(dep_task_id) dep_task = get_dependency_task(dep_task_id) return nil unless dep_task return nil unless dep_task.finished? dep_task.result end |
#get_dependency_task(dep_task_id) ⇒ PindoTask?
获取指定依赖任务
187 188 189 190 |
# File 'lib/pindo/module/task/pindo_task.rb', line 187 def get_dependency_task(dep_task_id) return nil unless @task_manager @task_manager.find_task(dep_task_id) end |
#on(event, &block) ⇒ Object
添加回调
357 358 359 |
# File 'lib/pindo/module/task/pindo_task.rb', line 357 def on(event, &block) @callbacks[event] << block if @callbacks[event] end |
#primary_data_param ⇒ Hash?
获取主数据参数(第一个依赖任务的参数)
262 263 264 265 |
# File 'lib/pindo/module/task/pindo_task.rb', line 262 def primary_data_param return nil if @dependencies.empty? get_data_param(@dependencies.first) end |
#release_resource(resource_spec) ⇒ Object
提前释放资源释放 required_resources 中声明的资源,允许其他任务使用
339 340 341 342 343 344 345 346 |
# File 'lib/pindo/module/task/pindo_task.rb', line 339 def release_resource(resource_spec) raise RuntimeError, "Task not running (task_manager is nil)" unless @task_manager resource_manager = @task_manager.resource_lock_manager resource_specs = [resource_spec].flatten resource_manager.release_partial(resource_specs, @id) end |
#release_resources(resource_specs) ⇒ Object
批量释放资源(release_resource 的别名)
350 351 352 |
# File 'lib/pindo/module/task/pindo_task.rb', line 350 def release_resources(resource_specs) release_resource(resource_specs) end |
#required_resources ⇒ Array<Hash>
获取任务需要的资源(子类覆盖以声明所需资源)资源规格格式:
{ type: :xcode, directory: "/path/to/project" } # 基于目录的资源
{ type: :keychain } # 全局资源
76 77 78 |
# File 'lib/pindo/module/task/pindo_task.rb', line 76 def required_resources [] # 默认不需要资源 end |
#reset_for_retry ⇒ Object
374 375 376 377 378 379 |
# File 'lib/pindo/module/task/pindo_task.rb', line 374 def reset_for_retry @status = TaskStatus::PENDING @result = nil @started_at = nil @finished_at = nil end |
#retryable? ⇒ Boolean
重试相关方法
362 363 364 |
# File 'lib/pindo/module/task/pindo_task.rb', line 362 def retryable? @retry_count > 0 end |
#running? ⇒ Boolean
是否正在运行
144 145 146 |
# File 'lib/pindo/module/task/pindo_task.rb', line 144 def running? @status == TaskStatus::RUNNING end |
#should_retry?(error) ⇒ Boolean
366 367 368 |
# File 'lib/pindo/module/task/pindo_task.rb', line 366 def should_retry?(error) true # 默认所有错误都重试,子类可重写 end |
#validate ⇒ Object
验证任务是否可以执行
149 150 151 |
# File 'lib/pindo/module/task/pindo_task.rb', line 149 def validate true end |
#with_resource(resource_spec, timeout: 30) { ... } ⇒ Object
临时锁定资源(块语法,推荐使用)在代码块执行期间锁定资源,自动释放
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/pindo/module/task/pindo_task.rb', line 290 def with_resource(resource_spec, timeout: 30) raise ArgumentError, "Block required" unless block_given? raise RuntimeError, "Task not running (task_manager is nil)" unless @task_manager resource_manager = @task_manager.resource_lock_manager resource_specs = [resource_spec].flatten # 阻塞式获取资源 success = resource_manager.acquire_blocking(resource_specs, @id, timeout: timeout) unless success raise ResourceLockTimeout, "无法获取资源: #{resource_specs.inspect}(超时#{timeout}秒)" end begin yield # 执行代码块 ensure # 自动释放临时资源 resource_manager.release_partial(resource_specs, @id) end end |
#with_resources(resource_specs, timeout: 30) { ... } ⇒ Object
批量临时锁定资源(with_resource 的别名)
316 317 318 |
# File 'lib/pindo/module/task/pindo_task.rb', line 316 def with_resources(resource_specs, timeout: 30, &block) with_resource(resource_specs, timeout: timeout, &block) end |