### Example Task Defining a Collection Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md This example demonstrates overriding `collection` to fetch and process featured posts. ```ruby class Maintenance::UpdatePostsTask < MaintenanceTasks::Task def collection Post.where(featured: false).order(:id) end def process(post) post.update!(featured: true) if post.high_quality? end end ``` -------------------------------- ### Example: Get Task Status Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Shows examples of retrieving the status for a task. ```ruby task_data.status # "running" task_data.status # "new" ``` -------------------------------- ### Install Maintenance Tasks Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Run this command to install the maintenance tasks gem and its associated migrations. ```sh-session bin/rails generate maintenance_tasks:install ``` -------------------------------- ### started? Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Returns whether the run has started its execution. ```APIDOC ## started? ### Description Returns whether the run has started execution. ### Method `started?` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```ruby if !run.started? puts "Still waiting to be picked up" end ``` ### Response #### Success Response - **Boolean** - True if the run has started, false otherwise. #### Response Example None ``` -------------------------------- ### Example Task with Custom Processing Logic Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md This example shows a `BackfillTask` that overrides the `process` method to update user records. ```ruby class Maintenance::BackfillTask < MaintenanceTasks::Task def collection User.where(name: nil) end def process(user) user.update!(name: user.email.split('@').first) end end ``` -------------------------------- ### Install maintenance_tasks CLI Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/cli.md Install the CLI executable using the gem command. Alternatively, use Bundler for project-specific installations. ```bash gem install maintenance_tasks ``` ```bash bundle exec maintenance_tasks [command] ``` -------------------------------- ### Example Task with Composite Key Cursor Columns Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md This example demonstrates using `cursor_columns` with a composite key for ordered iteration. ```ruby class Maintenance::IterateWithCompositeKeyTask < MaintenanceTasks::Task def collection Record.all end def cursor_columns [:user_id, :id] # For composite key ordering end def process(record) record.update!(processed: true) end end ``` -------------------------------- ### Example Task with Completion and Error Callbacks Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md This example shows how to implement a custom task with `after_complete` and `after_error` callbacks for notifications. ```ruby class Maintenance::NotificationTask < MaintenanceTasks::Task after_complete do NotificationService.notify("Task completed!") end after_error do NotificationService.alert("Task failed!") end def collection User.all end def process(user) user.notify end end ``` -------------------------------- ### start Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Sets the started_at timestamp and tick_total count, then executes :start callbacks. Requires the total expected iterations as an argument. ```APIDOC ## start ### Description Sets started_at timestamp and tick_total count, then executes :start callbacks. ### Method `start(count)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters #### Standard Parameters - **count** (Integer) - Required - Total expected iterations ### Request Example ```ruby run.start(500) # Expects 500 iterations ``` ### Response #### Success Response - **void** #### Response Example None ``` -------------------------------- ### Start a Run Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Initializes a run by setting the started_at timestamp and the total expected tick count, then executes any associated :start callbacks. ```ruby run.start(500) # Expects 500 iterations ``` -------------------------------- ### View Usage Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Provides an example of how to display paginated run records and a 'Next Page' link in a Rails view. ```erb
<% @runs.each do |run| %>

<%= run.task_name %>

Status: <%= run.status %>

Started: <%= run.started_at %>

<% end %>
``` -------------------------------- ### Example: Create a RunsPage Instance Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Demonstrates how to instantiate RunsPage with a relation of runs and a nil cursor for the first page. ```ruby all_runs = MaintenanceTasks::Run.where(task_name: "MyTask").order(created_at: :desc) page = MaintenanceTasks::RunsPage.new(all_runs, cursor: nil) ``` -------------------------------- ### Example: Group Available Tasks by Category Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Demonstrates how to retrieve all tasks and group them by their category. ```ruby all_tasks = MaintenanceTasks::TaskDataIndex.available_tasks tasks_by_category = all_tasks.group_by(&:category) # => { # active: [TaskDataIndex, ...], # completed: [TaskDataIndex, ...], # new: [TaskDataIndex, ...] # } ``` -------------------------------- ### Example: Group Tasks by Category in UI Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Demonstrates how to fetch available tasks and group them by category for display purposes. ```ruby tasks = MaintenanceTasks::TaskDataIndex.available_tasks tasks.group_by(&:category) # => { # active: [...], # new: [...], # completed: [...] # } ``` -------------------------------- ### CSV File Attachable Hash Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Example of creating and using the `csv_file` hash with `MaintenanceTasks::Runner.run`. ```ruby csv_file = { io: File.open('users.csv'), filename: 'users.csv', content_type: 'text/csv' } MaintenanceTasks::Runner.run( name: "ImportTask", csv_file: csv_file ) ``` -------------------------------- ### on_start Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-job.md Called when iteration begins. It calculates the total count, marks the run as started, and triggers the Task's start callbacks. ```APIDOC ## Private Method: on_start ### Description Called when iteration begins. ### Signature ```ruby def on_start -> void ``` ### Behavior: - Gets count from task or enumerator - Calls `run.start(count)` to set started_at and tick_total - Triggers Task's `:start` callbacks ``` -------------------------------- ### CsvCollectionBuilder Task Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Example of configuring a task to use `csv_collection` with specific CSV parsing options. ```ruby class Maintenance::ImportTask < MaintenanceTasks::Task csv_collection headers: true, encoding: 'UTF-8' def process(row) User.create!(row.to_h) end end ``` -------------------------------- ### Install Maintenance Tasks Gem Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Add the gem to your project and run the install generator to set up the necessary database tables and routes. ```sh bundle add maintenance_tasks bin/rails generate maintenance_tasks:install ``` -------------------------------- ### Example HTML Output for Progress Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Shows the resulting HTML structure and content generated by the view helper integration for progress display. ```html

Processed 250 out of 1,000 items (25%).

``` -------------------------------- ### Controller Actions for Task Index and Show Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Provides example controller actions for displaying a list of tasks and preparing a specific task for display, including handling parameters and arguments. ```ruby class TasksController < ApplicationController def index @available_tasks = MaintenanceTasks::TaskDataIndex.available_tasks @grouped_tasks = @available_tasks.group_by(&:category) end def show @task = MaintenanceTasks::TaskDataShow.prepare( params[:id], runs_cursor: params[:cursor], arguments: params.permit!.to_h ) end end ``` -------------------------------- ### Example Task with Custom Count Method Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md This example shows a task that defines a custom `count` method for progress estimation. ```ruby class Maintenance::CustomCountTask < MaintenanceTasks::Task def collection User.all end def count User.count # Optional: return nil to skip progress estimation end def process(user) user.touch end end ``` -------------------------------- ### BatchCsvCollectionBuilder Task Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Example of configuring a task to use `csv_collection` with batch processing and specific CSV options. ```ruby class Maintenance::ImportTask < MaintenanceTasks::Task csv_collection in_batches: 100, encoding: 'UTF-8' def process(batch) records = batch.map(&:to_h) User.insert_all(records) end end ``` -------------------------------- ### Example Task Reporting Specific Exceptions Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md This example demonstrates using `report_on` to handle `Timeout::Error` and `ApiError` during API synchronization. ```ruby class Maintenance::ApiSyncTask < MaintenanceTasks::Task report_on(Timeout::Error, ApiError) def collection Record.all end def process(record) record.sync_with_api # May raise ApiError end end ``` -------------------------------- ### Task.after_start Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task.md Registers a callback to run after the task starts. This allows for custom logic to be executed at the beginning of a task. ```APIDOC ## Task.after_start ### Description Register a callback to run after the task starts. ### Method Instance Method ### Parameters #### Path Parameters - **filter_list** (Array) - Optional - List of filters - **block** (Proc) - Required - Callback block ``` -------------------------------- ### Notification Event Subscription Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Example of subscribing to ActiveSupport notifications for maintenance tasks using a regular expression to match event names. ```ruby ActiveSupport::Notifications.subscribe /\.maintenance_tasks\z/ do |name, start, finish, id, payload| # name: "succeeded.maintenance_tasks" # payload: {run_id, job_id, task_name, arguments, metadata, time_running, ...} end ``` -------------------------------- ### Specific Notification Event Subscription Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Example of subscribing to a specific 'succeeded.maintenance_tasks' event to log task completion details. ```ruby ActiveSupport::Notifications.subscribe "succeeded.maintenance_tasks" do |name, start, finish, id, payload| TaskCompletionLog.create!( task_name: payload[:task_name], duration: payload[:time_running] ) end ``` -------------------------------- ### Error Context Subscription Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Example of subscribing to errors using `Rails.error.subscribe` to access the error context payload. ```ruby # Subscribing to errors Rails.error.subscribe do |error, handled:, context:| puts "Task: #{context[:task_name]}" puts "Run: #{context[:run_id]}" if context[:errored_element] puts "Failed on: #{context[:errored_element]}" end end ``` -------------------------------- ### Controller Usage Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Illustrates how to use RunsPage within a Rails controller to fetch and paginate run records. ```ruby class TasksController < ApplicationController def show runs = MaintenanceTasks::Run .where(task_name: params[:id]) .order(created_at: :desc) @page = MaintenanceTasks::RunsPage.new(runs, params[:cursor]) @runs = @page.records @has_next = !@page.last? @next_cursor = @page.next_cursor if @has_next end end ``` -------------------------------- ### Migrate Database Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Run this command after installing or reinstalling migrations to update the database schema. ```sh-session bin/rails db:migrate ``` -------------------------------- ### NullCollectionBuilder Override Example: collection Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Example of overriding the `collection` method in a custom task to define how to retrieve a collection. ```ruby class CustomTask < MaintenanceTasks::Task def collection User.all end end ``` -------------------------------- ### on_start Method Implementation Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-job.md Called when the iteration begins. It calculates the total count, updates the Run record, and triggers Task's start callbacks. ```ruby def on_start -> void ``` -------------------------------- ### Query Optimization Example Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Demonstrates query optimization techniques for forward-only pagination, including loading extra records to detect the next page and checking for its existence without loading the full result set. ```ruby # Loads 21 records to check for next page runs_after_cursor = runs.where("id < ?", cursor).limit(21) # Returns first 20 records = runs_after_cursor.take(20) # Checks if 21st exists without loading full result set has_more = runs_after_cursor.length > 20 ``` -------------------------------- ### Example: Determine if Next Page Exists Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Demonstrates how to use the `last?` method to determine if a 'Next Page' link should be displayed. ```ruby @page = MaintenanceTasks::RunsPage.new(runs, cursor: params[:cursor]) @show_next = !@page.last? ``` -------------------------------- ### BatchCsvCollectionBuilder Example: Accessing BatchCsv Struct Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Example showing how to obtain and access the fields of the BatchCsv struct returned by the `collection` method. ```ruby batch_csv = builder.collection(task) # batch_csv.csv = CSV object ``` -------------------------------- ### Example of Triggering Callbacks on Transition Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Shows how transitioning a run's status and persisting the transition triggers associated Task callbacks, such as `after_complete`. ```ruby # When run transitions to :succeeded, calls task.run_callbacks(:complete) run.status = :succeeded run.persist_transition # Triggers Task's after_complete callbacks ``` -------------------------------- ### Example Task Class within tasks_module Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/configuration.md Demonstrates defining a task class within the configured `tasks_module` namespace and loading it by name. ```ruby MaintenanceTasks.tasks_module = "Maintenance" # Task files go in: # app/tasks/maintenance/backfill_task.rb class Maintenance::BackfillTask < MaintenanceTasks::Task def collection User.all end def process(user) user.update!(state: "active") end end # Load task by name: task = MaintenanceTasks::Task.named("Maintenance::BackfillTask") ``` -------------------------------- ### Example: Iterate Through Records Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Shows how to iterate through the records of a RunsPage object and display their task name and status. ```ruby page.records.each do |run| puts "#{run.task_name}: #{run.status}" end ``` -------------------------------- ### Example Custom TaskJob with Conditional Queuing Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/configuration.md Illustrates a custom task job class with queueing logic that depends on the Rails environment. ```ruby class CustomTaskJob < ActiveJob::Base include MaintenanceTasks::TaskJobConcern queue_as { Rails.env.production? ? :production : :default } def on_error(error) Sentry.capture_exception(error) super end end MaintenanceTasks.job = "CustomTaskJob" ``` -------------------------------- ### Instantiate BatchCsv Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Example of how to instantiate the BatchCsv struct with a CSV object and a batch size. This is typically used with the BatchCsvCollectionBuilder. ```ruby batch_csv = MaintenanceTasks::BatchCsvCollectionBuilder::BatchCsv.new( csv: CSV.new(content, headers: true), batch_size: 100 ) ``` -------------------------------- ### Example: Custom Error Handling with `report_errors_as_handled = false` Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/configuration.md Demonstrates how to subscribe to Rails errors and differentiate between task-handled and unexpected errors when `report_errors_as_handled` is set to false. ```ruby # Report errors as unhandled for better error tracking MaintenanceTasks.report_errors_as_handled = false Rails.error.subscribe do |error, handled:, context:| if context&.dig(:source) == "maintenance-tasks" if handled # Task handled this error with rescue_from logger.info("Task recovered from: #{error}") else # Unexpected error Sentry.capture_exception(error) end end end ``` -------------------------------- ### NullCollectionBuilder Override Example: count Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Example of overriding the `count` method in a custom task to define how to count items in a collection. ```ruby class CustomTask < MaintenanceTasks::Task def count User.count end end ``` -------------------------------- ### Example of Catching Task NotFoundError Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Demonstrates how to use a begin-rescue block to catch `MaintenanceTasks::Task::NotFoundError` when attempting to find a non-existent task. ```ruby begin MaintenanceTasks::Task.named("NonexistentTask") rescue MaintenanceTasks::Task::NotFoundError => e puts "Task not found: #{e.message}" end ``` -------------------------------- ### Check if Run has Started Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Returns whether the run has begun its execution. Useful for determining if a task is still waiting to be picked up. ```ruby if !run.started? puts "Still waiting to be picked up" end ``` -------------------------------- ### Example Custom TaskJob with Queuing Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/configuration.md Define a custom Active Job class for tasks, including custom queuing logic and error handling. ```ruby class MyTaskJob < MaintenanceTasks::TaskJob queue_as :maintenance_high_priority end MaintenanceTasks.job = "MyTaskJob" ``` -------------------------------- ### Example: Using Complex Cursors with JSON Serialization Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/configuration.md Illustrates defining a task that uses multiple cursor columns when `serialize_cursors_as_json` is enabled. ```ruby MaintenanceTasks.serialize_cursors_as_json = true # Now cursors can be complex structures class Maintenance::CompositeKeyTask < MaintenanceTasks::Task def cursor_columns [:user_id, :created_at, :id] # Multiple columns end def process(record) record.touch end end ``` -------------------------------- ### Run.with_attached_csv Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Eagerly loads the associated CSV file attachment if Active Storage is installed. ```APIDOC ## Run.with_attached_csv ### Description Eagerly loads associated CSV file attachment if Active Storage is installed. ### Method `Run.with_attached_csv` ### Parameters None ### Response Returns an `ActiveRecord::Relation` of `Run` objects with the CSV attachment loaded. ### Request Example ```ruby runs = MaintenanceTasks::Run.with_attached_csv.limit(10) ``` ``` -------------------------------- ### Install Maintenance Task Migrations Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Use this command to copy the gem's migrations to your db/migrate folder, especially if previous migrations were deleted. ```sh-session bin/rails maintenance_tasks:install:migrations ``` -------------------------------- ### CsvCollectionBuilder Example: Processing CSV Content Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Demonstrates how to retrieve and iterate over a CSV object obtained from the task's content. ```ruby csv_content = "name,email\nAlice,alice@example.com\nBob,bob@example.com" task.csv_content = csv_content csv = task.collection_builder_strategy.collection(task) csv.each do |row| # row = {"name" => "Alice", "email" => "alice@example.com"} end ``` -------------------------------- ### Example: Conditional Logic for Stale Tasks Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Demonstrates using the `stale?` method to conditionally hide tasks from the main list and show them in an archive. ```ruby if task_data.stale? # Hide from main list, show in archive end ``` -------------------------------- ### Example of Valid and Invalid Status Transitions Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Illustrates how to set run statuses and the expected outcome, including a valid transition and an invalid one that raises `ActiveRecord::RecordInvalid`. ```ruby run.status = :running run.status = :paused # Valid run.save! run.status = :cancelled # Invalid (paused → cancelled not allowed) run.save! # Raises ActiveRecord::RecordInvalid ``` -------------------------------- ### Example Task Using NoCollectionBuilder Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Demonstrates how to use `no_collection` within a Maintenance::Task subclass to perform a single operation, such as clearing and warming the cache. ```ruby class Maintenance::CacheWarmer < MaintenanceTasks::Task no_collection def process Rails.cache.clear Rails.cache.warm_up end end ``` -------------------------------- ### Example CSV Data Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Sample data for a CSV file used with a CSV Maintenance Task. It includes headers and rows for importing posts. ```csv title,content My Title,Hello World! ``` -------------------------------- ### Initialize TaskDataShow Instance Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Creates a TaskDataShow instance. Accepts task name, an optional runs cursor for pagination, and optional arguments. ```ruby TaskDataShow.new(name, runs_cursor: nil, arguments: nil) ``` -------------------------------- ### Get Task Instance from Run Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Returns a Task instance with arguments assigned from the run. CSV content is not populated here and must be loaded separately. ```ruby task = run.task puts task.class.name ``` -------------------------------- ### TaskDataShow.new Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Creates a TaskDataShow instance with the specified name, runs cursor, and arguments. ```APIDOC ## TaskDataShow.new ### Description Creates a TaskDataShow instance. ### Method Instance Method ### Signature `TaskDataShow.new(name, runs_cursor: nil, arguments: nil)` ### Parameters #### Arguments - **name** (String) - Task class name - **runs_cursor** (String, nil) - Cursor for run pagination - **arguments** (Hash, nil) - Arguments to assign to Task ``` -------------------------------- ### Run a Maintenance Task in Rails Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/cli.md Install the gem and run maintenance tasks from your Rails application directory. The CLI automatically loads the Rails environment. ```bash cd myapp bundle exec maintenance_tasks perform Maintenance::MyTask ``` -------------------------------- ### Example ERB for Task Show Page Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md This ERB template displays task details, including its name, source code (if available), active runs, and run history. It utilizes instance variables like `@task` and its associated objects. ```erb

<%= @task.name %>

<% if @task.code %>
<%= @task.code %>
<% end %> <% if @task.active_runs.any? %>

Active Runs

<% @task.active_runs.each do |run| %> <% end %> <% end %>

Run History

<% @task.runs_page.records.each do |run| %> <% end %> ``` -------------------------------- ### Get Available Tasks Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns a sorted list of all available Task metadata, including Run records. Sorting is based on category, recency, and name. ```ruby TaskDataIndex.available_tasks -> Array ``` -------------------------------- ### Customize Batch Size for Record Processing Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Modify the default batch size for fetching records from the database. This example sets the batch size to 1000. ```ruby module Maintenance class UpdatePostsTask < MaintenanceTasks::Task # Fetch records in batches of 1000 collection_batch_size(1000) def collection Post.all end def process(post) post.update!(content: "New content!") end end end ``` -------------------------------- ### Example of Catching Runner EnqueuingError Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/types.md Shows how to catch `MaintenanceTasks::Runner::EnqueuingError` and access the associated `run` object to inspect details of the failed enqueue operation. ```ruby begin MaintenanceTasks::Runner.run(name: "MyTask") rescue MaintenanceTasks::Runner::EnqueuingError => e puts "Enqueue failed: #{e.message}" puts "Run ID: #{e.run.id}" end ``` -------------------------------- ### Example ERB for Displaying Tasks by Category Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md This ERB template iterates through available tasks, groups them by category, and displays each task's name and status. It requires the `@available_tasks` instance variable to be populated. ```erb <% @available_tasks.group_by(&:category).each do |category, tasks| %>

<%= category %>

<% tasks.each do |task| %> <%= link_to task.name, task_path(task) %> <%= task.status %> <% end %> <% end %> ``` -------------------------------- ### before_perform Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-job.md Initializes the job execution context by loading the Run, preparing the Task, downloading CSV content if applicable, and transitioning the run to a running state. ```APIDOC ## Private Method: before_perform ### Description Initializes job execution context. ### Signature ```ruby def before_perform -> void ``` ### Initializes: - `@run` — First argument (Run record) - `@task` — Run's Task instance - Downloads CSV content if CSV task - Transitions run to running - Creates Ticker for progress updates ### Side effects: - Transitions Run to running status - Downloads CSV file from Active Storage if applicable ``` -------------------------------- ### TaskDataShow#new Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Instantiates the Task class with assigned arguments, returning nil if the task file was deleted. ```APIDOC ## task_data.new ### Description Instantiates the Task class with arguments. ### Method Instance Method ### Signature `task_data.new -> Task, nil` ### Returns - Task instance with arguments assigned, if task exists - nil if task file was deleted ### Example ```ruby task = task_data.new task.process # Execute task ``` ``` -------------------------------- ### Initialize Progress Tracker Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Creates a Progress tracker for a Run. Requires a Run object as input. ```ruby class Progress def initialize(run) end ``` ```ruby Progress.new(run) -> Progress ``` ```ruby run = MaintenanceTasks::Run.find(123) progress = MaintenanceTasks::Progress.new(run) ``` -------------------------------- ### Batch Enumerator with Start Option Error Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/errors.md This snippet shows an `ArgumentError` raised when a batch enumerator with unsupported `start` or `finish` options is used in the `collection` method. ```ruby class BadTask < MaintenanceTasks::Task def collection Record.find_in_batches(start: 100) # start option not allowed end def process(batch) end end MaintenanceTasks::Runner.run(name: "BadTask") # => ArgumentError: BadTask#collection cannot support a batch enumerator... ``` -------------------------------- ### Prepare TaskDataShow Instance Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Loads task data and ensures the task exists or has run history. Use this to prepare a TaskDataShow instance with optional run pagination and arguments. ```ruby TaskDataShow.prepare( "Maintenance::BackfillTask", runs_cursor: "123" ) ``` -------------------------------- ### Get Task Name Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns the task name. This method is aliased to `to_s`. ```ruby task_data.name -> String ``` -------------------------------- ### Get Task Name Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns the task name. This method is an alias for `to_s`. ```ruby puts task_data.name # "Maintenance::BackfillTask" ``` -------------------------------- ### Run Task from CLI Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runner.md Illustrates how to execute a maintenance task using the command-line interface, including specifying a CSV file and task arguments. ```bash # bin/maintenance_tasks perform MyTask --csv=/path/to/file.csv --arguments=name:value ``` -------------------------------- ### progress.max Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Gets the maximum expected items to process. This accounts for cases where the total count was underestimated. ```APIDOC ## progress.max ### Description Maximum expected items to process. ### Method `progress.max` ### Logic: - If estimatable (has total and haven't exceeded it) → returns tick_total - Otherwise → returns tick_count (current best estimate) ### Note: Accounts for when tick_count exceeds tick_total (total was underestimated) ### Example: ```ruby progress.max # 1000 # If 1200 processed but expected 1000: progress.max # 1200 ``` ``` -------------------------------- ### Get Pagination Cursor Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Retrieves the current pagination cursor, which is the ID marking the pagination position. ```ruby page.cursor ``` -------------------------------- ### Initialize RunsPage Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Creates a paginated run page with specified runs and a cursor for pagination. ```ruby RunsPage.new(runs, cursor) ``` -------------------------------- ### Progress.new Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Creates a Progress tracker for a Run. This is the primary way to instantiate the Progress class. ```APIDOC ## Progress.new ### Description Creates a Progress tracker for a Run. ### Method `Progress.new(run)` ### Parameters #### Path Parameters - **run** (Run) - Required - The Run to track progress for ### Request Example ```ruby run = MaintenanceTasks::Run.find(123) progress = MaintenanceTasks::Progress.new(run) ``` ``` -------------------------------- ### TaskDataShow.prepare Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Loads task data and ensures the task exists or has run history. It returns a TaskDataShow instance with active/completed runs preloaded. ```APIDOC ## TaskDataShow.prepare ### Description Loads task data and ensures task exists (or has run history). ### Method Class Method ### Signature `TaskDataShow.prepare(name, runs_cursor: nil, arguments: nil) -> TaskDataShow` ### Parameters #### Arguments - **name** (String) - Required - Task class name - **runs_cursor** (String) - Optional - Cursor for pagination of completed runs - **arguments** (Hash) - Optional - Task arguments for instantiation ### Returns TaskDataShow instance with active/completed runs preloaded ### Raises `Task::NotFoundError` — if task has no runs and doesn't exist ### Example ```ruby task_data = MaintenanceTasks::TaskDataShow.prepare( "Maintenance::BackfillTask", runs_cursor: "123" ) ``` ``` -------------------------------- ### Create Run Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md Creates and enqueues a new task run. ```APIDOC ## Create Run ### Description Creates and enqueues a new task run. ### Method POST ### Endpoint /maintenance_tasks/tasks/:task_id/runs ### Parameters #### Path Parameters - **task_id** (String) - Required - Task class name #### Request Body - **csv_file** (File) - Conditional - CSV file (required if task uses CSV) - **task[param_name]** (Mixed) - Optional - Task argument values **Content-Type:** multipart/form-data (for CSV file upload) ### Response #### Success Response (302 Redirect) - **Location** - Redirects to task show page after creating run. #### Error Response (422 Unprocessable Entity) - **Status:** 422 Unprocessable Entity - **Template:** `maintenance_tasks/tasks/show.html.erb` - **Variables:** - `flash.now.alert` — Error message - `@task` — TaskDataShow with validation errors #### Error Response (302 Redirect - Value Too Long) - **Location:** Redirects with error message if arguments exceed column limits. #### Error Response (302 Redirect - Enqueuing Error) - **Location:** Redirects with error message if job enqueueing fails. ``` -------------------------------- ### Implement Task Callbacks: after_start Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Use the `after_start` callback to execute custom logic immediately after a task begins. Exceptions in this callback will be handled by the task's error handler and may stop the task. ```ruby module Maintenance class UpdatePostsTask < MaintenanceTasks::Task after_start :notify def notify NotifyJob.perform_later(self.class.name) end # ... end end ``` -------------------------------- ### Get Task Status Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns the status of the latest run (e.g., 'running', 'succeeded', 'errored'), or 'new' if no runs exist. ```ruby task_data.status -> String ``` -------------------------------- ### Get Related Run Record Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns the associated Run record (active or most recent completed), or nil if no runs exist. ```ruby task_data.related_run -> Run, nil ``` -------------------------------- ### Task Run Creation Logic Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md This Ruby code demonstrates the logic for creating a new task run, including handling CSV files, task arguments, and optional metadata configuration. ```ruby run = Runner.run( name: task_id, csv_file: params[:csv_file], arguments: params[:task].permit!.to_h, metadata: instance_exec(&MaintenanceTasks.metadata || -> {}) ) ``` -------------------------------- ### progress.value Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Gets the current progress value, which is the number of items processed. Returns nil if progress cannot be estimated and the run is still active. ```APIDOC ## progress.value ### Description Current progress value (number of items processed). ### Method `progress.value` ### Returns - Integer (tick_count) if progress is estimatable OR run is stopped - nil if progress cannot be estimated and run is still running ### Logic: - Stopped runs always return a value - Running runs return nil if total is unknown (shows indefinite progress) ### Example: ```ruby progress.value # 250 out of 1000 progress.value # 500 (if run completed) ``` ``` -------------------------------- ### Instantiate Task with Arguments Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Instantiates the Task class with assigned arguments. Returns a Task instance if the task exists, otherwise returns nil if the task file was deleted. ```ruby task = task_data.new task.process # Execute task ``` -------------------------------- ### before_perform Method Implementation Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-job.md Initializes the job execution context before performing the job. This includes loading the Run, preparing the Task, and setting up the Ticker. ```ruby def before_perform -> void ``` -------------------------------- ### Run a Task with Arguments from Command Line Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Execute a maintenance task that accepts command-line arguments using the `--arguments` option. Arguments are provided as key-value pairs. ```sh bundle exec maintenance_tasks perform Maintenance::ParamsTask \ --arguments post_ids:1,2,3 content:"Hello, World!" ``` -------------------------------- ### Get Parameter Names Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns an array of strings representing the names of parameters the Task accepts. Returns an empty array if the Task is deleted. ```ruby task_data.parameter_names # ["status", "country", "batch_size"] ``` -------------------------------- ### Get Paginated Runs Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Retrieves paginated completed runs for the task. Returns up to 20 most recent runs and includes a cursor for the next page. ```ruby task_data.runs_page -> RunsPage ``` -------------------------------- ### complete Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Marks the run as succeeded and sets the ended_at timestamp. It should be followed by `persist_transition`. ```APIDOC ## complete ### Description Marks run as succeeded and sets ended_at timestamp. ### Method `complete` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```ruby run.complete run.persist_transition ``` ### Response #### Success Response - **void** #### Response Example None ``` -------------------------------- ### Get Task Category Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Categorizes the task based on the status of its related run. Returns :active, :new, or :completed. Used for grouping tasks in the UI. ```ruby task_data.category -> Symbol ``` -------------------------------- ### CLI: list Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/README.md Command-line interface command to list all available maintenance tasks. ```APIDOC ## CLI: list ### Description Lists all available maintenance tasks that can be performed via the command line. ### Command `bundle exec maintenance_tasks list` ``` -------------------------------- ### Import Posts from CSV with Options Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md This snippet demonstrates how to import posts from a CSV file using the `csv_collection` macro with options to skip comment lines and strip whitespace from fields. ```ruby module Maintenance class ImportPosts csv_collection(skip_lines: /^#/, converters: ->(field) { field.strip }) def process(row) Post.create!(title: row["title"], content: row["content"]) end end end ``` -------------------------------- ### List Available Maintenance Tasks Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md Use this GET request to retrieve a list of all available maintenance tasks, categorized by their status (active, new, completed). ```http GET /maintenance_tasks GET /maintenance_tasks/tasks ``` -------------------------------- ### CSV File Preparation Logic Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/cli.md The `csv_file` method prepares the CSV input for the runner. It handles stdin, file paths, and raises an error for non-existent files. ```ruby def csv_file return unless options.key?(:csv) csv_option = options[:csv] if csv_option == :stdin { io: StringIO.new($stdin.read), filename: "stdin.csv", content_type: "text/csv", } else { io: File.open(csv_option), filename: File.basename(csv_option), content_type: "text/csv", } end rescue Errno::ENOENT raise ArgumentError, "CSV file not found: #{csv_option}" end ``` -------------------------------- ### Get Completed Runs Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns finished task executions with statuses succeeded, errored, or cancelled. The value is cached after first access and serves as historical reference. ```ruby task_data.completed_runs -> ActiveRecord::Relation ``` -------------------------------- ### Handling Task::NotFoundError Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/errors.md Demonstrates how to rescue and handle a Task::NotFoundError. This allows for graceful failure and alternative actions, such as displaying archived run history. ```ruby begin task = MaintenanceTasks::Task.named("MyTask") rescue MaintenanceTasks::Task::NotFoundError => e puts "Task not found: #{e.message}" # May want to show archived run history instead end ``` -------------------------------- ### Get Next Page Cursor Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runs-page.md Returns the cursor for the next page, which is the ID of the last record on the current page. Raises an error if called when records is empty. ```ruby page.next_cursor ``` -------------------------------- ### Task Show Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md Displays a specific task, its source code, parameters, and run history. ```APIDOC ## Task Show ### Description Displays a specific task, its source code, parameters, and run history. ### Method GET ### Endpoint /maintenance_tasks/tasks/:id ### Parameters #### Path Parameters - **id** (String) - Required - Task class name (e.g., "Maintenance::BackfillTask") #### Query Parameters - **cursor** (String) - Optional - Pagination cursor for completed runs - **{other}** (Mixed) - Optional - Task arguments as query parameters ### Response #### Success Response (200 OK) - **@task** (TaskDataShow) - An object containing task details. - **name** (String) - Task class name - **active_runs** (Array) - Array of currently running executions - **runs_page** (RunsPage) - Object with pagination information for runs - **code** (String) - Source file content (nil if deleted) - **csv_task?** (Boolean) - Whether the task processes CSV - **parameter_names** (Array) - Array of argument names ``` -------------------------------- ### Get Masked Run Arguments Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Returns run arguments with sensitive data filtered using Rails.application.config.filter_parameters and Task's masked_arguments. Returns nil if no arguments are present. ```ruby safe_args = run.masked_arguments # { api_key: '[FILTERED]' } ``` -------------------------------- ### Executable Script Entry Point Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/cli.md The `maintenance_tasks` executable script is the entry point for the CLI. It requires the CLI library and delegates execution to `MaintenanceTasks::CLI.start`. ```ruby #!/usr/bin/env ruby # exe/maintenance_tasks require "maintenance_tasks/cli" MaintenanceTasks::CLI.start(ARGV) ``` -------------------------------- ### Error Reporting in Rails Application Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/README.md Subscribe to Rails' error reporting system to capture exceptions originating from maintenance tasks. This example sends maintenance task errors to Sentry. ```ruby Rails.error.subscribe do |error, handled:, context:| if context[:source] == "maintenance-tasks" Sentry.capture_exception(error) end end ``` -------------------------------- ### Use Progress in Controllers Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Demonstrates how to instantiate and use the Progress class within a Rails controller to track task progress. ```ruby class TasksController < ApplicationController def show @run = MaintenanceTasks::Run.find(params[:id]) @progress = MaintenanceTasks::Progress.new(@run) end end ``` -------------------------------- ### Eager Load CSV Attachment Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/run.md Eagerly loads the associated CSV file attachment for runs, provided Active Storage is installed. This is efficient for fetching runs that have associated CSV data. ```ruby Run.with_attached_csv -> ActiveRecord::Relation ``` ```ruby runs = MaintenanceTasks::Run.with_attached_csv.limit(10) ``` -------------------------------- ### List available maintenance tasks Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/cli.md Display a list of all available maintenance tasks. The output is sorted alphabetically, with one task per line. ```bash $ bundle exec maintenance_tasks list Maintenance::ArchiveTask Maintenance::BackfillTask Maintenance::CleanupTask ``` -------------------------------- ### Custom Rails Error Reporter Subscriber Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Example of a custom subscriber to Rails.error.report for integrating with an exception monitoring service like Bugsnag. This snippet demonstrates how to capture and report task-related errors. ```ruby Bugsnag.notify(error) do |report| report.add_tab(:maintenance_tasks, context) end ``` -------------------------------- ### Initialize TaskDataIndex Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Creates a TaskDataIndex instance with a task name and an optional related run record. ```ruby TaskDataIndex.new(name, related_run = nil) ``` -------------------------------- ### Optimize CSV Task Count Method Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md An alternative implementation for the `#count` method in CSV tasks to avoid parsing the entire file. This example counts newlines to approximate the row count. ```ruby def count csv_content.count("\n") - 1 end ``` -------------------------------- ### Subscribe to Maintenance Tasks Errors Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/errors.md Example of subscribing to Rails' error reporter to handle errors originating from the maintenance-tasks source. This allows custom error logging or reporting, such as sending to Sentry. ```ruby Rails.error.handle(source: "maintenance-tasks") do MaintenanceTasks::Runner.run(name: "MyTask") end Rails.error.subscribe do |error, handled:, context:| if context[:source] == "maintenance-tasks" puts "Task error: #{context[:task_name]}" puts "Error: #{error.message}" Sentry.capture_exception(error) end end ``` -------------------------------- ### Run a Task with Arguments from Ruby Source: https://github.com/shopify/maintenance_tasks/blob/main/README.md Execute a maintenance task that accepts arguments from Ruby using `MaintenanceTasks::Runner.run`. Pass arguments as a hash to the `arguments` option. ```ruby MaintenanceTasks::Runner.run( name: "Maintenance::ParamsTask", arguments: { post_ids: "1,2,3" } ) ``` -------------------------------- ### Define a Custom High-Priority Task Job Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-job.md Example of defining a custom job that inherits from ActiveJob::Base and includes MaintenanceTasks::TaskJobConcern. It specifies a high-priority queue and custom error handling. ```ruby class HighPriorityTaskJob < ActiveJob::Base include MaintenanceTasks::TaskJobConcern queue_as :maintenance_high_priority def on_error(error) Sentry.capture_exception(error) super # Calls default error handling end end MaintenanceTasks.job = "HighPriorityTaskJob" ``` -------------------------------- ### CLI Option Parsing for CSV Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/cli.md Demonstrates how the CSV option is parsed. It defaults to stdin if no value is provided, and accepts a file path or '-' for stdin. ```ruby option :csv, lazy_default: :stdin, desc: "..." ``` -------------------------------- ### CsvCollectionBuilder Class Initialization Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/collection-builders.md Initializes the CsvCollectionBuilder, accepting CSV parsing options. Defaults to `{headers: true}`. ```ruby class CsvCollectionBuilder def initialize(**csv_options) end ``` -------------------------------- ### Get Active Runs Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/task-data.md Returns currently running task executions, including statuses like enqueued, running, pausing, cancelling, paused, and interrupted. The value is cached after first access. ```ruby task_data.active_runs -> ActiveRecord::Relation ``` -------------------------------- ### Run a Basic Maintenance Task Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runner.md Creates a Run record and enqueues a Job for a specified task. Use this for simple task execution without additional parameters. ```ruby task = MaintenanceTasks::Runner.run(name: "Maintenance::BackfillTask") ``` -------------------------------- ### Show Specific Task Details Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/endpoints.md Use this GET request to view the details of a specific maintenance task, including its source code, parameters, and run history. The task ID is the class name. ```http GET /maintenance_tasks/tasks/:id ``` -------------------------------- ### Get Current Progress Value Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/progress.md Retrieves the current number of items processed. Returns an Integer if progress is estimatable or the run is stopped, otherwise nil if the run is still running and progress cannot be estimated. ```ruby progress.value -> Integer, nil ``` ```ruby progress.value # 250 out of 1000 progress.value # 500 (if run completed) ``` -------------------------------- ### Runner.run Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/api-reference/runner.md Creates a Run record for a Task and enqueues the Job for execution. This method allows for basic task execution, tasks with arguments, CSV file processing, and custom metadata persistence. ```APIDOC ## Runner.run ### Description Creates a Run record for a Task and enqueues the Job for execution. This method allows for basic task execution, tasks with arguments, CSV file processing, and custom metadata persistence. ### Method Signature `Runner.run(name:, csv_file: nil, arguments: {}, run_model: Run, metadata: nil) { |run| ... } -> Task` ### Parameters #### Path Parameters * **name** (String) - Required - Task class name (e.g., "Maintenance::BackfillTask") * **csv_file** (Hash, nil) - Optional - Attachable CSV file (see ActiveStorage::Attached::One#attach) * **arguments** (Hash) - Optional - Task parameters to persist and pass to Task instance * **run_model** (Class) - Optional - Run model class (for testing/custom implementations) * **metadata** (Hash, nil) - Optional - Custom metadata to persist with the run * **block** (Proc) - Optional - Optional block yielded with Run before enqueueing ### CSV File Structure ```ruby { io: File.open('path.csv'), # or StringIO filename: 'data.csv', content_type: 'text/csv' } ``` ### Returns Task class (not instance) ### Raises * `EnqueuingError` — if Job fails to enqueue * `ActiveRecord::RecordInvalid` — if Run validation fails * `ActiveRecord::ValueTooLong` — if argument values exceed column limits ### Examples **Basic task:** ```ruby task = MaintenanceTasks::Runner.run(name: "Maintenance::BackfillTask") ``` **With arguments:** ```ruby task = MaintenanceTasks::Runner.run( name: "Maintenance::UpdateUsersTask", arguments: { status: "active", country: "US" } ) ``` **CSV task:** ```ruby csv_file = { io: File.open('users.csv'), filename: 'users.csv', content_type: 'text/csv' } task = MaintenanceTasks::Runner.run( name: "Maintenance::ImportUsersTask", csv_file: csv_file ) ``` **With metadata and block:** ```ruby task = MaintenanceTasks::Runner.run( name: "Maintenance::CleanupTask", metadata: { triggered_by: "admin_user", reason: "manual_cleanup" } ) do |run| # Inspect/modify run before enqueueing puts "Run ID: #{run.id}" end ``` **From CLI:** ```ruby # bin/maintenance_tasks perform MyTask --csv=/path/to/file.csv --arguments=name:value ``` ``` -------------------------------- ### CLI: perform Source: https://github.com/shopify/maintenance_tasks/blob/main/_autodocs/README.md Command-line interface command to perform a specific maintenance task. ```APIDOC ## CLI: perform ### Description Executes a specified maintenance task directly from the command line. ### Command `bundle exec maintenance_tasks perform TaskName [--csv data.csv] [--args key=value]` ### Parameters - **TaskName** (string) - Required - The name of the task to perform. - **--csv** (string) - Optional - Path to a CSV file to process. - **--args** (string) - Optional - Arguments to pass to the task, formatted as key=value pairs. ```