Class: Aias::CrontabManager

Inherits:
Object
  • Object
show all
Includes:
BlockParser
Defined in:
lib/aias/crontab_manager.rb

Constant Summary collapse

IDENTIFIER =
"aias"
BLOCK_OPEN =
"# BEGIN aias"
BLOCK_CLOSE =
"# END aias"
ENTRY_RE =

Parses cron lines generated by JobBuilder. Current format (flags before prompt_id, single redirect):

<cron> <shell> -c 'source <env.sh> && <aia> [--prompts-dir <dir>] [--config <cfg>] <prompt_id> > <log> 2>&1'

Legacy formats (with -l, inline env vars, flags after prompt_id, >>) are also matched for backward compatibility when reading older installed entries.

/^(?<cron>[^\/\n]+)\s+\/\S+\s+(?:-l\s+)?-c\s+['"](?:source\s+\S+\s+&&\s+)?(?:\w+=\S+\s+)*(?:[^\s'"]*\/)?aia\s+(?:--prompts-dir\s+\S+\s+)?(?:--config(?:-file)?\s+\S+\s+)?(?<prompt_id>(?!--)\S+)(?:\s+--prompts-dir\s+\S+)?(?:\s+--config(?:-file)?\s+\S+)?\s+>>?\s+(?<log>\S+)\s+2>&1/

Instance Method Summary collapse

Constructor Details

#initialize(crontab_command: "crontab", log_base: Paths::SCHEDULE_LOG) ⇒ CrontabManager



21
22
23
24
# File 'lib/aias/crontab_manager.rb', line 21

def initialize(crontab_command: "crontab", log_base: Paths::SCHEDULE_LOG)
  @crontab_command = crontab_command
  @log_base        = log_base
end

Instance Method Details

#add_job(cron_line, prompt_id) ⇒ Object

Inserts or replaces a single cron job in the aias block (upsert). Any existing entry whose prompt_id matches is removed first, then the new line is appended. All other managed entries are left untouched. Raises Aias::Error if the crontab write fails.



75
76
77
78
79
80
81
82
# File 'lib/aias/crontab_manager.rb', line 75

def add_job(cron_line, prompt_id)
  FileUtils.mkdir_p(@log_base, mode: 0o700)
  current  = read_crontab
  existing = extract_block(current, BLOCK_OPEN, BLOCK_CLOSE).each_line.map(&:chomp).reject(&:empty?)
  updated  = existing.reject { |l| ENTRY_RE.match(l)&.[](:prompt_id) == prompt_id }
  updated << cron_line
  write_crontab(replace_block(current, updated))
end

#clearObject

Removes the aias-managed block from the crontab. Non-aias entries are not touched.



37
38
39
# File 'lib/aias/crontab_manager.rb', line 37

def clear
  write_crontab(remove_block(read_crontab))
end

#current_blockObject

Returns the raw text of the aias-managed block currently in the crontab (markers excluded). Returns an empty string when no block exists.



49
50
51
# File 'lib/aias/crontab_manager.rb', line 49

def current_block
  extract_block(read_crontab, BLOCK_OPEN, BLOCK_CLOSE)
end

#dry_run(cron_lines) ⇒ Object

Returns the cron lines as they would be written, without touching the crontab. Useful for aias dry-run.



43
44
45
# File 'lib/aias/crontab_manager.rb', line 43

def dry_run(cron_lines)
  Array(cron_lines).join("\n")
end

#ensure_log_directories(prompt_ids) ⇒ Object

Creates subdirectory structure under @log_base for each prompt_id. Called by CLI before install to ensure log dirs exist.



99
100
101
102
103
# File 'lib/aias/crontab_manager.rb', line 99

def ensure_log_directories(prompt_ids)
  prompt_ids.each do |id|
    FileUtils.mkdir_p(File.dirname(File.join(@log_base, "#{id}.log")), mode: 0o700)
  end
end

#install(cron_lines) ⇒ Object

Installs the given cron lines into the user's crontab, replacing any previously installed aias block. Creates the log base directory first. Raises Aias::Error if the crontab write fails.



29
30
31
32
33
# File 'lib/aias/crontab_manager.rb', line 29

def install(cron_lines)
  FileUtils.mkdir_p(@log_base, mode: 0o700)
  updated = replace_block(read_crontab, Array(cron_lines))
  write_crontab(updated)
end

#installed_jobsObject

Returns an Array of Hashes describing each installed aias cron job. Each hash has :prompt_id, :cron_expr, and :log_path keys.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/aias/crontab_manager.rb', line 55

def installed_jobs
  current_block.each_line.filter_map do |line|
    line = line.strip
    next if line.empty? || line.start_with?("#")

    match = ENTRY_RE.match(line)
    next unless match

    {
      prompt_id: match[:prompt_id],
      cron_expr: match[:cron].strip,
      log_path:  match[:log]
    }
  end
end

#remove_job(prompt_id) ⇒ Object

Removes a single cron job from the aias block by prompt_id. All other managed entries are left untouched. Raises Aias::Error if the prompt_id is not currently installed or if the crontab write fails.

Raises:



88
89
90
91
92
93
94
95
# File 'lib/aias/crontab_manager.rb', line 88

def remove_job(prompt_id)
  current  = read_crontab
  existing = extract_block(current, BLOCK_OPEN, BLOCK_CLOSE).each_line.map(&:chomp).reject(&:empty?)
  updated  = existing.reject { |l| ENTRY_RE.match(l)&.[](:prompt_id) == prompt_id }
  raise Aias::Error, "'#{prompt_id}' is not currently installed" if updated.size == existing.size

  write_crontab(replace_block(current, updated))
end