Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve demo startup time #80

Merged
merged 1 commit into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ fi
HOST_PORT="${HOST_PORT:-8000}"

python manage.py migrate
if [ "$DEMO_MODE" = "TRUE" ]; then
python manage.py create_demo_data
fi
python manage.py clean_up_shared_pdfs
python manage.py clean_up

python -m gunicorn --bind 0.0.0.0:$HOST_PORT --workers 3 core.wsgi:application
1 change: 1 addition & 0 deletions pdfding/core/settings/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,5 @@

# demo mode
DEMO_MODE = False
DEMO_MAX_USERS = 10
DEMO_MODE_RESTART_INTERVAL = 60
1 change: 1 addition & 0 deletions pdfding/core/settings/prod.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,6 @@
if os.environ.get('DEMO_MODE', 'FALSE') == 'TRUE':
DEMO_MODE = True
DEMO_MODE_RESTART_INTERVAL = os.environ.get('DEMO_MODE_RESTART_INTERVAL', 60) # in minutes
DEMO_MAX_USERS = int(os.environ.get('DEMO_MAX_USERS', 500))
else:
DEMO_MODE = False
17 changes: 16 additions & 1 deletion pdfding/e2e/test_users_e2e.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from unittest.mock import Mock, patch

from allauth.socialaccount.models import SocialAccount
from django.test import override_settings
from django.urls import reverse
Expand Down Expand Up @@ -281,8 +283,21 @@ def test_default_theme(self):
expect(self.page.locator('body')).to_have_css('background-color', 'oklch(0.279 0.041 260.031)')
expect(self.page.locator('#logo_div')).to_have_css('background-color', 'rgb(71, 147, 204)')

@patch('users.views.create_demo_user')
@patch('users.views.uuid4', return_value='123456789')
@override_settings(DEMO_MODE=True)
def test_login_demo_mode(self):
def test_login_demo_mode(self, mock_uuid4, mock_create_demo_user):
email = '12345678@pdfding.com'
mock_user = Mock()
mock_user.email = email
mock_create_demo_user.return_value = mock_user

with sync_playwright() as p:
self.open(reverse('home'), p)
expect(self.page.locator("#demo_mode")).to_be_visible()

self.page.get_by_role("button", name="Create User").click()
expect(self.page.locator("#demo_user")).to_contain_text("Demo user successfully created")
expect(self.page.locator("#demo_user")).to_contain_text(
f"You can log into your temporary account with: {email} / demo"
)
Empty file removed pdfding/pdf/management/__init__.py
Empty file.
19 changes: 0 additions & 19 deletions pdfding/pdf/management/commands/clean_up_shared_pdfs.py

This file was deleted.

10 changes: 0 additions & 10 deletions pdfding/pdf/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from urllib.parse import parse_qs, urlparse
from uuid import uuid4

from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.core.files import File
from django.db.models.functions import Lower
Expand Down Expand Up @@ -296,12 +295,3 @@ def get_pdf_info_list(profile: Profile) -> list[tuple]:
pdf_info_list.append((pdf.name, pdf_size))

return pdf_info_list


def get_demo_pdf():
"""Get the pdf file used in the demo mode."""

file_path = settings.BASE_DIR / 'users' / 'management' / 'commands' / 'demo_data' / 'demo.pdf'
demo_pdf = File(file=open(file_path, 'rb'), name=file_path.name)

return demo_pdf
34 changes: 0 additions & 34 deletions pdfding/pdf/tests/test_management.py

This file was deleted.

5 changes: 0 additions & 5 deletions pdfding/pdf/tests/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,3 @@ def test_get_pdf_info_list(self):
expected_info_list = [(f'pdf_{i}', 8885) for i in range(3)]

self.assertEqual(generated_info_list, expected_info_list)

def test_get_demo_pdf(self):
demo_pdf = service.get_demo_pdf()

self.assertEqual(demo_pdf.size, 26140)
8 changes: 4 additions & 4 deletions pdfding/pdf/views/pdf_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from pdf import forms, service
from pdf.models import Pdf, Tag
from users.models import Profile
from users.service import convert_hex_to_rgb
from users.service import convert_hex_to_rgb, get_demo_pdf


class BasePdfMixin:
Expand Down Expand Up @@ -43,7 +43,7 @@ def obj_save(form: forms.AddForm | forms.AddFormNoFile, request: HttpRequest, __
pdf = form.save(commit=False)

if settings.DEMO_MODE:
pdf_file = service.get_demo_pdf()
pdf_file = get_demo_pdf()
pdf.file = pdf_file
else:
pdf_file = form.files['file']
Expand Down Expand Up @@ -95,7 +95,7 @@ def obj_save(form: forms.BulkAddForm | forms.BulkAddFormNoFile, request: HttpReq
pdf_info_list = []

if settings.DEMO_MODE:
files = [service.get_demo_pdf()]
files = [get_demo_pdf()]
else:
files = form.files.getlist('file')

Expand Down Expand Up @@ -379,7 +379,7 @@ def post(self, request: HttpRequest):
pdf = self.get_object(request, pdf_id)

if settings.DEMO_MODE:
updated_pdf = service.get_demo_pdf()
updated_pdf = get_demo_pdf()
else:
updated_pdf = request.FILES.get('updated_pdf')

Expand Down
30 changes: 22 additions & 8 deletions pdfding/templates/socialaccount/snippets/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,36 @@

{% if DEMO_MODE %}
{% with '12345'|make_list as int_list %}
<div id="demo_mode" class="pt-12 pb-6">
<div id="demo_mode" class="mt-6 pt-4 pb-6 border-t border-gray-400">
<h2>Demo Mode</h2>
<div>
<span class="text-sm [&>span]:bg-slate-300 dark:[&>span]:bg-slate-500 [&>span]:rounded-sm [&>span]:px-1">
You can log into a shared account with:
<span>user_{{ int_list|random }}@pdfding.com</span> / <span>demo</span>
</span>
</div>
<div class="pt-4">
<span class="text-sm">The demo mode has a couple of <span class="font-bold">restrictions</span>:</span>
</div>
<ul class="list-disc pl-5 pt-1 text-sm">
<li>The demo instance is reset every hour, so any changes you make will be lost. </li>
<li>The demo instance is reset every hour, so any changes you make will be lost.</li>
<li>File uploads are not allowed when adding a new PDF. Instead, a dummy PDF will be used.</li>
<li>PDFs are read-only. So any changes in the viewer's editor won't be saved.</li>
<li>Don't enter private information. Assume all data can be read by other users.</li>
</ul>
</div>
<div id="demo_user" class="pt-2" x-data="{ in_progress: false }">
<button x-show="!in_progress"
@click="in_progress = true"
hx-post="{% url 'create_demo_user' %}"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-target="#demo_user"
hx-swap="innerHTML">
Create User
</button>
<button class="-pt-4" x-show="in_progress" x-cloak type="button" disabled>
<div class="flex justify-center">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>Processing</span>
</div
</button>
</div>
{% endwith %}
{% endif %}
49 changes: 49 additions & 0 deletions pdfding/users/management/commands/clean_up.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import logging
from pathlib import Path
from shutil import copy

from django.conf import settings
from django.core.management.base import BaseCommand
from pdf.models import SharedPdf

logger = logging.getLogger('management')


class Command(BaseCommand):
help = "Clean up data on start up"

def handle(self, *args, **kwargs):
clean_up_deleted_shared_pdfs()

if settings.DEMO_MODE:
clean_demo_db()


def clean_up_deleted_shared_pdfs():
"""Delete shared PDFs with a deletion date in the past."""

logger.info('Cleaning up shared PDFs with a deletion date in the past.')

shared_pdfs = SharedPdf.objects.all()

for shared_pdf in shared_pdfs:
if shared_pdf.deleted:
shared_pdf.delete()


def clean_demo_db(
db_path: Path = settings.BASE_DIR / 'db' / 'db.sqlite3',
after_migration_db_path: Path = settings.BASE_DIR / 'db' / 'migrated.sqlite3',
):
"""Clean the database for the demo mode. In this state the db will have applied migrations but no users or pdfs."""

logger.info('Cleaning up the demo database.')

# If the after_migration_db_path is not present, then the container is started for the first time.
# This means only the migrations were applied until now, so we want preserve this state.
if not after_migration_db_path.exists():
copy(db_path, after_migration_db_path)
# otherwise replace the migrations db.
else:
db_path.unlink()
copy(after_migration_db_path, db_path)
105 changes: 0 additions & 105 deletions pdfding/users/management/commands/create_demo_data.py

This file was deleted.

Loading