Class: JekyllImgFlow::BatchManager

Inherits:
Object
  • Object
show all
Defined in:
lib/jekyll-imgflow/batch_manager.rb

Overview

BatchManager - manages batch processing of image operations Queues tasks and processes them efficiently

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(operation_processor) ⇒ BatchManager

Returns a new instance of BatchManager.



11
12
13
14
15
16
17
18
# File 'lib/jekyll-imgflow/batch_manager.rb', line 11

def initialize(operation_processor)
  @operation_processor = operation_processor
  @filename_generator = FilenameGenerator.new
  @queue = []
  @completed = []
  @failed = []
  @mutex = Mutex.new
end

Instance Attribute Details

#completedObject (readonly)

Returns the value of attribute completed.



9
10
11
# File 'lib/jekyll-imgflow/batch_manager.rb', line 9

def completed
  @completed
end

#failedObject (readonly)

Returns the value of attribute failed.



9
10
11
# File 'lib/jekyll-imgflow/batch_manager.rb', line 9

def failed
  @failed
end

#queueObject (readonly)

Returns the value of attribute queue.



9
10
11
# File 'lib/jekyll-imgflow/batch_manager.rb', line 9

def queue
  @queue
end

Class Method Details

.build_default_tasks(original_name, input_path, config, _site) ⇒ Array<Hash>

Build batch tasks for default image versions

Parameters:

  • original_name (String)

    Original image filename

  • input_path (String)

    Path to original image

  • config (Config)

    ImgFlow configuration

  • site (Jekyll::Site)

    Jekyll site object

Returns:

  • (Array<Hash>)

    Array of tasks



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/jekyll-imgflow/batch_manager.rb', line 204

def self.build_default_tasks(original_name, input_path, config, _site)
  tasks = []

  # Use FilenameGenerator for consistent naming
  filename_generator = JekyllImgFlow::FilenameGenerator.new
  path_resolver = JekyllImgFlow::PathResolver.new(config)

  config.sizes.each_value do |width|
    config.formats.each do |format|
      # Use FilenameGenerator to generate proper filename
      operations = { width: width, format: format, quality: config.quality }
      filename = filename_generator.generate_filename(original_name, operations)
      # Write to _site during build (after Jekyll copies assets)
      output_path = path_resolver.resolve_output_path(filename)

      tasks << {
        original_name: original_name,
        operation_type: :resize,
        input_path: input_path,
        output_path: output_path,
        params: {
          width: width,
          format: format,
          quality: config.quality
        },
        version_type: :default,
        page_path: nil, # Default versions not tied to specific page
        skip_if_exists: true
      }
    end
  end

  tasks
end

.build_specialized_task(original_name, input_path, operations, output_path, page_path) ⇒ Hash

Build batch tasks for specialized image version

Parameters:

  • original_name (String)

    Original image filename

  • input_path (String)

    Path to original image

  • operations (Array<Hash>)

    Operations to apply

  • output_path (String)

    Path to output image

  • page_path (String)

    Page using this image

Returns:

  • (Hash)

    Task definition



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/jekyll-imgflow/batch_manager.rb', line 246

def self.build_specialized_task(original_name, input_path, operations, output_path, page_path)
  # For now, assume single operation
  # Future: support chaining multiple operations
  operation = operations.first

  {
    original_name: original_name,
    operation_type: operation[:type],
    input_path: input_path,
    output_path: output_path,
    params: operation[:params],
    version_type: :specialized,
    page_path: page_path,
    skip_if_exists: false
  }
end

Instance Method Details

#add_task(task) ⇒ Object

Add a task to the batch queue

Parameters:

  • task (Hash)

    Task definition

Options Hash (task):

  • :original_name (String)

    Original image filename

  • :operation_type (Symbol)

    Type of operation

  • :input_path (String)

    Path to input image

  • :output_path (String)

    Path to output image

  • :params (Hash)

    Operation parameters

  • :version_type (Symbol)

    :default or :specialized

  • :page_path (String)

    Page using this image



29
30
31
32
33
# File 'lib/jekyll-imgflow/batch_manager.rb', line 29

def add_task(task)
  @mutex.synchronize do
    @queue << task
  end
end

#add_tasks(tasks) ⇒ Object

Add multiple tasks to the queue

Parameters:

  • tasks (Array<Hash>)

    Array of task definitions



37
38
39
40
41
# File 'lib/jekyll-imgflow/batch_manager.rb', line 37

def add_tasks(tasks)
  @mutex.synchronize do
    @queue.concat(tasks)
  end
end

#clearObject

Clear all queues



171
172
173
174
175
176
177
# File 'lib/jekyll-imgflow/batch_manager.rb', line 171

def clear
  @mutex.synchronize do
    @queue.clear
    @completed.clear
    @failed.clear
  end
end

#failed_tasksArray<Hash>

Get failed tasks for retry

Returns:

  • (Array<Hash>)

    Array of failed tasks



181
182
183
184
185
# File 'lib/jekyll-imgflow/batch_manager.rb', line 181

def failed_tasks
  @mutex.synchronize do
    @failed.map { |f| f[:task] }
  end
end

#mark_completed(task, status, result = nil) ⇒ Object

Mark a task as completed

Parameters:

  • task (Hash)

    Completed task

  • status (Symbol)

    Completion status (:processed or :skipped)

  • result (String) (defaults to: nil)

    Result path



132
133
134
135
136
137
138
139
140
141
# File 'lib/jekyll-imgflow/batch_manager.rb', line 132

def mark_completed(task, status, result = nil)
  @mutex.synchronize do
    @completed << {
      task: task,
      status: status,
      result: result,
      completed_at: Time.now
    }
  end
end

#mark_failed(task, error) ⇒ Object

Mark a task as failed

Parameters:

  • task (Hash)

    Failed task

  • error (Exception)

    Error that occurred



146
147
148
149
150
151
152
153
154
155
# File 'lib/jekyll-imgflow/batch_manager.rb', line 146

def mark_failed(task, error)
  @mutex.synchronize do
    @failed << {
      task: task,
      error: error.message,
      backtrace: error.backtrace&.first(5),
      failed_at: Time.now
    }
  end
end

#next_taskHash?

Get the next task from the queue

Returns:

  • (Hash, nil)

    Next task or nil if queue is empty



83
84
85
86
87
# File 'lib/jekyll-imgflow/batch_manager.rb', line 83

def next_task
  @mutex.synchronize do
    @queue.shift
  end
end

#process_all(parallel: false) ⇒ Hash

Process all queued tasks

Parameters:

  • parallel (Boolean) (defaults to: false)

    Whether to process in parallel (future enhancement)

Returns:

  • (Hash)

    Results summary



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/jekyll-imgflow/batch_manager.rb', line 46

def process_all(parallel: false)
  start_time = Time.now

  if parallel
    # Future: implement parallel processing
    process_parallel
  else
    process_sequential
  end

  end_time = Time.now
  duration = end_time - start_time

  {
    total: @queue.length + @completed.length + @failed.length,
    completed: @completed.length,
    failed: @failed.length,
    duration: duration
  }
end

#process_parallelObject

Process tasks in parallel (future enhancement)



75
76
77
78
79
# File 'lib/jekyll-imgflow/batch_manager.rb', line 75

def process_parallel
  # Future: implement thread pool for parallel processing
  # For now, fall back to sequential
  process_sequential
end

#process_sequentialObject

Process tasks sequentially



68
69
70
71
72
# File 'lib/jekyll-imgflow/batch_manager.rb', line 68

def process_sequential
  while (task = next_task)
    process_task(task)
  end
end

#process_task(task) ⇒ Object

Process a single task

Parameters:

  • task (Hash)

    Task to process



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/jekyll-imgflow/batch_manager.rb', line 91

def process_task(task)
  # Check if processing is needed
  # Check if output is up-to-date
  if task[:skip_if_exists] && File.exist?(task[:output_path]) && !@operation_processor.needs_processing?(
    task[:input_path],
    task[:output_path],
    task[:params]
  )
    Jekyll.logger.debug "⏭️  Skipping #{task[:original_name]} - already up-to-date"
    mark_completed(task, :skipped)
    return
  end

  # Process the operation
  operation = {
    type: task[:operation_type],
    params: task[:params]
  }

  Jekyll.logger.debug "🔍 BatchManager: Processing task - input: #{task[:input_path]}, original: #{task[:original_name]}"
  result = @operation_processor.process_operation(
    task[:original_name],
    operation,
    task[:input_path]
  )
  Jekyll.logger.debug "🔍 BatchManager: OperationProcessor returned - result: #{result}"

  # Store result for manifest registration
  task[:result_path] = result

  mark_completed(task, :processed, result)
  Jekyll.logger.debug "✅ Processed: #{task[:original_name]}#{File.basename(result)}"
rescue StandardError => e
  mark_failed(task, e)
  Jekyll.logger.error "❌ Failed: #{task[:original_name]} - #{e.message}"
end

#retry_failedInteger

Retry failed tasks

Returns:

  • (Integer)

    Number of tasks added back to queue



189
190
191
192
193
194
195
196
# File 'lib/jekyll-imgflow/batch_manager.rb', line 189

def retry_failed
  tasks = failed_tasks
  @mutex.synchronize do
    @failed.clear
    @queue.concat(tasks)
  end
  tasks.length
end

#statusHash

Get queue status

Returns:

  • (Hash)

    Current queue status



159
160
161
162
163
164
165
166
167
168
# File 'lib/jekyll-imgflow/batch_manager.rb', line 159

def status
  @mutex.synchronize do
    {
      queued: @queue.length,
      completed: @completed.length,
      failed: @failed.length,
      total: @queue.length + @completed.length + @failed.length
    }
  end
end