Skip to content

Commit

Permalink
Merge branch 'development' into asset-technology-serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
alesanchezr authored Oct 3, 2023
2 parents bcb6ad8 + f18db0d commit 365d3f4
Show file tree
Hide file tree
Showing 31 changed files with 1,955 additions and 59 deletions.
4 changes: 2 additions & 2 deletions Procfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
release: export CORALOGIX_SUBSYSTEM=release; python manage.py migrate && python manage.py create_academy_roles && python manage.py set_permissions
celeryworker: export CORALOGIX_SUBSYSTEM=celeryworker; export CELERY_WORKER_RUNNING=True; export REMAP_SIGTERM=SIGQUIT; newrelic-admin run-program bin/start-pgbouncer-stunnel celery -A breathecode.celery worker --loglevel=INFO
web: export CORALOGIX_SUBSYSTEM=web; newrelic-admin run-program bin/start-pgbouncer-stunnel gunicorn breathecode.wsgi --timeout 29 --workers 2 --max-requests 500 --max-requests-jitter 100 --worker-class gevent
celeryworker: export CORALOGIX_SUBSYSTEM=celeryworker; export CELERY_WORKER_RUNNING=True; export REMAP_SIGTERM=SIGQUIT; newrelic-admin run-program bin/start-pgbouncer-stunnel celery -A breathecode.celery worker --loglevel=INFO --concurrency 1 --prefetch-multiplier=4 --max-tasks-per-child=500
web: export CORALOGIX_SUBSYSTEM=web; newrelic-admin run-program bin/start-pgbouncer-stunnel gunicorn breathecode.wsgi --timeout 29 --workers 2 --worker-connections $WEB_WORKER_CONNECTION --max-requests-jitter 100 --worker-class gevent
1 change: 0 additions & 1 deletion breathecode/admissions/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1483,7 +1483,6 @@ def get(self, request, syllabus_id=None, syllabus_slug=None, academy_id=None):
if like is not None:
items = items.filter(Q(name__icontains=like) | Q(slug__icontains=like))


items = handler.queryset(items)
serializer = GetSyllabusSerializer(items, many=True)

Expand Down
6 changes: 5 additions & 1 deletion breathecode/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings')
app.conf.update(BROKER_URL=REDIS_URL, CELERY_RESULT_BACKEND=REDIS_URL, namespace='CELERY', broker_pool_limit=1, result_expires=10)
app.conf.update(BROKER_URL=REDIS_URL,
CELERY_RESULT_BACKEND=REDIS_URL,
namespace='CELERY',
broker_pool_limit=1,
result_expires=10)

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
from django.core.management.base import BaseCommand, CommandError
from ...models import TaskManager
from django.utils import timezone
from datetime import datetime
from datetime import timedelta
from django.utils import timezone


class Command(BaseCommand):
help = 'Delete logs and other garbage'

def handle(self, *args, **options):

date_limit = timezone.make_aware(datetime.now() - timedelta(days=2))
date_limit = timezone.now() - timedelta(days=2)

webhooks = TaskManager.objects.filter(created_at__lt=date_limit)
count = webhooks.count()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.core.management.base import BaseCommand

from breathecode.commons.tasks import mark_task_as_pending
from breathecode.commons import tasks
from ...models import TaskManager
from datetime import datetime
from datetime import timedelta
Expand All @@ -18,7 +18,7 @@ def handle(self, *args, **options):
status='PENDING').values_list('id', flat=True)

for id in ids:
mark_task_as_pending.delay(id, force=True)
tasks.mark_task_as_pending.delay(id, force=True)

if ids:
msg = self.style.SUCCESS(f"Rerunning TaskManager's {', '.join([str(id) for id in ids])}")
Expand Down
21 changes: 11 additions & 10 deletions breathecode/commons/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def mark_task_as_cancelled(task_manager_id):
logger.info(f'Running mark_task_as_cancelled for {task_manager_id}')

x = TaskManager.objects.filter(id=task_manager_id, status='PENDING').first()
x = TaskManager.objects.filter(id=task_manager_id).first()
if x is None:
logger.error(f'TaskManager {task_manager_id} not found')
return
Expand All @@ -27,7 +27,7 @@ def mark_task_as_cancelled(task_manager_id):
x.status = 'CANCELLED'
x.save()

logger.info(f'TaskManager {task_manager_id} CANCELLED')
logger.info(f'TaskManager {task_manager_id} is being marked as CANCELLED')


# do not use our own task decorator
Expand All @@ -46,24 +46,25 @@ def mark_task_as_reversed(task_manager_id, *, attempts=0, force=False):

if not force and (x.status != 'DONE' and not x.last_run < timezone.now() - timedelta(minutes=TOLERANCE)
and not x.killed and attempts < 10):
logger.warn(f'TaskManager {task_manager_id} was not killed, scheduling to run again')
logger.warn(f'TaskManager {task_manager_id} was not killed, scheduling to run it again')

x.status = 'CANCELLED'
x.save()

mark_task_as_reversed.apply_async(args=(task_manager_id, ),
kwargs={'attempts': attempts + 1},
eta=datetime.utcnow() + timedelta(seconds=30))
eta=timezone.now() + timedelta(seconds=30))
return

x.status = 'REVERSED'
x.save()

module = importlib.import_module(x.reverse_module)
function = getattr(module, x.reverse_name)
print('function', function, x.arguments)
function(*x.arguments['args'], **x.arguments['kwargs'])

logger.info(f'TaskManager {task_manager_id} REVERSED')
logger.info(f'TaskManager {task_manager_id} is being marked as REVERSED')


# do not use our own task decorator
Expand All @@ -77,13 +78,13 @@ def mark_task_as_paused(task_manager_id):
return

if x.status != 'PENDING':
logger.warn(f'TaskManager {task_manager_id} is not PENDING')
logger.warn(f'TaskManager {task_manager_id} is not running')
return

x.status = 'PAUSED'
x.save()

logger.info(f'TaskManager {task_manager_id} PAUSED')
logger.info(f'TaskManager {task_manager_id} is being marked as PAUSED')


# do not use our own task decorator
Expand All @@ -106,14 +107,14 @@ def mark_task_as_pending(task_manager_id, *, attempts=0, force=False, last_run=N

if force is False and not x.last_run < timezone.now() - timedelta(
minutes=TOLERANCE) and not x.killed and attempts < 10:
logger.warn(f'TaskManager {task_manager_id} was not killed, scheduling to run again')
logger.warn(f'TaskManager {task_manager_id} was not killed, scheduling to run it again')

mark_task_as_pending.apply_async(args=(task_manager_id, ),
kwargs={
'attempts': attempts + 1,
'last_run': last_run or x.last_run,
},
eta=datetime.utcnow() + timedelta(seconds=30))
eta=timezone.now() + timedelta(seconds=30))
return

x.status = 'PENDING'
Expand All @@ -130,4 +131,4 @@ def mark_task_as_pending(task_manager_id, *, attempts=0, force=False, last_run=N
'task_manager_id': task_manager_id,
})

logger.info(f'TaskManager {task_manager_id} is PENDING')
logger.info(f'TaskManager {task_manager_id} is being marked as PENDING')
Empty file.
54 changes: 54 additions & 0 deletions breathecode/commons/tests/admin/tests_cancel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import random
from unittest.mock import MagicMock, call
from logging import Logger
import pytest
from breathecode.commons.admin import cancel
from breathecode.commons import tasks

from breathecode.tests.mixins.breathecode_mixin.breathecode import Breathecode

param_names = 'task_module,task_name,get_call_args_list'


@pytest.fixture(autouse=True)
def setup(db, monkeypatch):
monkeypatch.setattr('breathecode.commons.tasks.mark_task_as_cancelled.delay', MagicMock())

yield


@pytest.fixture
def arrange(bc: Breathecode, fake):

def _arrange(n):
model = bc.database.create(task_manager=n)
return model, bc.database.get_model('commons.TaskManager').objects.filter()

yield _arrange


# When: 0 TaskManager's
# Then: nothing happens
def test_with_0(bc: Breathecode, arrange):
_, queryset = arrange(0)

res = cancel(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == []
assert tasks.mark_task_as_cancelled.delay.call_args_list == []


# When: 2 TaskManager's
# Then: two tasks are scheduled
def test_with_2(bc: Breathecode, arrange):

model, queryset = arrange(2)

res = cancel(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == bc.format.to_dict(model.task_manager)
assert tasks.mark_task_as_cancelled.delay.call_args_list == [call(1), call(2)]
54 changes: 54 additions & 0 deletions breathecode/commons/tests/admin/tests_force_reverse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import random
from unittest.mock import MagicMock, call
from logging import Logger
import pytest
from breathecode.commons.admin import force_reverse
from breathecode.commons import tasks

from breathecode.tests.mixins.breathecode_mixin.breathecode import Breathecode

param_names = 'task_module,task_name,get_call_args_list'


@pytest.fixture(autouse=True)
def setup(db, monkeypatch):
monkeypatch.setattr('breathecode.commons.tasks.mark_task_as_reversed.delay', MagicMock())

yield


@pytest.fixture
def arrange(bc: Breathecode, fake):

def _arrange(n):
model = bc.database.create(task_manager=n)
return model, bc.database.get_model('commons.TaskManager').objects.filter()

yield _arrange


# When: 0 TaskManager's
# Then: nothing happens
def test_with_0(bc: Breathecode, arrange):
_, queryset = arrange(0)

res = force_reverse(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == []
assert tasks.mark_task_as_reversed.delay.call_args_list == []


# When: 2 TaskManager's
# Then: two tasks are scheduled
def test_with_2(bc: Breathecode, arrange):

model, queryset = arrange(2)

res = force_reverse(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == bc.format.to_dict(model.task_manager)
assert tasks.mark_task_as_reversed.delay.call_args_list == [call(1, force=True), call(2, force=True)]
54 changes: 54 additions & 0 deletions breathecode/commons/tests/admin/tests_pause.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import random
from unittest.mock import MagicMock, call
from logging import Logger
import pytest
from breathecode.commons.admin import pause
from breathecode.commons import tasks

from breathecode.tests.mixins.breathecode_mixin.breathecode import Breathecode

param_names = 'task_module,task_name,get_call_args_list'


@pytest.fixture(autouse=True)
def setup(db, monkeypatch):
monkeypatch.setattr('breathecode.commons.tasks.mark_task_as_paused.delay', MagicMock())

yield


@pytest.fixture
def arrange(bc: Breathecode, fake):

def _arrange(n):
model = bc.database.create(task_manager=n)
return model, bc.database.get_model('commons.TaskManager').objects.filter()

yield _arrange


# When: 0 TaskManager's
# Then: nothing happens
def test_with_0(bc: Breathecode, arrange):
_, queryset = arrange(0)

res = pause(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == []
assert tasks.mark_task_as_paused.delay.call_args_list == []


# When: 2 TaskManager's
# Then: two tasks are scheduled
def test_with_2(bc: Breathecode, arrange):

model, queryset = arrange(2)

res = pause(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == bc.format.to_dict(model.task_manager)
assert tasks.mark_task_as_paused.delay.call_args_list == [call(1), call(2)]
54 changes: 54 additions & 0 deletions breathecode/commons/tests/admin/tests_resume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import random
from unittest.mock import MagicMock, call
from logging import Logger
import pytest
from breathecode.commons.admin import resume
from breathecode.commons import tasks

from breathecode.tests.mixins.breathecode_mixin.breathecode import Breathecode

param_names = 'task_module,task_name,get_call_args_list'


@pytest.fixture(autouse=True)
def setup(db, monkeypatch):
monkeypatch.setattr('breathecode.commons.tasks.mark_task_as_pending.delay', MagicMock())

yield


@pytest.fixture
def arrange(bc: Breathecode, fake):

def _arrange(n):
model = bc.database.create(task_manager=n)
return model, bc.database.get_model('commons.TaskManager').objects.filter()

yield _arrange


# When: 0 TaskManager's
# Then: nothing happens
def test_with_0(bc: Breathecode, arrange):
_, queryset = arrange(0)

res = resume(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == []
assert tasks.mark_task_as_pending.delay.call_args_list == []


# When: 2 TaskManager's
# Then: two tasks are scheduled
def test_with_2(bc: Breathecode, arrange):

model, queryset = arrange(2)

res = resume(None, None, queryset)

assert res == None

assert bc.database.list_of('commons.TaskManager') == bc.format.to_dict(model.task_manager)
assert tasks.mark_task_as_pending.delay.call_args_list == [call(1), call(2)]
Loading

0 comments on commit 365d3f4

Please sign in to comment.