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, NugetTask, 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
Returns a new instance of PindoTask.
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 110 |
# File 'lib/pindo/module/task/pindo_task.rb', line 81 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
标记回调是否已经设置
44 45 46 |
# File 'lib/pindo/module/task/pindo_task.rb', line 44 def callbacks_setup @callbacks_setup end |
#context ⇒ Object
Returns the value of attribute context.
40 41 42 |
# File 'lib/pindo/module/task/pindo_task.rb', line 40 def context @context end |
#created_at ⇒ Object (readonly)
Returns the value of attribute created_at.
41 42 43 |
# File 'lib/pindo/module/task/pindo_task.rb', line 41 def created_at @created_at end |
#dependencies ⇒ Object (readonly)
Returns the value of attribute dependencies.
39 40 41 |
# File 'lib/pindo/module/task/pindo_task.rb', line 39 def dependencies @dependencies end |
#error ⇒ Object
Returns the value of attribute error.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def error @error end |
#finished_at ⇒ Object (readonly)
Returns the value of attribute finished_at.
41 42 43 |
# File 'lib/pindo/module/task/pindo_task.rb', line 41 def finished_at @finished_at end |
#id ⇒ Object
Returns the value of attribute id.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def id @id end |
#max_retry_count ⇒ Object (readonly)
max_retry_count: 初始最大重试次数
43 44 45 |
# File 'lib/pindo/module/task/pindo_task.rb', line 43 def max_retry_count @max_retry_count end |
#metadata ⇒ Object
Returns the value of attribute metadata.
40 41 42 |
# File 'lib/pindo/module/task/pindo_task.rb', line 40 def @metadata end |
#name ⇒ Object
Returns the value of attribute name.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def name @name end |
#priority ⇒ Object (readonly)
Returns the value of attribute priority.
39 40 41 |
# File 'lib/pindo/module/task/pindo_task.rb', line 39 def priority @priority end |
#result ⇒ Object
Returns the value of attribute result.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def result @result end |
#retry_count ⇒ Object
剩余重试次数
42 43 44 |
# File 'lib/pindo/module/task/pindo_task.rb', line 42 def retry_count @retry_count end |
#retry_delay ⇒ Object (readonly)
max_retry_count: 初始最大重试次数
43 44 45 |
# File 'lib/pindo/module/task/pindo_task.rb', line 43 def retry_delay @retry_delay end |
#retry_mode ⇒ Object (readonly)
max_retry_count: 初始最大重试次数
43 44 45 |
# File 'lib/pindo/module/task/pindo_task.rb', line 43 def retry_mode @retry_mode end |
#skip_count ⇒ Object
因资源不足被跳过的次数
46 47 48 |
# File 'lib/pindo/module/task/pindo_task.rb', line 46 def skip_count @skip_count end |
#started_at ⇒ Object (readonly)
Returns the value of attribute started_at.
41 42 43 |
# File 'lib/pindo/module/task/pindo_task.rb', line 41 def started_at @started_at end |
#status ⇒ Object
Returns the value of attribute status.
38 39 40 |
# File 'lib/pindo/module/task/pindo_task.rb', line 38 def status @status end |
#task_key ⇒ Object (readonly)
Returns the value of attribute task_key.
39 40 41 |
# File 'lib/pindo/module/task/pindo_task.rb', line 39 def task_key @task_key end |
#task_manager ⇒ Object
TaskManager 实例(依赖注入)
45 46 47 |
# File 'lib/pindo/module/task/pindo_task.rb', line 45 def task_manager @task_manager end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
39 40 41 |
# File 'lib/pindo/module/task/pindo_task.rb', line 39 def type @type end |
Class Method Details
.default_retry_count ⇒ Object
126 127 128 |
# File 'lib/pindo/module/task/pindo_task.rb', line 126 def self.default_retry_count 0 # 默认不重试 end |
.default_retry_delay ⇒ Object
130 131 132 |
# File 'lib/pindo/module/task/pindo_task.rb', line 130 def self.default_retry_delay 10 # 默认延迟 10 秒 end |
.default_retry_mode ⇒ Object
默认重试配置
122 123 124 |
# File 'lib/pindo/module/task/pindo_task.rb', line 122 def self.default_retry_mode RetryMode::IMMEDIATE end |
.task_key ⇒ Object
117 118 119 |
# File 'lib/pindo/module/task/pindo_task.rb', line 117 def self.task_key raise NotImplementedError, "Subclass must define task_key" end |
.task_type ⇒ Object
子类必须实现的方法
113 114 115 |
# File 'lib/pindo/module/task/pindo_task.rb', line 113 def self.task_type raise NotImplementedError, "Subclass must define task_type" end |
Instance Method Details
#before_retry ⇒ Object
371 372 373 |
# File 'lib/pindo/module/task/pindo_task.rb', line 371 def before_retry # 子类可重写,进行重试前的清理工作 end |
#cancel ⇒ Object
取消任务
155 156 157 158 159 160 161 162 |
# File 'lib/pindo/module/task/pindo_task.rb', line 155 def cancel if @status == TaskStatus::PENDING @status = TaskStatus::CANCELLED true else false end end |
#cancelled? ⇒ Boolean
检查是否已取消(不抛异常)
179 180 181 |
# File 'lib/pindo/module/task/pindo_task.rb', line 179 def cancelled? @status == TaskStatus::CANCELLED end |
#check_cancelled! ⇒ Object
检查是否已取消,如果已取消则抛出异常
172 173 174 175 176 |
# File 'lib/pindo/module/task/pindo_task.rb', line 172 def check_cancelled! if @status == TaskStatus::CANCELLED raise TaskCancelledException.new("任务已被取消: #{@name}") end end |
#data_param ⇒ Hash
获取任务的数据参数(用于传递给其他任务)
217 218 219 220 221 222 223 224 225 |
# File 'lib/pindo/module/task/pindo_task.rb', line 217 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
执行任务(在主线程中同步执行)
135 136 137 |
# File 'lib/pindo/module/task/pindo_task.rb', line 135 def do_task execute_internal end |
#execution_time ⇒ Object
执行时间
165 166 167 168 169 |
# File 'lib/pindo/module/task/pindo_task.rb', line 165 def execution_time return nil unless @started_at end_time = @finished_at || Time.now end_time - @started_at end |
#finished? ⇒ Boolean
检查是否完成
140 141 142 |
# File 'lib/pindo/module/task/pindo_task.rb', line 140 def finished? [TaskStatus::SUCCESS, TaskStatus::FAILED, TaskStatus::CANCELLED].include?(@status) end |
#get_all_data_params ⇒ Array<Hash>
获取所有依赖任务的数据参数
239 240 241 |
# File 'lib/pindo/module/task/pindo_task.rb', line 239 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 的数据参数
257 258 259 |
# File 'lib/pindo/module/task/pindo_task.rb', line 257 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
获取所有依赖任务的结果(按依赖顺序)
205 206 207 208 209 210 211 |
# File 'lib/pindo/module/task/pindo_task.rb', line 205 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?
获取指定数据依赖任务的数据参数
230 231 232 233 234 235 |
# File 'lib/pindo/module/task/pindo_task.rb', line 230 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 获取依赖任务的数据参数
246 247 248 249 250 251 252 |
# File 'lib/pindo/module/task/pindo_task.rb', line 246 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?
获取指定依赖任务的结果
196 197 198 199 200 201 |
# File 'lib/pindo/module/task/pindo_task.rb', line 196 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?
获取指定依赖任务
188 189 190 191 |
# File 'lib/pindo/module/task/pindo_task.rb', line 188 def get_dependency_task(dep_task_id) return nil unless @task_manager @task_manager.find_task(dep_task_id) end |
#on(event, &block) ⇒ Object
添加回调
358 359 360 |
# File 'lib/pindo/module/task/pindo_task.rb', line 358 def on(event, &block) @callbacks[event] << block if @callbacks[event] end |
#primary_data_param ⇒ Hash?
获取主数据参数(第一个依赖任务的参数)
263 264 265 266 |
# File 'lib/pindo/module/task/pindo_task.rb', line 263 def primary_data_param return nil if @dependencies.empty? get_data_param(@dependencies.first) end |
#release_resource(resource_spec) ⇒ Object
提前释放资源释放 required_resources 中声明的资源,允许其他任务使用
340 341 342 343 344 345 346 347 |
# File 'lib/pindo/module/task/pindo_task.rb', line 340 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 的别名)
351 352 353 |
# File 'lib/pindo/module/task/pindo_task.rb', line 351 def release_resources(resource_specs) release_resource(resource_specs) end |
#required_resources ⇒ Array<Hash>
获取任务需要的资源(子类覆盖以声明所需资源)资源规格格式:
{ type: :xcode, directory: "/path/to/project" } # 基于目录的资源
{ type: :keychain } # 全局资源
77 78 79 |
# File 'lib/pindo/module/task/pindo_task.rb', line 77 def required_resources [] # 默认不需要资源 end |
#reset_for_retry ⇒ Object
375 376 377 378 379 380 |
# File 'lib/pindo/module/task/pindo_task.rb', line 375 def reset_for_retry @status = TaskStatus::PENDING @result = nil @started_at = nil @finished_at = nil end |
#retryable? ⇒ Boolean
重试相关方法
363 364 365 |
# File 'lib/pindo/module/task/pindo_task.rb', line 363 def retryable? @retry_count > 0 end |
#running? ⇒ Boolean
是否正在运行
145 146 147 |
# File 'lib/pindo/module/task/pindo_task.rb', line 145 def running? @status == TaskStatus::RUNNING end |
#should_retry?(error) ⇒ Boolean
367 368 369 |
# File 'lib/pindo/module/task/pindo_task.rb', line 367 def should_retry?(error) true # 默认所有错误都重试,子类可重写 end |
#validate ⇒ Object
验证任务是否可以执行
150 151 152 |
# File 'lib/pindo/module/task/pindo_task.rb', line 150 def validate true end |
#with_resource(resource_spec, timeout: 30) { ... } ⇒ Object
临时锁定资源(块语法,推荐使用)在代码块执行期间锁定资源,自动释放
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/pindo/module/task/pindo_task.rb', line 291 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 的别名)
317 318 319 |
# File 'lib/pindo/module/task/pindo_task.rb', line 317 def with_resources(resource_specs, timeout: 30, &block) with_resource(resource_specs, timeout: timeout, &block) end |