Class: Ace::Assign::Molecules::AssignmentManager
- Inherits:
-
Object
- Object
- Ace::Assign::Molecules::AssignmentManager
- Defined in:
- lib/ace/assign/molecules/assignment_manager.rb
Overview
Manages assignment YAML file operations.
Handles creation, loading, and updating of assignment.yaml files. Uses ace-b36ts for assignment ID generation.
Instance Method Summary collapse
-
#clear_current ⇒ Object
Clear current assignment selection.
-
#create(name:, source_config:, description: nil, parent: nil) ⇒ Models::Assignment
Create a new assignment.
-
#current_id ⇒ String?
Get the currently selected assignment ID (from .current symlink).
-
#delete(assignment_id) ⇒ Boolean
Delete an assignment’s cache directory and clean up symlinks.
-
#find_active ⇒ Models::Assignment?
Find the most recent active assignment.
-
#initialize(cache_base: nil) ⇒ AssignmentManager
constructor
A new instance of AssignmentManager.
-
#list ⇒ Array<Models::Assignment>
List all assignments.
-
#load(assignment_id) ⇒ Models::Assignment?
Load an existing assignment by ID.
-
#set_current(assignment_id) ⇒ Object
Set current assignment via .current symlink.
-
#update(assignment) ⇒ Models::Assignment
Update assignment metadata.
Constructor Details
#initialize(cache_base: nil) ⇒ AssignmentManager
Returns a new instance of AssignmentManager.
16 17 18 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 16 def initialize(cache_base: nil) @cache_base = cache_base || Ace::Assign.cache_dir end |
Instance Method Details
#clear_current ⇒ Object
Clear current assignment selection
Removes the .current symlink, falling back to .latest resolution
135 136 137 138 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 135 def clear_current current_symlink = File.join(@cache_base, ".current") File.delete(current_symlink) if File.symlink?(current_symlink) end |
#create(name:, source_config:, description: nil, parent: nil) ⇒ Models::Assignment
Create a new assignment
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 27 def create(name:, source_config:, description: nil, parent: nil) # Ensure cache base directory exists before generate_assignment_id FileUtils.mkdir_p(@cache_base) assignment_id = generate_assignment_id cache_dir = File.join(@cache_base, assignment_id) # Create directories FileUtils.mkdir_p(cache_dir) FileUtils.mkdir_p(File.join(cache_dir, "steps")) FileUtils.mkdir_p(File.join(cache_dir, "reports")) now = Time.now.utc assignment = Models::Assignment.new( id: assignment_id, name: name, description: description, created_at: now, updated_at: now, source_config: source_config, cache_dir: cache_dir, parent: parent ) # Write assignment.yaml write_assignment_file(assignment) # Update .latest symlink for O(1) active assignment lookup update_latest_symlink(assignment_id) assignment end |
#current_id ⇒ String?
Get the currently selected assignment ID (from .current symlink)
143 144 145 146 147 148 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 143 def current_id current_symlink = File.join(@cache_base, ".current") return nil unless File.symlink?(current_symlink) File.basename(File.readlink(current_symlink)) end |
#delete(assignment_id) ⇒ Boolean
Delete an assignment’s cache directory and clean up symlinks
154 155 156 157 158 159 160 161 162 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 154 def delete(assignment_id) dir = File.join(@cache_base, assignment_id) return false unless File.directory?(dir) cleanup_symlink(".current", assignment_id) cleanup_symlink(".latest", assignment_id) FileUtils.rm_rf(dir) true end |
#find_active ⇒ Models::Assignment?
Find the most recent active assignment
Uses resolution order:
-
.current symlink (explicit user selection)
-
.latest symlink (auto, most recent)
-
Scan all assignments (fallback)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 83 def find_active return nil unless File.directory?(@cache_base) # Priority 1: use .current symlink if it exists (explicit selection) current_symlink = File.join(@cache_base, ".current") if File.symlink?(current_symlink) assignment_id = File.basename(File.readlink(current_symlink)) assignment = load(assignment_id) return assignment if assignment end # Priority 2: use .latest symlink if it exists latest_symlink = File.join(@cache_base, ".latest") if File.symlink?(latest_symlink) assignment_id = File.basename(File.readlink(latest_symlink)) assignment = load(assignment_id) return assignment if assignment end # Fallback: find all assignment directories assignments = Dir.glob(File.join(@cache_base, "*", "assignment.yaml")) .map { |f| load_from_file(f) } .compact .sort_by(&:updated_at) .reverse assignments.first end |
#list ⇒ Array<Models::Assignment>
List all assignments
192 193 194 195 196 197 198 199 200 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 192 def list return [] unless File.directory?(@cache_base) Dir.glob(File.join(@cache_base, "*", "assignment.yaml")) .map { |f| load_from_file(f) } .compact .sort_by(&:updated_at) .reverse end |
#load(assignment_id) ⇒ Models::Assignment?
Load an existing assignment by ID
65 66 67 68 69 70 71 72 73 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 65 def load(assignment_id) cache_dir = File.join(@cache_base, assignment_id) assignment_file = File.join(cache_dir, "assignment.yaml") return nil unless File.exist?(assignment_file) data = YAML.safe_load_file(assignment_file, permitted_classes: [Time, Date]) Models::Assignment.from_h(data, cache_dir: cache_dir) end |
#set_current(assignment_id) ⇒ Object
Set current assignment via .current symlink
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 116 def set_current(assignment_id) assignment = load(assignment_id) raise AssignmentErrors::NotFound, "Assignment '#{assignment_id}' not found" unless assignment current_symlink = File.join(@cache_base, ".current") # Remove old symlink if it exists File.delete(current_symlink) if File.symlink?(current_symlink) # Create new symlink target_dir = File.join(@cache_base, assignment_id) File.symlink(target_dir, current_symlink) assignment end |
#update(assignment) ⇒ Models::Assignment
Update assignment metadata
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/ace/assign/molecules/assignment_manager.rb', line 168 def update(assignment) # Create new assignment with updated timestamp updated = Models::Assignment.new( id: assignment.id, name: assignment.name, description: assignment.description, created_at: assignment.created_at, updated_at: Time.now.utc, source_config: assignment.source_config, cache_dir: assignment.cache_dir, parent: assignment.parent ) write_assignment_file(updated) # Update .latest symlink since this assignment was just updated update_latest_symlink(assignment.id) updated end |