I have a Mojolicious App behind a reverse proxy. The Mojo App uses Promises, and in some cases, the synchronous response is returned after 2 minutes, by which time, the reverse proxy times out.
How can I best render the response? (making my subroutine respond sooner, unfortunately, is not an option)
I demonstrate this behavior using docker
below with a reverse proxy that times out after 5 seconds, and a mojo app that responds after 10 seconds:
Dockerfile
FROM docker.io/library/perl:5.36
# Install Apache2
RUN apt-get update && apt-get install -y --no-install-recommends apache2
# Install Mojolicious
RUN cpanm Mojolicious
# Install Apache mod_proxy and configure Apache2 as a reverse proxy to mojo app with 5s timeout
RUN a2enmod proxy_http \
&& perl -i.bak -pe 's#</VirtualHost>#\tProxyPass /mojo http://localhost:3000/ keepalive=On timeout=5\n</VirtualHost>#' /etc/apache2/sites-enabled/000-default.conf
# Generate a mojo app and simulate a timer
RUN mojo generate app \
&& perl -i.bak -pe 's/^.*$/ sleep(10);/ if $. == 6' /my_app/lib/MyApp/Controller/Example.pm
# Expose Apache2 and Mojo ports
EXPOSE 80 3000
# Run Apache 2 in the background and Morbo in the foreground
CMD ["/bin/bash", "-c", "apache2ctl start; /my_app/script/my_app prefork"]
docker build -t myapp .
docker run --rm --name myapp -p 8080:80 -p 3000:3000 myapp
http://localhost:8080/mojo
I ended up going with an asynchronous approach using Minion as a queue. A full working example of a LinkCheck
application is provided at:
https://github.com/mojolicious/minion/tree/main/examples/linkcheck
The example requires you either:
docker
:docker run --rm --name postgres -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 postgres:15
OR
2. Replace one line during startup to use SQLite instead of Postgres. (requires Minion::Backend::SQLite
plugin )
$self->plugin(Minion => {SQLite=>'sqlite:minion.db'});
In either cases, you must run a separate a background worker process to handle the job queue, for example:
perl script/linkcheck minion worker