Skip to content

Conversation

@p3rcypj
Copy link

@p3rcypj p3rcypj commented Jun 5, 2025

📌 References

📝 Implementation

The Django production environment was unable to deploy successfully on either the staging or production machines. Several issues were preventing production deployment. Some of these included:

  • Deprecated methods that are no longer available (skip_before_filterskip_before_action)
  • Unused gems unsupported by the new Ruby version (gem gsl)
  • Previously built-in Rails functionalities that have been moved to standalone gems (gem net-ftp)
  • A new mandatory storage configuration from a dependency (ActiveStorage, even if it is not used)
  • Static files not being served → Added Nginx to serve static files
  • Digest configuration was disabled in the production.rb environment
  • Missing assets from the asset pipeline (not correctly referenced in the views – digests not used consistently)
  • Missing schemas in the database (from IEDB bionotes.epitope)
  • Rails errors in the _footer.html.haml layout, causing several routes to return HTTP 500 errors

After resolving these issues, some route requests were still failing, resulting in HTTP 404 and HTTP 500 errors. This required further troubleshooting, often by "pulling the thread." Most of these issues were related to:

  • Docker network problems with the previous Docker Compose configuration → temporarily resolved with a "patch" (not an ideal solution)
  • Database checks for UniProt accession IDs (including ENSEMBL mappings – related to genomicIFrame, aka "GeneViewer")
  • SVG icons not being served correctly (missing entries in mime.types)
  • Missing redirections to BWS and LRS
  • Incorrect self-referencing of Rails web service endpoints
  • Inconsistencies in external database requests, including the use of repeated slashes (//) and the lack of HTTPS support
  • Issues with mandatory folders in the local environment

Some improvements have also been made:

  • Optimized the Dockerfile build process to reduce build times (via caching in earlier steps for expensive operations) when Rails code changes
  • Reduced build context using .dockerignore
  • Refined and reconsidered environment variables
  • Enabled dynamic requests for BWS and LRS when needed
  • Enabled the use of external BWS and LRS for local development
  • Refined Docker Compose configurations
  • Increased timeout settings for Rails web service requests in the viewer

🔥 Testing

For local deployment, neither BWS nor LRS is required anymore. Instead, requests will be redirected to https://3dbionotes.cnb.csic.es.

If redirection to local BWS or LRS is needed for development purposes, copying the Nginx service from docker-compose.staging.yml to docker-compose.development.yml and setting BWS_API_PORT and LRS_API_PORT (as referenced in the .env.sample file) will allow redirection to local services.

If only one of the two is needed, modifying ./nginx/nginx.conf will be necessary, but ./nginx/nginx.dev.conf can be used as a reference to delegate the unused service to https://3dbionotes.cnb.csic.es.

@p3rcypj p3rcypj marked this pull request as ready for review June 6, 2025 02:04
Copy link
Author

@p3rcypj p3rcypj left a comment

Choose a reason for hiding this comment

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

Some end-of-file (EOF) changes occurred because the default code formatter was not installed on the machine I was using to modify the files.

@p3rcypj
Copy link
Author

p3rcypj commented Jun 6, 2025

Docker Compose configurations and environment variables may change in the coming weeks as our new needs become clearer.

@adrianq adrianq requested a review from tokland June 19, 2025 08:08
@adrianq adrianq merged commit b303816 into development Jun 26, 2025
1 check passed
@adrianq
Copy link
Member

adrianq commented Jun 26, 2025

@tokland I merged this PR because there is an intern working on something related but when you are back please take some time to review it. @p3rcypj will create a new PR for the review if needed

Copy link

@tokland tokland left a comment

Choose a reason for hiding this comment

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

In-line comments:

iedb: onF(proteinId, proteinId => getJSON(`${bioUrl}/api/annotations/IEDB/Uniprot/${proteinId}`, increasedTimeout)),
elmdbUniprot: onF(proteinId, proteinId => getJSON(`${bioUrl}/api/annotations/elmdb/Uniprot/${proteinId}`, increasedTimeout)),
mutagenesis: onF(proteinId, proteinId => getJSON(`${bioUrl}/api/annotations/biomuta/Uniprot/${proteinId}`, increasedTimeout)),
// BIONOTES
Copy link

@tokland tokland Jun 30, 2025

Choose a reason for hiding this comment

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

Was this change about the timeout intended for this infrastructure PR? In any case, for that kind of situations where we repeatedly call a refined version of the function, we can create an in-line abstraction:

const getJSON2 = (url: string) => getJSON(url, { timeout: 100e3 });

(if you can find a better name than getJSON2...)

genomicVariantsCNCB: onF(proteinId, proteinId => getJSON(`${bioUrl}/ws/lrs/features/variants/Genomic_Variants_CNCB/${proteinId}/`)),
pdbPublications,
nmrTargets,
pdbEmdbsEmValidations,
Copy link

Choose a reason for hiding this comment

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

minor, but lately the consensus is to write nmrTargets: nmrTargets so we can easily navigate to the type OR the value.

@alignment = nil
else
url = BaseUrl+"/api/mappings/Uniprot/ENSEMBL/transcript/"+uniprot_acc
url = BaseUrl+"api/mappings/Uniprot/ENSEMBL/transcript/"+uniprot_acc
Copy link

Choose a reason for hiding this comment

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

A more resilient solution is to use a function that performs URI joining, such as join_url(BaseUrl, "/api/mappings/Uniprot/ENSEMBL/transcript", uniprot_acc).

This join_url function would be defined in a global module (which would use URI.join, for example).


if Rails.env.development?
skip_before_action :verify_authenticity_token, only: [:home]
end
Copy link

Choose a reason for hiding this comment

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

Minor, but this Rails filters have a "if" param, right? skip_before_action :verify_authenticity_token, only: [:home], if: -> { Rails.env.development? }

identifierName.strip!
redirect_to ws_path + "/viewer/#/" + identifierName
ws_path_uri = URI.parse(ws_path) # Note: not sure why rails doesn't let me define ws_path_uri outside
ws_path_uri.port = Settings.APP_EXT_PORT
Copy link

Choose a reason for hiding this comment

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

As 1) this action is performed twice, and 2) we have to inspect the code to see what's doing -> create an abstraction with a declarative name

begin
_url = URI.parse(url)
http = Net::HTTP.new(_url.host, _url.port)
http.use_ssl = (_url.scheme == "https") # Ensure HTTPS is used if needed
Copy link

Choose a reason for hiding this comment

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

[format] I think Ruby formatters prefer not to add () for this kind of expressions

File.write(LocalPath+"/"+rand+"_can_seq", uniprot_seq)
File.write(LocalPath+"/"+rand+"_trans_seq", transcript_seq)
File.write(LocalPath+rand+"_can_seq", uniprot_seq)
File.write(LocalPath+rand+"_trans_seq", transcript_seq)
Copy link

@tokland tokland Jun 30, 2025

Choose a reason for hiding this comment

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

Same idea that URIs: abstraction or direct File.join

File.write(LocalPath+rand+"_trans_seq", transcript_seq)

cmd = "echo \"\n\" | water -asequence "+LocalPath+"/"+rand+"_can_seq -bsequence "+LocalPath+"/"+rand+"_trans_seq -gapopen 50 -gapextend 0 -datafile "+IdentityMatrix+" -aformat3 markx10 -stdout -aglobal3 Y -awidth3 1000000 2> /dev/null"
cmd = "echo \"\n\" | water -asequence "+LocalPath+rand+"_can_seq -bsequence "+LocalPath+rand+"_trans_seq -gapopen 50 -gapextend 0 -datafile "+IdentityMatrix+" -aformat3 markx10 -stdout -aglobal3 Y -awidth3 1000000 2> /dev/null"
Copy link

@tokland tokland Jun 30, 2025

Choose a reason for hiding this comment

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

That code is not ours, so let's keep it as-is to minimize the diffs, but for future code like this, a wiser usage of the quote character and mult-iline joined strings are more readable. For example:

cmd = [
  'echo "\n" | water',
  "-asequence #{LocalPath}#{rand}_can_seq",
  "-bsequence #{LocalPath}#{rand}_trans_seq",
  "-gapopen 50",
  "-gapextend 0",
  "-datafile #{IdentityMatrix}",
  "-aformat3 markx10",
  "-stdout",
  "-aglobal3 Y",
  "-awidth3 1000000",
  "2> /dev/null"
].join(' ')

# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
# config.serve_static_files = true //DEPRECATED
Copy link

@tokland tokland Jun 30, 2025

Choose a reason for hiding this comment

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

If it's deprecated, we need to insert the code? if it's something we really need to document, we can write a comment as text. Commented-out code always raises questions to the reader (is this temporal? will we need to uncomment it at some point?)

# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = false
# config.assets.digest = false
Copy link

Choose a reason for hiding this comment

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

The maybe be explicit and set to true? or it's not the same?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants