Enhancement: Implement customizable post-task cleanup policies (#1611)#1641
Enhancement: Implement customizable post-task cleanup policies (#1611)#1641AviJxn wants to merge 2 commits into
Conversation
…ies for success and failure states
|
Hey @prioux it looks like the CI pipeline is dropping on a strict framework sequence error. The workflow runs rake db:seed before executing pending migrations, which triggers a crash on my new cleanup policy migration ( |
|
@AviJxn That's because your pull request includes a migration, but it doesn't include the effect of that migration on the full schema. In your work environment, when you apply your migration, it will also update the file db/schema.rb which describe the final effect of the DB. That file is what is loaded in CI. During a CI check, no migrations are applied, because the DB is initialized right from the start with the final schema. |
prioux
left a comment
There was a problem hiding this comment.
There are many issues here. See comments.
Also, there are missing elements that I would ideally have liked to have in this PR:
- provide an abstract CbrainTask method that returns the IDs of outputs; the default would be [] and subclasses would override this, thus giving the framework an easy access to the list of outputs of a task. BoutiquesTasks would fetch from the params array and return the
_cbrain_output_XXXarrays for instance. - the decision about which input file's cache to clean or not would benefit from using the kind of logic we use in the special module BoutiquesInputCacheCleaner ; that module use the timestamps of the synchronization subsystem to make some decisions
- we could entirely skip cleaning any input or output that are less than 1mb; we don't really care about leaving those in the caches, in the end. The point is to provide cleanup of LARGE pieces of data that are only used once (either as inputs or as produced outputs)
| # Safety check: skip if another active task relies on this exact input | ||
| file_in_use = CbrainTask.active | ||
| .where.not(id: cbrain_task.id) | ||
| .any? { |t| t.params[:interface_userfile_ids]&.include?(userfile_id) } |
There was a problem hiding this comment.
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 .include?() would fail. Generally, when I need to write such code, I turn everything into strings. So I'd end up with something ugly like this:
.any? { |t| (t.params[:interface_userfile_ids] || []).map(&:to_s)
.include?(userfile_id.to_s)
}| next unless userfile | ||
|
|
||
| # Safety check: skip if another active task relies on this exact input | ||
| file_in_use = CbrainTask.active |
There was a problem hiding this comment.
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.
| [true, nil] | ||
| end | ||
|
|
||
| def prepare_dynamic_items |
There was a problem hiding this comment.
This is leftover from another BAC, it shouldn't be here.
| 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 |
There was a problem hiding this comment.
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 _cbrain_output_IDHERE in params, where IDHERE is the ID of the output-files object in the Boutiques descriptor for the task.
There was a problem hiding this comment.
The fact that this code is submitted and would crash (because Userfile.where(:task_id => x) is illegal) tells me you never actually ran your code, did you?
| [true, nil] | ||
| end | ||
|
|
||
| def prepare_dynamic_items |
| end # case 'status' is 'New', 'Data Ready', 'Recover*' and 'Restart*' | ||
|
|
||
|
|
||
| enqueue_post_task_cleanup_policies(task) |
There was a problem hiding this comment.
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.
|
|
||
| # 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 |
There was a problem hiding this comment.
Again, this is a bad name for that class, we are not removing outputs.
|
|
||
| # 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 |
There was a problem hiding this comment.
This is a bad name for that class, we are not removing inputs ! We are removing the cached copies of inputs.
| add_column :cbrain_tasks, :success_cleanup_policy, :string, default: 'keep_all' | ||
| add_column :cbrain_tasks, :failure_cleanup_policy, :string, default: 'keep_all' | ||
| end | ||
| end No newline at end of file |
| populate_items_from_task_custom_filter | ||
| end | ||
|
|
||
| end No newline at end of file |
Closes #1611 this implements the customizable data preservation and cleanup policies discussed, mapping the state action matrix into two intuitive dropdowns in the task control panel.
Changes
success_cleanup_policyandfailure_cleanup_policystring columns (defaulting to'keep_all'so legacy tasks do not break)._control.html.erband whitelisted the new attributes inTasksController.should_cleanup_component?toCbrainTaskto handle the matrix mapping witherase_workdir_and_outputsas the default on success.RemoveTaskInputsandRemoveTaskOutputsbackground activities both include real time checks against active tasks to safely skip erasing any shared or downstream assets.enqueue_post_task_cleanup_policieshelper hook intoBourreauWorkerto prevent making the monolithic loop any longer.