feat: Display loading message in browser when Appsmith is starting (#22215)
## Description Added Appsmith Initializing and Starting pages to inform the users that Appsmith is starting up and they will need to wait for a few minutes before their Appsmith deployment is up and running, instead of displaying the 503 error like it earlier. ## Type of change - New feature (non-breaking change which adds functionality) # Media Initialization page  Starting page  [Demo Video](https://drive.google.com/file/d/1sjvfbtbWHRqVfg0Vvf2JM6W3y61-KrWm/view?usp=share_link) ## How Has This Been Tested? - Manual --------- Co-authored-by: Shrikant Sharat Kandula <shrikant@appsmith.com> Co-authored-by: Arpit Mohan <mohanarpit@users.noreply.github.com>
This commit is contained in:
parent
2729bbff28
commit
f1bf7b17dc
|
|
@ -71,6 +71,8 @@ COPY ./deploy/docker/templates/nginx/* \
|
||||||
./deploy/docker/templates/docker.env.sh \
|
./deploy/docker/templates/docker.env.sh \
|
||||||
./deploy/docker/templates/mockdb_postgres.sql \
|
./deploy/docker/templates/mockdb_postgres.sql \
|
||||||
./deploy/docker/templates/users_postgres.sql \
|
./deploy/docker/templates/users_postgres.sql \
|
||||||
|
./deploy/docker/templates/appsmith_starting.html \
|
||||||
|
./deploy/docker/templates/appsmith_initializing.html \
|
||||||
templates/
|
templates/
|
||||||
|
|
||||||
# Add bootstrapfile
|
# Add bootstrapfile
|
||||||
|
|
|
||||||
|
|
@ -271,6 +271,9 @@ configure_supervisord() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp -f "$SUPERVISORD_CONF_PATH/application_process/"*.conf /etc/supervisor/conf.d
|
cp -f "$SUPERVISORD_CONF_PATH/application_process/"*.conf /etc/supervisor/conf.d
|
||||||
|
|
||||||
|
# Copy Supervisor Listiner confs to conf.d
|
||||||
|
cp -f "$SUPERVISORD_CONF_PATH/event_listeners/"*.conf /etc/supervisor/conf.d
|
||||||
|
|
||||||
# Disable services based on configuration
|
# Disable services based on configuration
|
||||||
if [[ -z "${DYNO}" ]]; then
|
if [[ -z "${DYNO}" ]]; then
|
||||||
|
|
@ -377,7 +380,20 @@ runEmbeddedPostgres=1
|
||||||
init_postgres || runEmbeddedPostgres=0
|
init_postgres || runEmbeddedPostgres=0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_loading_pages(){
|
||||||
|
local starting_page="/opt/appsmith/templates/appsmith_starting.html"
|
||||||
|
local initializing_page="/opt/appsmith/templates/appsmith_initializing.html"
|
||||||
|
local editor_load_page="/opt/appsmith/editor/loading.html"
|
||||||
|
# Update default nginx page for initializing page
|
||||||
|
cp "$initializing_page" /var/www/html/index.nginx-debian.html
|
||||||
|
# Start nginx page to display the Appsmith is Initializing page
|
||||||
|
nginx
|
||||||
|
# Update editor nginx page for starting page
|
||||||
|
cp "$starting_page" "$editor_load_page"
|
||||||
|
}
|
||||||
|
|
||||||
# Main Section
|
# Main Section
|
||||||
|
init_loading_pages
|
||||||
init_env_file
|
init_env_file
|
||||||
setup_proxy_variables
|
setup_proxy_variables
|
||||||
unset_unused_variables
|
unset_unused_variables
|
||||||
|
|
@ -413,7 +429,10 @@ fi
|
||||||
mkdir -p /appsmith-stacks/data/{backup,restore}
|
mkdir -p /appsmith-stacks/data/{backup,restore}
|
||||||
|
|
||||||
# Create sub-directory to store services log in the container mounting folder
|
# Create sub-directory to store services log in the container mounting folder
|
||||||
mkdir -p /appsmith-stacks/logs/{backend,cron,editor,rts,mongodb,redis,postgres}
|
mkdir -p /appsmith-stacks/logs/{backend,cron,editor,rts,mongodb,redis,postgres,appsmithctl}
|
||||||
|
|
||||||
|
# Stop nginx gracefully
|
||||||
|
nginx -s quit
|
||||||
|
|
||||||
# Handle CMD command
|
# Handle CMD command
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|
|
||||||
74
deploy/docker/scripts/supervisor_event_listener.py
Normal file
74
deploy/docker/scripts/supervisor_event_listener.py
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import time
|
||||||
|
|
||||||
|
LOADING_TEMPLATE_PAGE = r'/opt/appsmith/templates/appsmith_starting.html'
|
||||||
|
LOADING_PAGE_EDITOR = r'/opt/appsmith/editor/loading.html'
|
||||||
|
BACKEND_HEALTH_ENDPOINT = "http://localhost/api/v1/health"
|
||||||
|
|
||||||
|
def write_stdout(s):
|
||||||
|
# only eventlistener protocol messages may be sent to stdout
|
||||||
|
sys.stdout.write(s)
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
def write_stderr(s):
|
||||||
|
sys.stderr.write(s)
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
def wait_until_backend_healthy():
|
||||||
|
sleep_sec = 3
|
||||||
|
timeout_sec = 120
|
||||||
|
for _ in range(timeout_sec//sleep_sec):
|
||||||
|
if requests.get(BACKEND_HEALTH_ENDPOINT).ok:
|
||||||
|
write_stderr('\nBackend is healthy\n')
|
||||||
|
break
|
||||||
|
time.sleep(sleep_sec)
|
||||||
|
|
||||||
|
else:
|
||||||
|
write_stderr('\nBackend health check timed out\n')
|
||||||
|
|
||||||
|
remove_loading_page()
|
||||||
|
|
||||||
|
def remove_loading_page():
|
||||||
|
if os.path.exists(LOADING_PAGE_EDITOR):
|
||||||
|
os.remove(LOADING_PAGE_EDITOR)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
while True:
|
||||||
|
# transition from ACKNOWLEDGED to READY
|
||||||
|
write_stdout('READY\n')
|
||||||
|
|
||||||
|
# read header line and print it to stderr
|
||||||
|
line = sys.stdin.readline()
|
||||||
|
write_stderr(line)
|
||||||
|
|
||||||
|
# read event payload and print it to stderr
|
||||||
|
headers = dict(x.split(':', 1) for x in line.split())
|
||||||
|
data = sys.stdin.read(int(headers['len']))
|
||||||
|
|
||||||
|
if 'PROCESS_STATE_STARTING' in line:
|
||||||
|
data_params = dict([ x.split(':') for x in data.split()])
|
||||||
|
if data_params['groupname'] == 'backend':
|
||||||
|
write_stderr('\nBackend State: STARTING\n')
|
||||||
|
shutil.copyfile(LOADING_TEMPLATE_PAGE, LOADING_PAGE_EDITOR)
|
||||||
|
|
||||||
|
elif 'PROCESS_STATE_RUNNING' in line:
|
||||||
|
data_params = dict([ x.split(':') for x in data.split()])
|
||||||
|
if data_params['groupname'] == 'backend':
|
||||||
|
write_stderr('\nBackend State: RUNNING\n')
|
||||||
|
wait_until_backend_healthy()
|
||||||
|
write_stderr(data)
|
||||||
|
|
||||||
|
elif 'PROCESS_STATE_FATAL' in line:
|
||||||
|
data_params = dict([ x.split(':') for x in data.split()])
|
||||||
|
if data_params['groupname'] == 'backend':
|
||||||
|
write_stderr('\nBackend State: FATAL\n')
|
||||||
|
remove_loading_page()
|
||||||
|
|
||||||
|
# transition from READY to ACKNOWLEDGED
|
||||||
|
write_stdout('RESULT 2\nOK')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
87
deploy/docker/templates/appsmith_initializing.html
Normal file
87
deploy/docker/templates/appsmith_initializing.html
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" http-equiv="refresh" content="5"/>
|
||||||
|
<link
|
||||||
|
rel="shortcut icon"
|
||||||
|
href="https://assets.appsmith.com/appsmith-favicon-orange.ico"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
|
/>
|
||||||
|
<title>Appsmith</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<p class="bold-text">
|
||||||
|
Please wait
|
||||||
|
</p>
|
||||||
|
<p>Appsmith is initializing. This might take a few minutes.</p>
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
color: #182026;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||||
|
Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 90%;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 5%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.bold-text {
|
||||||
|
font-family: system-ui;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 24px;
|
||||||
|
margin: 24px 0 0;
|
||||||
|
}
|
||||||
|
.body-text {
|
||||||
|
margin: 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Safari */
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
border: 4px solid #f3f3f3;
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top: 4px solid #939090;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
-webkit-animation: spin 1s linear infinite; /* Safari */
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
87
deploy/docker/templates/appsmith_starting.html
Normal file
87
deploy/docker/templates/appsmith_starting.html
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" http-equiv="refresh" content="3"/>
|
||||||
|
<link
|
||||||
|
rel="shortcut icon"
|
||||||
|
href="https://assets.appsmith.com/appsmith-favicon-orange.ico"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
|
/>
|
||||||
|
<title>Appsmith</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<p class="bold-text">
|
||||||
|
Appsmith is starting.
|
||||||
|
</p>
|
||||||
|
<p>Please wait until Appsmith is ready. This process usually takes a minute. </p>
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
color: #182026;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||||
|
Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 90%;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 5%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.bold-text {
|
||||||
|
font-family: system-ui;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 24px;
|
||||||
|
margin: 24px 0 0;
|
||||||
|
}
|
||||||
|
.body-text {
|
||||||
|
margin: 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Safari */
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
border: 4px solid #f3f3f3;
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top: 4px solid #939090;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
-webkit-animation: spin 1s linear infinite; /* Safari */
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -70,7 +70,7 @@ server {
|
||||||
proxy_set_header X-Forwarded-Host \$origin_host;
|
proxy_set_header X-Forwarded-Host \$origin_host;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files \$uri /index.html =404;
|
try_files /loading.html \$uri /index.html =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^/static/(js|css|media)\b {
|
location ~ ^/static/(js|css|media)\b {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ server {
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files \$uri /index.html =404;
|
try_files /loading.html \$uri /index.html =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^/static/(js|css|media)\b {
|
location ~ ^/static/(js|css|media)\b {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ command=/opt/appsmith/run-with-env.sh /opt/appsmith/run-java.sh
|
||||||
priority=20
|
priority=20
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
startsecs=10
|
startsecs=20
|
||||||
startretries=3
|
startretries=3
|
||||||
stdout_logfile=/appsmith-stacks/logs/%(program_name)s/%(program_name)s-%(ENV_HOSTNAME)s.log
|
stdout_logfile=/appsmith-stacks/logs/%(program_name)s/%(program_name)s-%(ENV_HOSTNAME)s.log
|
||||||
redirect_stderr=true
|
redirect_stderr=true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
[eventlistener:event_listener]
|
||||||
|
command=python3 /opt/appsmith/supervisor_event_listener.py
|
||||||
|
events=PROCESS_STATE
|
||||||
|
stderr_logfile=/appsmith-stacks/logs/appsmithctl/eventlistener.log
|
||||||
|
priority=1
|
||||||
Loading…
Reference in New Issue
Block a user