taski 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/taski.rb CHANGED
@@ -140,6 +140,7 @@ module Taski
140
140
 
141
141
  @args_monitor = Monitor.new
142
142
  @env_monitor = Monitor.new
143
+ @message_monitor = Monitor.new
143
144
 
144
145
  # Get the current runtime arguments
145
146
  # @return [Args, nil] The current args or nil if no task is running
@@ -153,6 +154,23 @@ module Taski
153
154
  @env_monitor.synchronize { @env }
154
155
  end
155
156
 
157
+ # Output a message to the user without being captured by TaskOutputRouter.
158
+ # During task execution with progress display, messages are queued and
159
+ # displayed after execution completes. Without progress display or outside
160
+ # task execution, messages are output immediately.
161
+ #
162
+ # @param text [String] The message text to display
163
+ def self.message(text)
164
+ @message_monitor.synchronize do
165
+ progress = progress_display
166
+ if progress&.respond_to?(:queue_message)
167
+ progress.queue_message(text)
168
+ else
169
+ $stdout.puts(text)
170
+ end
171
+ end
172
+ end
173
+
156
174
  # Start new execution environment (internal use only)
157
175
  # @api private
158
176
  # @return [Boolean] true if this call created the env, false if env already existed
@@ -229,9 +247,14 @@ module Taski
229
247
  end
230
248
 
231
249
  # Get the current progress mode (:tree or :simple)
250
+ # Environment variable TASKI_PROGRESS_MODE takes precedence over code settings.
232
251
  # @return [Symbol] The current progress mode
233
252
  def self.progress_mode
234
- @progress_mode || progress_mode_from_env
253
+ if ENV["TASKI_PROGRESS_MODE"]
254
+ progress_mode_from_env
255
+ else
256
+ @progress_mode || :tree
257
+ end
235
258
  end
236
259
 
237
260
  # Set the progress mode (:tree or :simple)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taski
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ahogappa
@@ -59,17 +59,12 @@ files:
59
59
  - examples/README.md
60
60
  - examples/args_demo.rb
61
61
  - examples/clean_demo.rb
62
- - examples/data_pipeline_demo.rb
63
62
  - examples/group_demo.rb
64
- - examples/large_tree_demo.rb
65
- - examples/nested_section_demo.rb
66
- - examples/parallel_progress_demo.rb
63
+ - examples/message_demo.rb
64
+ - examples/progress_demo.rb
67
65
  - examples/quick_start.rb
68
66
  - examples/reexecution_demo.rb
69
67
  - examples/section_demo.rb
70
- - examples/simple_progress_demo.rb
71
- - examples/system_call_demo.rb
72
- - examples/tree_progress_demo.rb
73
68
  - lib/taski.rb
74
69
  - lib/taski/args.rb
75
70
  - lib/taski/env.rb
@@ -120,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
115
  - !ruby/object:Gem::Version
121
116
  version: '0'
122
117
  requirements: []
123
- rubygems_version: 4.0.3
118
+ rubygems_version: 4.0.4
124
119
  specification_version: 4
125
120
  summary: A simple yet powerful Ruby task runner with static dependency resolution
126
121
  (in development).
@@ -1,231 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Taski Data Pipeline Example
5
- #
6
- # This example demonstrates a realistic data processing pipeline:
7
- # - Section API for switching data sources (production vs test)
8
- # - Multiple data sources fetched in parallel
9
- # - Data transformation and aggregation
10
- #
11
- # Run: ruby examples/data_pipeline_demo.rb
12
- # Disable progress: TASKI_PROGRESS_DISABLE=1 ruby examples/data_pipeline_demo.rb
13
-
14
- require_relative "../lib/taski"
15
-
16
- # Section: Data source abstraction
17
- # Switch between production API and test fixtures
18
- class DataSourceSection < Taski::Section
19
- interfaces :users, :sales, :activities
20
-
21
- def impl
22
- (ENV["USE_TEST_DATA"] == "true") ? TestData : ProductionData
23
- end
24
-
25
- # Production: Fetch from APIs (simulated with delays)
26
- class ProductionData < Taski::Task
27
- def run
28
- puts " [ProductionData] Fetching from APIs..."
29
- sleep(0.3)
30
-
31
- @users = [
32
- {id: 1, name: "Alice", department: "Engineering"},
33
- {id: 2, name: "Bob", department: "Sales"},
34
- {id: 3, name: "Charlie", department: "Engineering"},
35
- {id: 4, name: "Diana", department: "Marketing"}
36
- ]
37
-
38
- @sales = [
39
- {user_id: 2, amount: 1000, date: "2024-01"},
40
- {user_id: 2, amount: 1500, date: "2024-02"},
41
- {user_id: 4, amount: 800, date: "2024-01"}
42
- ]
43
-
44
- @activities = [
45
- {user_id: 1, action: :commit, count: 45},
46
- {user_id: 3, action: :commit, count: 32},
47
- {user_id: 1, action: :review, count: 12},
48
- {user_id: 3, action: :review, count: 8}
49
- ]
50
-
51
- puts " [ProductionData] Loaded #{@users.size} users, #{@sales.size} sales, #{@activities.size} activities"
52
- end
53
- end
54
-
55
- # Test: Minimal fixture data (no delays)
56
- class TestData < Taski::Task
57
- def run
58
- puts " [TestData] Loading test fixtures..."
59
-
60
- @users = [
61
- {id: 1, name: "Test User", department: "Test Dept"}
62
- ]
63
-
64
- @sales = [
65
- {user_id: 1, amount: 100, date: "2024-01"}
66
- ]
67
-
68
- @activities = [
69
- {user_id: 1, action: :commit, count: 10}
70
- ]
71
-
72
- puts " [TestData] Loaded minimal test data"
73
- end
74
- end
75
- end
76
-
77
- # Section: Report format selection
78
- class ReportFormatSection < Taski::Section
79
- interfaces :format_report
80
-
81
- def impl
82
- (ENV["REPORT_FORMAT"] == "json") ? JsonFormat : TextFormat
83
- end
84
-
85
- class TextFormat < Taski::Task
86
- def run
87
- @format_report = ->(report) {
88
- report.map do |dept, stats|
89
- "#{dept}: #{stats[:user_count]} users, $#{stats[:total_sales]} sales"
90
- end.join("\n")
91
- }
92
- end
93
- end
94
-
95
- class JsonFormat < Taski::Task
96
- def run
97
- require "json"
98
- @format_report = ->(report) { JSON.pretty_generate(report) }
99
- end
100
- end
101
- end
102
-
103
- # Transform: Enrich users with sales data
104
- class EnrichWithSales < Taski::Task
105
- exports :users_with_sales
106
-
107
- def run
108
- users = DataSourceSection.users
109
- sales = DataSourceSection.sales
110
-
111
- sales_by_user = sales.group_by { |s| s[:user_id] }
112
- .transform_values { |records| records.sum { |r| r[:amount] } }
113
-
114
- @users_with_sales = users.map do |user|
115
- user.merge(total_sales: sales_by_user[user[:id]] || 0)
116
- end
117
-
118
- puts " [EnrichWithSales] Enriched #{@users_with_sales.size} users"
119
- end
120
- end
121
-
122
- # Transform: Enrich users with activity data
123
- class EnrichWithActivities < Taski::Task
124
- exports :users_with_activities
125
-
126
- def run
127
- users = DataSourceSection.users
128
- activities = DataSourceSection.activities
129
-
130
- activities_by_user = activities.group_by { |a| a[:user_id] }
131
- .transform_values do |records|
132
- records.to_h { |r| [r[:action], r[:count]] }
133
- end
134
-
135
- @users_with_activities = users.map do |user|
136
- user.merge(activities: activities_by_user[user[:id]] || {})
137
- end
138
-
139
- puts " [EnrichWithActivities] Enriched #{@users_with_activities.size} users"
140
- end
141
- end
142
-
143
- # Aggregate: Combine enrichments into profiles
144
- class BuildProfiles < Taski::Task
145
- exports :profiles
146
-
147
- def run
148
- users_sales = EnrichWithSales.users_with_sales
149
- users_activities = EnrichWithActivities.users_with_activities
150
-
151
- activities_map = users_activities.to_h { |u| [u[:id], u[:activities]] }
152
-
153
- @profiles = users_sales.map do |user|
154
- user.merge(activities: activities_map[user[:id]] || {})
155
- end
156
-
157
- puts " [BuildProfiles] Built #{@profiles.size} profiles"
158
- end
159
- end
160
-
161
- # Output: Generate department report
162
- class GenerateReport < Taski::Task
163
- exports :report, :formatted_output
164
-
165
- def run
166
- profiles = BuildProfiles.profiles
167
- formatter = ReportFormatSection.format_report
168
-
169
- by_department = profiles.group_by { |p| p[:department] }
170
-
171
- @report = by_department.transform_values do |dept_users|
172
- {
173
- user_count: dept_users.size,
174
- total_sales: dept_users.sum { |u| u[:total_sales] },
175
- total_commits: dept_users.sum { |u| u[:activities][:commit] || 0 },
176
- total_reviews: dept_users.sum { |u| u[:activities][:review] || 0 }
177
- }
178
- end
179
-
180
- @formatted_output = formatter.call(@report)
181
- puts " [GenerateReport] Generated report for #{@report.size} departments"
182
- end
183
- end
184
-
185
- # Demo execution
186
- puts "Taski Data Pipeline Demo"
187
- puts "=" * 50
188
-
189
- puts "\n1. Dependency Tree"
190
- puts "-" * 50
191
- puts GenerateReport.tree
192
-
193
- puts "\n2. Production Data (default)"
194
- puts "-" * 50
195
- ENV["USE_TEST_DATA"] = "false"
196
- ENV["REPORT_FORMAT"] = "text"
197
-
198
- start_time = Time.now
199
- GenerateReport.run
200
- elapsed = Time.now - start_time
201
-
202
- puts "\nReport (text format):"
203
- puts GenerateReport.formatted_output
204
- puts "\nCompleted in #{elapsed.round(3)}s"
205
-
206
- puts "\n" + "=" * 50
207
- puts "\n3. Test Data with JSON Format"
208
- puts "-" * 50
209
- ENV["USE_TEST_DATA"] = "true"
210
- ENV["REPORT_FORMAT"] = "json"
211
-
212
- # Reset all tasks for fresh execution
213
- [DataSourceSection, ReportFormatSection, EnrichWithSales,
214
- EnrichWithActivities, BuildProfiles, GenerateReport].each(&:reset!)
215
-
216
- start_time = Time.now
217
- GenerateReport.run
218
- elapsed = Time.now - start_time
219
-
220
- puts "\nReport (JSON format):"
221
- puts GenerateReport.formatted_output
222
- puts "\nCompleted in #{elapsed.round(3)}s"
223
-
224
- puts "\n" + "=" * 50
225
- puts "Pipeline demonstration complete!"
226
- puts "\nKey concepts demonstrated:"
227
- puts " - DataSourceSection: Switch between production/test data"
228
- puts " - ReportFormatSection: Switch output format (text/JSON)"
229
- puts " - Parallel execution of independent transforms"
230
- puts "\nTo disable progress display:"
231
- puts " TASKI_PROGRESS_DISABLE=1 ruby examples/data_pipeline_demo.rb"