Dash App In Ubuntu Production under NGINX and UWSGI no longer working

I created a Dash App that converts a YouTube video to an MP3. On my local computer, it worked perfectly fine.

Now that it’s in production, in Ubuntu (via a Digital Ocean Droplet), using NGINX and UWSGI, it no longer works. I have gone back and forth between my local computer and production with the same code - and cannot figure out the cause of the issue.

The app is located here https://gusmontano.com/youtube_to_mp3/.

Code for the app is shown further below, though, in absence of the app_layout.

I’ve checked the error NGINX logs, though can only see the following, which I don’t understand.

Is anyone able to assist? The code basically (i) Streams the YT video; (ii) extracts the audio and stores it in memory; (iii) converts it from MP4 to MP3, and stores it in memory; (iv) outputs it to the user.

I’ve also pasted my NGINX configuration further below.

Thank you

2023/01/25 01:02:41 [crit] 2226927#2226927: *2321 SSL_do_handshake() failed (SSL: error:141CF06C:SSL routines:tls_parse_ctos_key_share:bad key share) while SSL handshaking, client: XXX.XXX.XX.XXX, server: 0.0.0.0:443
2023/01/25 02:14:04 [notice] 2244296#2244296: signal process started
2023/01/25 02:14:12 [alert] 2244229#2244229: *1 open socket #3 left in connection 3
2023/01/25 02:14:12 [alert] 2244229#2244229: *3 open socket #12 left in connection 5
2023/01/25 02:14:12 [alert] 2244229#2244229: *27 open socket #14 left in connection 6
2023/01/25 02:14:12 [alert] 2244229#2244229: *28 open socket #15 left in connection 7
2023/01/25 02:14:12 [alert] 2244229#2244229: *29 open socket #16 left in connection 9
2023/01/25 02:14:12 [alert] 2244229#2244229: *30 open socket #17 left in connection 10
2023/01/25 02:14:12 [alert] 2244229#2244229: aborting
from dash.long_callback import DiskcacheLongCallbackManager
from dash import Dash, dcc, Input, Output, State
from pydub import AudioSegment
from pytube import YouTube, exceptions
from io import BytesIO
from .layout import app_layout
import diskcache

APP_NAME = 'youtube_to_mp3'
APP_STYLESHEET = "https://cdn.jsdelivr.net/npm/bootswatch@5.2.3/dist/lux/bootstrap.min.css"
cache = diskcache.Cache("./cache")
long_callback_manager = DiskcacheLongCallbackManager(cache)


def initialise(server):

    dash_app = Dash(__name__,
                    server=server,
                    url_base_pathname=f'/{APP_NAME}/',
                    external_stylesheets=[APP_STYLESHEET],
                    long_callback_manager=long_callback_manager,
                    )

    dash_app.layout = app_layout

    @dash_app.long_callback(
        Output('downloaded_file', 'data'),
        Input('button_submit', 'n_clicks'),
        State('input_youtube_link', 'value'),
        progress=[Output('status', 'children')],
        prevent_initial_call=True)
    def update_output(set_progress, n_clicks, youtube_link):
        if n_clicks > 0:
            try:
                # Get YouTube Object
                set_progress('Downloading audio...')
                yt = YouTube(youtube_link)
                # Stream audio only, and download to memory
                audio = yt.streams.filter(only_audio=True).first()
                audio_bytes = BytesIO()
                audio.stream_to_buffer(audio_bytes)
                audio_bytes.seek(0)
                # Convert audio to MP3 format
                set_progress('Converting audio to MP3 format...')
                sound = AudioSegment.from_file(file=audio_bytes).export(BytesIO(), 'mp3')
                set_progress('Done!')
                return dcc.send_bytes(sound.getvalue(), f'{yt.streams[0].title}.mp3')
            except exceptions.RegexMatchError:
                set_progress('Inappropriate URL. Check and try again.')

    return dash_app
server {
        listen 80;
        server_name gusmontano.com www.gusmontano.com;

        location / {
                include uwsgi_params;
                uwsgi_pass unix:/gusmontanocom/gusmontanocom.sock;
        }
}

Hello @GusMontano,

I don’t know if this is necessarily and issue with nginx or anything.

It seems like it is trying to use port 443, which is the SSL port for some reason.

Does this run locally?

@jinnyzor - Thank you very much for your time, and help.

Correct - it runs locally. One theory is that there is a timeout on the stream/download stage that stops the app from running

Though, we we look at my code carefully, it should provide a status update on the progress of the app.

As soon as the program is clicked I should see “Downloading Audio” appear on the app. But this does not happen. This leads me to believe that something else may be going on.

EDIT: I see something else in my logs:

2023/01/26 01:25:48 [error] 2244320#2244320: *1331 upstream timed out (110: Connection timed out) while reading upstream, client: XX.XX.XXX.XXX, server: gusmontano.com, request: "POST /youtube_to_mp3/_dash-update-component HTTP/1.1", upstream: "uwsgi://unix:/gusmontanocom/gusmontanocom.sock:", host: "gusmontano.com", referrer: "http://gusmontano.com/youtube_to_mp3/"

(110:Connection timed out). Hmm…

What happens if you update dash and use the background callback instead of longcallbacks?

try implementing your callback with background-callbacks. I had the same error, I managed to solve it with the help of background-callbacks

This definitely seems like the solution. Though, I have no knowledge of Redis.

How do I go by

(1) Installing REDIS appropriately for the Dash app
(2) Satisfying 'REDIS_URL' in os.environ:
(3) Setting the correct value for os.environ['REDIS_URL'],

Are there any Dash examples, or simple and clear documentations that I may I follow?

Thank you very much