Skip to content

Commit 80b18f7

Browse files
authored
Merge pull request #2352 from broadinstitute/jb-duos-full-integration
Full integration for registering public studies in DUOS (SCP-6105, SCP-6106)
2 parents 2a70548 + 51ff7df commit 80b18f7

File tree

7 files changed

+76
-8
lines changed

7 files changed

+76
-8
lines changed

app/lib/duos_registration_service.rb

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# service containing business logic for managing Study registrations as datasets in DUOS
22
class DuosRegistrationService
3+
extend Loggable
34

45
# pointer to DUOS UI for auto-completing URLs
56
#
@@ -14,7 +15,11 @@ def self.duos_ui_url
1415
# * *returns*
1516
# - (DuosClient)
1617
def self.client
17-
@client ||= DuosClient.new
18+
duos_client = @client ||= DuosClient.new
19+
if duos_client.access_token_expired?
20+
duos_client.refresh_access_token!
21+
end
22+
duos_client
1823
end
1924

2025
# determine if study is eligible for registering as a dataset in DUOS
@@ -80,13 +85,16 @@ def self.register_study(study)
8085
dataset = client.create_dataset(study)
8186
ids = client.identifiers_from_dataset(dataset)
8287
study.update(**ids)
83-
Rails.logger.info "Registered #{study.accession} in DUOS as #{ids}"
88+
log_message "Registered #{study.accession} in DUOS as #{ids}"
8489
dataset
8590
rescue ArgumentError => e
86-
Rails.logger.error "Cannot validate #{study.accession} for DUOS: #{e.message}"
91+
log_message "Cannot validate #{study.accession} for DUOS: #{e.message}", level: :error
92+
nil
8793
rescue Faraday::Error => e
88-
Rails.logger.error "Unable to register #{study.accession} in DUOS: #{e.message} (#{e.try(:response_body)})"
94+
log_message "Unable to register #{study.accession} in DUOS: #{e.message} (#{e.try(:response_body)})",
95+
level: :error
8996
ErrorTracker.report_exception(e, client.issuer, { study: })
97+
SingleCellMailer.duos_error(study, e, 'register').deliver_now
9098
nil
9199
end
92100
end
@@ -107,11 +115,12 @@ def self.redact_study(study)
107115
study.update(duos_dataset_id: nil, duos_study_id: nil)
108116
end
109117

110-
Rails.logger.info "Redacted #{study.accession} in DUOS"
118+
log_message "Redacted #{study.accession} in DUOS"
111119
true
112120
rescue Faraday::Error => e
113-
Rails.logger.error "Unable to redact #{study.accession} in DUOS: (#{e.message}) #{e.try(:response_body)}"
121+
log_message "Unable to redact #{study.accession} in DUOS: (#{e.message}) #{e.try(:response_body)}", level: :error
114122
ErrorTracker.report_exception(e, client.issuer, { study: })
123+
SingleCellMailer.duos_error(study, e, 'redact').deliver_now
115124
false
116125
end
117126
end

app/mailers/single_cell_mailer.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,16 @@ def data_retention_policy_report
308308
format.html { render layout: 'nightly_admin_report' }
309309
end
310310
end
311+
312+
def duos_error(study, error, action)
313+
@study = study
314+
@action = action
315+
client = DuosClient.new
316+
error_content = error.try(:body) || error.try(:response_body) || error.try(:reason_phrase) || error.try(:message) || error.to_s
317+
@error_message = client.parse_response_body(error_content)
318+
mail(to: AdminConfiguration.qa_emails,
319+
subject: "[Single Cell Portal Admin Notification] DUOS #{action} error for #{@study.accession}") do |format|
320+
format.html { render layout: 'nightly_admin_report' }
321+
end
322+
end
311323
end

app/models/duos_client.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ class DuosClient
3333
}.freeze
3434

3535
# identifier to append to every description
36-
PLATFORM_ID = "(Platform: Single Cell Portal)".freeze
36+
PLATFORM_ID = '(Platform: Single Cell Portal)'.freeze
37+
38+
# content for tags to use in creating data library
39+
TAG_CONTENT = { tags: [PLATFORM_ID] }.freeze
3740

3841
# initialize new client and generate access token for auth
3942
#
@@ -342,7 +345,8 @@ def schema_from(study)
342345
species: study.species_list.join(', '),
343346
dataCustodianEmail: study.data_custodians,
344347
piName: study.data_custodians.first,
345-
consentGroups: [consent_values]
348+
consentGroups: [consent_values],
349+
data: TAG_CONTENT
346350
}.merge(ANVIL_VALUES).with_indifferent_access
347351
end
348352

app/models/ingest_job.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,11 +501,13 @@ def set_study_state_after_ingest
501501
launch_differential_expression_jobs
502502
launch_dot_plot_preprocess_job
503503
create_cell_name_indexes
504+
register_duos_study
504505
when :ingest_expression
505506
set_anndata_file_info if study_file.is_anndata?
506507
study.delay.set_gene_count
507508
launch_dot_plot_preprocess_job
508509
launch_differential_expression_jobs
510+
register_duos_study
509511
when :ingest_cluster
510512
set_cluster_point_count
511513
set_study_default_options
@@ -514,9 +516,11 @@ def set_study_state_after_ingest
514516
launch_dot_plot_preprocess_job
515517
launch_differential_expression_jobs
516518
create_cell_name_indexes
519+
register_duos_study
517520
when :ingest_subsample
518521
set_subsampling_flags
519522
create_cell_name_indexes
523+
register_duos_study
520524
when :differential_expression
521525
create_differential_expression_results
522526
when :ingest_differential_expression
@@ -841,6 +845,12 @@ def set_has_dot_plot_genes
841845
cluster_group.update(has_dot_plot_genes: true)
842846
end
843847

848+
# register eligible studies in DUOS
849+
def register_duos_study
850+
study.reload
851+
DuosRegistrationService.register_study(study) if DuosRegistrationService.study_eligible?(study)
852+
end
853+
844854
# set appropriate flags for AnnDataFileInfo entries
845855
def set_anndata_file_info
846856
study_file.build_ann_data_file_info if study_file.ann_data_file_info.nil?
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<html lang="en">
2+
<body>
3+
<p>The following error occurred when trying to <strong><%= @action %></strong> <%= @study.accession %> in DUOS:</p>
4+
<pre>
5+
<%= @error_message %>
6+
</pre>
7+
</body>
8+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class RegisterEligibleDuosStudies < Mongoid::Migration
2+
def self.up
3+
registered = []
4+
unregistered = []
5+
accessions = DuosRegistrationService.eligible_studies
6+
puts "found #{accessions.count} eligible studies for DUOS registration"
7+
accessions.each do |accession|
8+
study = Study.find_by(accession:)
9+
dataset = DuosRegistrationService.register_study(study)
10+
if dataset
11+
registered << accession
12+
else
13+
unregistered << accession
14+
end
15+
end
16+
puts "completed!"
17+
puts "registered #{registered.count} studies: #{registered.join(', ')}"
18+
puts "failed to register #{unregistered.count} studies: #{unregistered.join(', ')}"
19+
end
20+
21+
# don't reverse migration so we can re-run if necessary
22+
def self.down; end
23+
end

test/integration/external/duos_client_test.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ def skip_if_api_down
118118
participant_count = duos_data[:consentGroups].first[:numberOfParticipants]
119119
assert_equal 5, participant_count
120120
assert_equal @author.email, duos_data[:dataCustodianEmail].first
121+
assert_equal DuosClient::TAG_CONTENT.with_indifferent_access,
122+
duos_data[:data].with_indifferent_access
121123
end
122124

123125
test 'should load dataset JSON schema from DUOS' do

0 commit comments

Comments
 (0)