Skip to content
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

allow artifact summary update #3205

Merged
merged 1 commit into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions qiita_db/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -1131,10 +1131,12 @@ def set_html_summary(self, html_fp, support_dir=None):
the HTML file
"""
with qdb.sql_connection.TRN:
if self.html_summary_fp:
# Delete the current HTML summary
old_summs = self.html_summary_fp
to_delete_fps = []
if old_summs:
# Delete from the DB current HTML summary; below we will remove
# files, if necessary
to_delete_ids = []
to_delete_fps = []
for x in self.filepaths:
if x['fp_type'] in ('html_summary', 'html_summary_dir'):
to_delete_ids.append([x['fp_id']])
Expand All @@ -1146,17 +1148,6 @@ def set_html_summary(self, html_fp, support_dir=None):
# From the filepath table
sql = "DELETE FROM qiita.filepath WHERE filepath_id=%s"
qdb.sql_connection.TRN.add(sql, to_delete_ids, many=True)
# And from the filesystem only after the transaction is
# successfully completed (after commit)

def path_cleaner(fps):
for fp in fps:
if isfile(fp):
remove(fp)
else:
rmtree(fp)
qdb.sql_connection.TRN.add_post_commit_func(
path_cleaner, to_delete_fps)

# Add the new HTML summary
filepaths = [(html_fp, 'html_summary')]
Expand All @@ -1171,6 +1162,19 @@ def path_cleaner(fps):
qdb.sql_connection.TRN.add(sql, sql_args, many=True)
qdb.sql_connection.TRN.execute()

# to avoid deleting potentially necessary files, we are going to add
# that check after the previous transaction is commited
if to_delete_fps:
for x in self.filepaths:
if x['fp'] in to_delete_fps:
to_delete_fps.remove(x['fp'])

for fp in to_delete_fps:
if isfile(fp):
remove(fp)
else:
rmtree(fp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rmtree() can take a callback function to handle errors or ignore failures to delete. Just to confirm, is it better to just have it raise an Error here instead of using a handler or ignoring it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has been fine so far ... but if you have specific examples of what to add and why, please let me know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I just realized path_cleaner() is using the same parameters. I was thinking it might be good to avoid an Error in that part of the code, but it hasn't caused issues so far, and I'd need to look deeper into it in order to provide a specific example.


@property
def parents(self):
"""Returns the parents of the artifact
Expand Down
4 changes: 4 additions & 0 deletions qiita_db/test/test_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,10 @@ def test_html_summary_setter(self):
if x['fp_type'] == 'html_summary_dir']
self.assertEqual(summary_dir, [])

# let's check if we update, we do _not_ remove the files
a.set_html_summary(exp3)
self.assertTrue(exists(a.html_summary_fp[1]))

def test_descendants_with_jobs_one_element(self):
artifact = qdb.artifact.Artifact.create(
self.filepaths_root, 'FASTQ', prep_template=self.prep_template)
Expand Down
6 changes: 4 additions & 2 deletions qiita_pet/handlers/artifact_handlers/base_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def artifact_summary_get_request(user, artifact_id):
'errored_summary_jobs': errored_summary_jobs}


def artifact_summary_post_request(user, artifact_id):
def artifact_summary_post_request(user, artifact_id, force_creation=False):
"""Launches the HTML summary generation and returns the job information

Parameters
Expand All @@ -251,6 +251,8 @@ def artifact_summary_post_request(user, artifact_id):
The user making the request
artifact_id : int or str
The artifact id
force_creation : bool
If all jobs should be ignored and it should force creation

Returns
-------
Expand All @@ -267,7 +269,7 @@ def artifact_summary_post_request(user, artifact_id):
command = Command.get_html_generator(artifact.artifact_type)
jobs = artifact.jobs(cmd=command)
jobs = [j for j in jobs if j.status in ['queued', 'running', 'success']]
if jobs:
if not force_creation and jobs:
# The HTML summary is either being generated or already generated.
# Return the information of that job so we only generate the HTML
# once - Magic number 0 -> we are ensuring that there is only one
Expand Down