Reactor.File Cheatsheet

View Source

Reactor.File is an extension that provides file system operations as steps within Reactor workflows.

Getting Started

Basic Setup

defmodule MyFileReactor do
  use Reactor, extensions: [Reactor.File]

  input :source_path
  input :dest_path

  read_file :content do
    path input(:source_path)
  end

  write_file :output do
    path input(:dest_path)
    content result(:content)
  end

  return :output
end

Installation

def deps do
  [
    {:reactor_file, "~> 0.18.2"}
  ]
end

File Operations

Reading Files

# Read entire file
read_file :config do
  path value("/etc/config.json")
end

# Using inputs/results
read_file :user_data do
  path input(:file_path)
end

Writing Files

# Write simple content
write_file :output do
  path input(:output_path)
  content value("Hello, World!")
end

# Write with revert capability
write_file :backup do
  path input(:backup_path)
  content result(:processed_data)
  revert_on_undo? true
end

Copying Files

# Copy single file
cp :backup_file do
  source input(:source_path)
  destination input(:dest_path)
end

# Copy recursively
cp_r :backup_directory do
  source input(:source_dir)
  destination input(:backup_dir)
end

Directory Operations

Creating Directories

# Create single directory
mkdir :new_dir do
  path input(:new_directory_path)
end

# Create with parents
mkdir_p :deep_path do
  path input(:deep_directory_path)
  revert_on_undo? true
end

File Discovery

# Find files by pattern
glob :txt_files do
  pattern input(:search_pattern)
end

# Include hidden files
glob :all_configs do
  pattern value("/etc/**/*.conf")
  match_dot true
end

Removing Files

# Remove single file
rm :temp_file do
  path input(:file_to_remove)
end

# Remove directory
rmdir :empty_dir do
  path input(:directory_to_remove)
end

File I/O Operations

File Handles

# Open file for reading
open_file :file_handle do
  path input(:data_file_path)
  modes [:read]
end

# Open for writing
open_file :output_handle do
  path input(:log_file_path)
  modes [:write, :append]
end

# Close when done
close_file :cleanup do
  file result(:file_handle)
end

Stream Reading

# Read as lines
io_stream :lines do
  file result(:file_handle)
end

# Binary streaming
io_binstream :chunks do
  file result(:binary_handle)
  line_or_bytes 4096
end

Direct I/O

# Read specific amount
io_read :chunk do
  file result(:file_handle)
  length 1024
end

# Write to file handle
io_write :append_data do
  file result(:output_handle)
  data input(:log_message)
end

File Metadata

File Information

# Get file stats
stat :file_info do
  path input(:target_file)
end

# Get link stats (doesn't follow symlinks)
lstat :link_info do
  path input(:symlink_path)
end

# Read symlink target
read_link :target do
  path input(:symlink_path)
end
# Hard link
ln :hard_link do
  existing input(:original_file)
  new input(:hardlink_path)
end

# Symbolic link
ln_s :soft_link do
  existing input(:original_file)
  new input(:symlink_path)
end

Permissions & Ownership

Changing Permissions

# Set file permissions
chmod :make_executable do
  path input(:script_path)
  mode value(0o755)
end

# Use template for dynamic permissions
chmod :set_perms do
  path input(:file_path)
  mode input(:permission_mode)
  revert_on_undo? true
end

Changing Ownership

# Change owner
chown :change_owner do
  path input(:log_file)
  uid input(:new_owner_id)
  revert_on_undo? true
end

# Change group
chgrp :change_group do
  path input(:shared_directory)
  gid input(:group_id)
end

Writing File Stats

# Update timestamps and permissions
write_stat :update_metadata do
  path input(:target_file)
  stat result(:new_stat_info)
end

Advanced Patterns

File Processing Pipeline

defmodule ProcessFiles do
  use Reactor, extensions: [Reactor.File]

  input :directory

  glob :source_files do
    pattern input(:directory), transform: &Path.join(&1, "*.txt")
  end

  map :process_files do
    source result(:source_files)

    read_file :content do
      path element(:process_files)
    end

    step :transform do
      argument :data, result(:content)
      run &String.upcase/1
    end

    write_file :output do
      path element(:process_files), transform: &(&1 <> ".processed")
      content result(:transform)
    end

    return :output
  end

  return :process_files
end

Backup and Restore

# Create backup with metadata preservation
stat :original_stats do
  path input(:source_file)
end

cp :backup_file do
  source input(:source_file)
  destination input(:backup_path)
end

write_stat :preserve_metadata do
  path input(:backup_path)
  stat result(:original_stats)
end

File Validation

# Check file exists and is readable
stat :validate_source do
  path input(:source_path)
end

step :check_permissions do
  argument :stat, result(:validate_source)
  run fn %{stat: %{access: access}}, _context ->
    if :read in access do
      {:ok, :valid}
    else
      {:error, "File not readable"}
    end
  end
end

Error Handling

Common Patterns

# Handle missing files gracefully
read_file :optional_config do
  path value("/etc/app/config.json")
end

step :use_defaults do
  argument :config, result(:optional_config)
  run fn
    %{config: content}, _context -> 
      {:ok, Jason.decode!(content)}
    %{}, _context -> 
      {:ok, %{default: true}}
  end
  where config_exists?/1
end

# Guard function
def config_exists?(%{config: _}), do: true
def config_exists?(_), do: false

Undoable Operations

# Operations that can be reverted
mkdir_p :temp_workspace do
  path input(:workspace_path)
  revert_on_undo? true
end

write_file :temp_data do
  path input(:workspace_path), transform: &Path.join(&1, "data.json")
  content input(:json_data)
  revert_on_undo? true
end

chmod :secure_temp do
  path input(:workspace_path)
  mode value(0o700)
  revert_on_undo? true
end

Common Options

Universal Options

OptionTypeDescription
nameatomUnique step identifier
descriptionstringOptional step description

Revert Options

OptionTypeDefaultDescription
revert_on_undo?booleanfalseRestore original state on undo

File Mode Options

ModeDescription
:readRead-only access
:writeWrite access
:appendAppend to file
:exclusiveFail if file exists
:rawRaw binary mode
:binaryBinary mode
:compressedEnable compression