-
Notifications
You must be signed in to change notification settings - Fork 59
Enhancement: Implement customizable post-task cleanup policies (#1611) #1641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # | ||
| # CBRAIN Project | ||
| # | ||
| # Copyright (C) 2008-2026 | ||
| # The Royal Institution for the Advancement of Learning | ||
| # McGill University | ||
| # | ||
|
|
||
| # Removes the cached inputs of a CBRAIN task safely from the local cache. | ||
| # Must be run on a Bourreau only. | ||
| class BackgroundActivity::RemoveTaskInputs < BackgroundActivity::TerminateTask | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bad name for that class, we are not removing inputs ! We are removing the cached copies of inputs. |
||
|
|
||
| Revision_info = CbrainFileRevision[__FILE__] #:nodoc: | ||
|
|
||
| def process(item) | ||
| super(item) | ||
|
|
||
| cbrain_task = CbrainTask.where(:bourreau_id => CBRAIN::SelfRemoteResourceId).find_by(id: item) | ||
| return [false, "Task not found"] unless cbrain_task | ||
|
|
||
| input_userfile_ids = cbrain_task.params[:interface_userfile_ids] || [] | ||
|
|
||
| input_userfile_ids.each do |userfile_id| | ||
| userfile = Userfile.find_by(id: userfile_id) | ||
| next unless userfile | ||
|
|
||
| # Safety check: skip if another active task relies on this exact input | ||
| file_in_use = CbrainTask.active | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can restrict the search to only the active tasks on the current server, we don't really care if a file is being used on a different one. |
||
| .where.not(id: cbrain_task.id) | ||
| .any? { |t| t.params[:interface_userfile_ids]&.include?(userfile_id) } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can't be sure that t.params[:interface_userfile_ids] will contain an array of IDs that are numeric or string. This is a known inconsistent part of CBRAIN. So your comparison with .any? { |t| (t.params[:interface_userfile_ids] || []).map(&:to_s)
.include?(userfile_id.to_s)
} |
||
|
|
||
| if file_in_use | ||
| self.addlog("Skipped cache erase for '#{userfile.name}' (ID: #{userfile_id}) - asset is currently in use.") | ||
| next | ||
| end | ||
|
|
||
| userfile.cache_erase | ||
| self.addlog("Deleted cache of input file '#{userfile.name}' (ID: #{userfile_id}) via post-task cleanup policy.") | ||
| end | ||
|
|
||
| [true, nil] | ||
| end | ||
|
|
||
| def prepare_dynamic_items | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is leftover from another BAC, it shouldn't be here. |
||
| populate_items_from_task_custom_filter | ||
| end | ||
|
|
||
| end | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing final NL |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # | ||
| # CBRAIN Project | ||
| # | ||
| # Copyright (C) 2008-2026 | ||
| # The Royal Institution for the Advancement of Learning | ||
| # McGill University | ||
| # | ||
|
|
||
| # Removes the cached outputs of a CBRAIN task safely from the local cache. | ||
| # Must be run on a Bourreau only. | ||
| class BackgroundActivity::RemoveTaskOutputs < BackgroundActivity::TerminateTask | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, this is a bad name for that class, we are not removing |
||
|
|
||
| Revision_info = CbrainFileRevision[__FILE__] #:nodoc: | ||
|
|
||
| def process(item) | ||
| super(item) | ||
|
|
||
| cbrain_task = CbrainTask.where(:bourreau_id => CBRAIN::SelfRemoteResourceId).find_by(id: item) | ||
| return [false, "Task not found"] unless cbrain_task | ||
|
|
||
| output_userfiles = Userfile.where(task_id: cbrain_task.id).to_a | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is non-sense; there is no such relation between userfiles and tasks. You can't find the output of tasks using a relation, you need to query the params array of a task. Task models needs to be extended with a method that returns their output IDs. For BoutiquesTasks, these would be recognized by looking up the keys
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fact that this code is submitted and would crash (because |
||
|
|
||
| if output_userfiles.empty? | ||
| self.addlog("No output userfiles registered to erase for task ##{item}.") | ||
| return [true, nil] | ||
| end | ||
|
|
||
| output_userfiles.each do |userfile| | ||
| userfile_id = userfile.id | ||
|
|
||
| # Safety check: ensure no downstream task is reading this output file | ||
| output_in_use = CbrainTask.active | ||
| .where.not(id: cbrain_task.id) | ||
| .any? { |t| t.params[:interface_userfile_ids]&.include?(userfile_id) } | ||
|
|
||
| if output_in_use | ||
| self.addlog("Skipped output cache erase for '#{userfile.name}' (ID: #{userfile_id}) - asset is in use downstream.") | ||
| next | ||
| end | ||
|
|
||
| userfile.cache_erase | ||
| self.addlog("Deleted cache of output file '#{userfile.name}' (ID: #{userfile_id}) via post-task cleanup policy.") | ||
| end | ||
|
|
||
| [true, nil] | ||
| end | ||
|
|
||
| def prepare_dynamic_items | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also spurious. |
||
| populate_items_from_task_custom_filter | ||
| end | ||
|
|
||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| class AddCleanupPoliciesToCbrainTasks < ActiveRecord::Migration[5.0] | ||
| def change | ||
| add_column :cbrain_tasks, :success_cleanup_policy, :string, default: 'keep_all' | ||
| add_column :cbrain_tasks, :failure_cleanup_policy, :string, default: 'keep_all' | ||
| end | ||
| end | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing final NL |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the code including in "bourreau_worker.rb" is misplaced. The role of the BourreauWorker is to manage the life cycle of the task, e.g. how each state is turned into another, but not the actual work being performed during each state.
So the code for cleaning up inputs and outputs should instead be integrated into the class ClusterTask.