taski 0.3.0 → 0.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c018d3aa27087ea7f87e11e01833ffe9c2e6118cc59af29f7f718b7706d108f
4
- data.tar.gz: c18eb90fcfab955b8576b6329ee5df932fcdb8cfed9079c8705656c9e8b90de9
3
+ metadata.gz: 80c881415617aa09fb7ae24441c38c677af816c20f356cc06ea82bba50639820
4
+ data.tar.gz: cc0c6e07e3f53c312844dc237ebebe344a0201bb772f1c6c20ee8c6476b9db30
5
5
  SHA512:
6
- metadata.gz: ea18fc4b07667fd17f2a37356c6a92c54daeadd4f7ad986d5e6131a4a717baf985548845789a17f8b5f5508de70354359a7413b957510d080b041c2f9cde6067
7
- data.tar.gz: '08d4ce07b0bcde870805a2d5b0daf38d6a3cb850bc0e4da8b197c71b906d9f854fc8c97963362bd7b404b1709ded3d2d53975314bc31b19aab3967bdba903a19'
6
+ metadata.gz: 5e40462d8b2b359c17f28f16ec03524ee649324eb4e21eaf365fd147ccedad6bb3d683ece9021975683b1b121c93ad1da2bdaa0fed82ec37797090fadc79129c
7
+ data.tar.gz: 441c9553cded529843af032347f4590f9b6a289bd00f3a8ccbbe996b6be43d2154bc6e2fc4f84a94c1f18c35eb4cfcf5408ff07f6b8878b4f50e41c32a407756
data/README.md CHANGED
@@ -105,7 +105,7 @@ For environment-specific implementations with clean interfaces:
105
105
  class DatabaseSection < Taski::Section
106
106
  interface :host, :port
107
107
 
108
- def impl # No 'self' needed!
108
+ def impl
109
109
  ENV['RAILS_ENV'] == 'production' ? Production : Development
110
110
  end
111
111
 
@@ -122,8 +122,6 @@ class DatabaseSection < Taski::Section
122
122
  @port = 5432
123
123
  end
124
124
  end
125
-
126
- apply_auto_exports # DRY - auto-adds exports to nested tasks
127
125
  end
128
126
 
129
127
  # Usage is simple - Section works like any Task
@@ -58,9 +58,6 @@ class DatabaseSection < Taski::Section
58
58
  @pool_size = 5
59
59
  end
60
60
  end
61
-
62
- # Apply auto-exports after all nested Task classes are defined
63
- apply_auto_exports
64
61
  end
65
62
 
66
63
  # Example 2: API Configuration Section
@@ -98,9 +95,6 @@ class ApiSection < Taski::Section
98
95
  @retry_count = 1
99
96
  end
100
97
  end
101
-
102
- # Apply auto-exports after all nested Task classes are defined
103
- apply_auto_exports
104
98
  end
105
99
 
106
100
  # Example 3: Task that depends on multiple sections
@@ -165,10 +165,11 @@ module Taski
165
165
  begin
166
166
  resolved_class = nil
167
167
 
168
- # 1. Try absolute reference first (existing logic)
168
+ # Try absolute reference first for performance and clarity
169
169
  if Object.const_defined?(const_name)
170
170
  resolved_class = Object.const_get(const_name)
171
- # 2. Try relative reference within namespace context
171
+ # Fall back to relative reference for nested module support
172
+ # This enables tasks defined inside modules to reference siblings
172
173
  elsif @context_class
173
174
  resolved_class = resolve_relative_constant(const_name)
174
175
  end
@@ -63,7 +63,8 @@ module Taski
63
63
 
64
64
  lines_count = 0
65
65
 
66
- # Only display current task with spinner (no past completed tasks during execution)
66
+ # Show only current task to maintain clean, focused UI
67
+ # Displaying all past completed tasks creates visual clutter and reduces readability
67
68
  @terminal.puts @formatter.format_current_task(spinner_char, task_name)
68
69
  lines_count += 1
69
70
 
@@ -85,7 +86,8 @@ module Taski
85
86
  @output_capture.stop
86
87
  clear_current_display
87
88
 
88
- # Include captured output if requested (typically for test environments)
89
+ # Test environments need output for verification, production prefers concise display
90
+ # Conditional inclusion balances debugging needs with user experience
89
91
  if @include_captured_output && captured_output.any?
90
92
  captured_output.each do |line|
91
93
  @terminal.puts line.chomp
@@ -28,12 +28,15 @@ module Taski
28
28
  sleep FRAME_DELAY
29
29
  end
30
30
  rescue
31
- # Silently handle thread errors
31
+ # Prevent crashes during app shutdown or forced thread termination
32
+ # Progress display is auxiliary - errors shouldn't affect main processing
32
33
  end
33
34
  end
34
35
 
35
36
  def stop
36
37
  @running = false
38
+ # 0.2s timeout prevents hanging during rapid task execution
39
+ # UI responsiveness is more important than perfect cleanup
37
40
  @thread&.join(0.2)
38
41
  @thread = nil
39
42
  end
@@ -20,8 +20,6 @@ module Taski
20
20
  @spinner = Progress::SpinnerAnimation.new
21
21
  @output_capture = Progress::OutputCapture.new(output)
22
22
 
23
- # Default to including captured output in test environments (when output != $stdout)
24
- # This ensures test output is visible in the test output stream
25
23
  include_captured_output = include_captured_output.nil? ? (output != $stdout) : include_captured_output
26
24
  @display_manager = Progress::DisplayManager.new(@terminal, @spinner, @output_capture, include_captured_output: include_captured_output)
27
25
 
data/lib/taski/section.rb CHANGED
@@ -117,7 +117,7 @@ module Taski
117
117
  colored_section_name = color ? TreeColors.section(section_name) : section_name
118
118
  result = "#{prefix}#{colored_section_name}\n"
119
119
 
120
- # Add possible implementations (一般化 - detect from nested Task classes)
120
+ # Add possible implementations - detect from nested Task classes
121
121
  possible_implementations = find_possible_implementations
122
122
  if possible_implementations.any?
123
123
  impl_names = possible_implementations.map { |impl| extract_implementation_name(impl) }
@@ -174,6 +174,9 @@ module Taski
174
174
  end
175
175
  end
176
176
  end
177
+
178
+ # Automatically apply exports to existing nested Task classes
179
+ auto_apply_exports_to_existing_tasks
177
180
  end
178
181
 
179
182
  # Get the interface exports for this section
@@ -214,9 +217,10 @@ module Taski
214
217
  result
215
218
  end
216
219
 
217
- # Apply auto-exports to all nested Task classes
218
- # Call this method after defining nested Task classes to automatically add exports
219
- def apply_auto_exports
220
+ private
221
+
222
+ # Automatically apply exports to existing nested Task classes when interface is defined
223
+ def auto_apply_exports_to_existing_tasks
220
224
  constants.each do |const_name|
221
225
  const_value = const_get(const_name)
222
226
  if const_value.is_a?(Class) && const_value < Taski::Task && !interface_exports.empty?
@@ -20,7 +20,7 @@ module Taski
20
20
  def method_added(method_name)
21
21
  super
22
22
  return unless ANALYZED_METHODS.include?(method_name)
23
- # Only call if the method is available (loaded by dependency_resolver)
23
+ # Avoid calling before dependency_resolver module is loaded
24
24
  analyze_dependencies_at_definition if respond_to?(:analyze_dependencies_at_definition, true)
25
25
  end
26
26
 
@@ -29,7 +29,8 @@ module Taski
29
29
  # @return [Reference] A reference object
30
30
  def ref(klass)
31
31
  reference = Reference.new(klass)
32
- # If we're in a define context, throw for dependency tracking
32
+ # Use throw/catch mechanism for dependency collection during define API analysis
33
+ # This allows catching unresolved references without unwinding the entire call stack
33
34
  if Thread.current[TASKI_ANALYZING_DEFINE_KEY]
34
35
  reference.tap { |ref| throw :unresolved, ref }
35
36
  else
@@ -84,7 +85,7 @@ module Taski
84
85
  # Clean method with default empty implementation
85
86
  # Subclasses can override this method to implement cleanup logic
86
87
  def clean
87
- # Default implementation does nothing
88
+ # Default implementation does nothing - allows optional cleanup in subclasses
88
89
  end
89
90
  end
90
91
  end
@@ -16,7 +16,8 @@ module Taski
16
16
  @dependencies ||= []
17
17
  @definitions ||= {}
18
18
 
19
- # Ensure ref method is defined first time define is called
19
+ # Enable forward declarations by creating ref method on first define usage
20
+ # This allows tasks to reference other tasks before they're defined
20
21
  create_ref_method_if_needed
21
22
 
22
23
  # Create method that tracks dependencies on first call
@@ -61,7 +62,7 @@ module Taski
61
62
  def self.#{name}
62
63
  __resolve__[__callee__] ||= false
63
64
  if __resolve__[__callee__]
64
- # already resolved
65
+ # already resolved - prevents infinite recursion
65
66
  else
66
67
  __resolve__[__callee__] = true
67
68
  throw :unresolved, [self, __callee__]
@@ -93,7 +94,8 @@ module Taski
93
94
  # Reset resolution state
94
95
  classes.each do |task_class|
95
96
  klass = task_class[:klass]
96
- # Only reset Task classes, not Reference objects
97
+ # Reference objects are stateless but Task classes store analysis state
98
+ # Selective reset prevents errors while ensuring clean state for next analysis
97
99
  if klass.respond_to?(:instance_variable_set) && !klass.is_a?(Taski::Reference)
98
100
  klass.instance_variable_set(:@__resolve__, {})
99
101
  end
@@ -15,12 +15,10 @@ module Taski
15
15
  names.each do |name|
16
16
  next if respond_to?(name)
17
17
 
18
- # Define class method to access exported value
19
18
  define_singleton_method(name) do
20
19
  ensure_instance_built.send(name)
21
20
  end
22
21
 
23
- # Define instance method getter
24
22
  define_method(name) do
25
23
  instance_variable_get("@#{name}")
26
24
  end
@@ -12,14 +12,12 @@ module Taski
12
12
  # @return [Task] Returns task instance (singleton or temporary)
13
13
  def build(**args)
14
14
  if args.empty?
15
- # Traditional build: singleton instance with caching
16
15
  resolve_dependencies.reverse_each do |task_class|
17
16
  task_class.ensure_instance_built
18
17
  end
19
18
  # Return the singleton instance for consistency
20
19
  instance_variable_get(:@__task_instance)
21
20
  else
22
- # Parametrized build: temporary instance without caching
23
21
  build_with_args(args)
24
22
  end
25
23
  end
@@ -45,7 +43,7 @@ module Taski
45
43
  self
46
44
  end
47
45
 
48
- # Refresh task state (currently just resets)
46
+ # Refresh task state
49
47
  # @return [self] Returns self for method chaining
50
48
  def refresh
51
49
  reset!
@@ -82,11 +80,11 @@ module Taski
82
80
  # Ensure task instance is built (public because called from build)
83
81
  # @return [Task] The built task instance
84
82
  def ensure_instance_built
85
- # Use double-checked locking pattern for thread safety
83
+ # Double-checked locking prevents lock contention in multi-threaded builds
84
+ # First check avoids expensive synchronization when instance already exists
86
85
  return @__task_instance if @__task_instance
87
86
 
88
87
  build_monitor.synchronize do
89
- # Check again after acquiring lock
90
88
  return @__task_instance if @__task_instance
91
89
 
92
90
  check_circular_dependency
@@ -26,15 +26,12 @@ module Taski
26
26
  child_prefix_text = is_last ? " " : "│ "
27
27
  child_prefix = prefix + (color ? TreeColors.connector(child_prefix_text) : child_prefix_text)
28
28
 
29
- # For the dependency itself, we want to use the connector
30
- # For its children, we want to use the child_prefix
31
29
  dep_tree = if dep_class.respond_to?(:tree)
32
30
  dep_class.tree(child_prefix, visited, color: color)
33
31
  else
34
32
  "#{child_prefix}#{dep_class.name}\n"
35
33
  end
36
34
 
37
- # Replace the first line (which has child_prefix) with the proper connector
38
35
  dep_lines = dep_tree.lines
39
36
  if dep_lines.any?
40
37
  # Replace the first line prefix with connector
data/lib/taski/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Taski
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/taski.rb CHANGED
@@ -26,20 +26,20 @@ module Taski
26
26
  # Main module for the Taski task framework
27
27
  #
28
28
  # Taski provides a framework for defining and managing task dependencies
29
- # with two complementary APIs:
29
+ # with three complementary APIs:
30
30
  # 1. Exports API - Export instance variables as class methods (static dependencies)
31
31
  # 2. Define API - Define lazy-evaluated values with dynamic dependency resolution
32
+ # 3. Section API - Abstraction layers with runtime implementation selection
32
33
  #
33
- # Use Define API when:
34
- # - Dependencies change based on runtime conditions
35
- # - Environment-specific configurations
36
- # - Feature flags determine which classes to use
37
- # - Complex conditional logic determines dependencies
34
+ # API Selection Guide:
35
+ # - Use Exports API for simple static dependencies
36
+ # - Use Define API for conditional dependencies analyzed at class definition time
37
+ # - Use Section API for environment-specific implementations with static analysis
38
38
  #
39
39
  # Features:
40
40
  # - Automatic dependency resolution (static and dynamic)
41
41
  # - Static analysis of method dependencies
42
- # - Runtime dependency resolution for conditional logic
42
+ # - Runtime implementation selection with Section API
43
43
  # - Thread-safe task building
44
44
  # - Circular dependency detection
45
45
  # - Memory leak prevention
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.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ahogappa