-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: upstream downstream link model
test: recreate_upstream_links management command test: upstream - downstream link tasks chore: fix lint issues refactor: fix import issues temp: point openedx-learning to dev branch refactor: check for upstream_version test: fix failing tests feat: create upstream links after course import refactor: rename learning classes refactor: apply review suggestions refactor: save failed status of course links docs: update docs feat: move link models from openedx-learning chore: organize imports chore: fix lint issues chore: fix dep chore: fix migrations feat: delete links for child block on delete chore: remove unused signal feat: use openedx event to create links on import temp: point openedx-events to dev branch test: fix modulestore tests test: fix weird failure in CI only refactor: update post course import signal name chore: update openedx-events dep
- Loading branch information
1 parent
3003984
commit 8e4a8be
Showing
17 changed files
with
940 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
cms/djangoapps/contentstore/management/commands/recreate_upstream_links.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
""" | ||
Management command to recreate upstream-dowstream links in PublishableEntityLink for course(s). | ||
This command can be run for all the courses or for given list of courses. | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
import logging | ||
from datetime import datetime, timezone | ||
|
||
from django.core.management.base import BaseCommand, CommandError | ||
from django.utils.translation import gettext as _ | ||
from opaque_keys import InvalidKeyError | ||
from opaque_keys.edx.keys import CourseKey | ||
|
||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview | ||
|
||
from ...tasks import create_or_update_upstream_links | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class Command(BaseCommand): | ||
""" | ||
Recreate links for course(s) in PublishableEntityLink table. | ||
Examples: | ||
# Recreate upstream links for two courses. | ||
$ ./manage.py cms recreate_upstream_links --course course-v1:edX+DemoX.1+2014 \ | ||
--course course-v1:edX+DemoX.2+2015 | ||
# Force recreate upstream links for one or more courses including processed ones. | ||
$ ./manage.py cms recreate_upstream_links --course course-v1:edX+DemoX.1+2014 \ | ||
--course course-v1:edX+DemoX.2+2015 --force | ||
# Recreate upstream links for all courses. | ||
$ ./manage.py cms recreate_upstream_links --all | ||
# Force recreate links for all courses including completely processed ones. | ||
$ ./manage.py cms recreate_upstream_links --all --force | ||
# Delete all links and force recreate links for all courses | ||
$ ./manage.py cms recreate_upstream_links --all --force --replace | ||
""" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument( | ||
'--course', | ||
metavar=_('COURSE_KEY'), | ||
action='append', | ||
help=_('Recreate links for xblocks under given course keys. For eg. course-v1:edX+DemoX.1+2014'), | ||
default=[], | ||
) | ||
parser.add_argument( | ||
'--all', | ||
action='store_true', | ||
help=_( | ||
'Recreate links for xblocks under all courses. NOTE: this can take long time depending' | ||
' on number of course and xblocks' | ||
), | ||
) | ||
parser.add_argument( | ||
'--force', | ||
action='store_true', | ||
help=_('Recreate links even for completely processed courses.'), | ||
) | ||
parser.add_argument( | ||
'--replace', | ||
action='store_true', | ||
help=_('Delete all and create links for given course(s).'), | ||
) | ||
|
||
def handle(self, *args, **options): | ||
""" | ||
Handle command | ||
""" | ||
courses = options['course'] | ||
should_process_all = options['all'] | ||
force = options['force'] | ||
replace = options['replace'] | ||
time_now = datetime.now(tz=timezone.utc) | ||
if not courses and not should_process_all: | ||
raise CommandError('Either --course or --all argument should be provided.') | ||
|
||
if should_process_all and courses: | ||
raise CommandError('Only one of --course or --all argument should be provided.') | ||
|
||
if should_process_all: | ||
courses = CourseOverview.get_all_course_keys() | ||
for course in courses: | ||
log.info(f"Start processing upstream->dowstream links in course: {course}") | ||
try: | ||
CourseKey.from_string(str(course)) | ||
except InvalidKeyError: | ||
log.error(f"Invalid course key: {course}, skipping..") | ||
continue | ||
create_or_update_upstream_links.delay(str(course), force=force, replace=replace, created=time_now) |
93 changes: 93 additions & 0 deletions
93
...angoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# Generated by Django 4.2.18 on 2025-02-05 05:33 | ||
|
||
import uuid | ||
|
||
import django.db.models.deletion | ||
import opaque_keys.edx.django.models | ||
import openedx_learning.lib.fields | ||
import openedx_learning.lib.validators | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
dependencies = [ | ||
('oel_publishing', '0002_alter_learningpackage_key_and_more'), | ||
('contentstore', '0008_cleanstalecertificateavailabilitydatesconfig'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='LearningContextLinksStatus', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
( | ||
'context_key', | ||
opaque_keys.edx.django.models.CourseKeyField( | ||
help_text='Linking status for course context key', max_length=255, unique=True | ||
), | ||
), | ||
( | ||
'status', | ||
models.CharField( | ||
choices=[ | ||
('pending', 'Pending'), | ||
('processing', 'Processing'), | ||
('failed', 'Failed'), | ||
('completed', 'Completed'), | ||
], | ||
help_text='Status of links in given learning context/course.', | ||
max_length=20, | ||
), | ||
), | ||
('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), | ||
('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), | ||
], | ||
options={ | ||
'verbose_name': 'Learning Context Links status', | ||
'verbose_name_plural': 'Learning Context Links status', | ||
}, | ||
), | ||
migrations.CreateModel( | ||
name='PublishableEntityLink', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), | ||
( | ||
'upstream_usage_key', | ||
opaque_keys.edx.django.models.UsageKeyField( | ||
help_text='Upstream block usage key, this value cannot be null and useful to track upstream library blocks that do not exist yet', | ||
max_length=255, | ||
), | ||
), | ||
( | ||
'upstream_context_key', | ||
openedx_learning.lib.fields.MultiCollationCharField( | ||
db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, | ||
db_index=True, | ||
help_text='Upstream context key i.e., learning_package/library key', | ||
max_length=500, | ||
), | ||
), | ||
('downstream_usage_key', opaque_keys.edx.django.models.UsageKeyField(max_length=255, unique=True)), | ||
('downstream_context_key', opaque_keys.edx.django.models.CourseKeyField(db_index=True, max_length=255)), | ||
('version_synced', models.IntegerField()), | ||
('version_declined', models.IntegerField(blank=True, null=True)), | ||
('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), | ||
('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), | ||
( | ||
'upstream_block', | ||
models.ForeignKey( | ||
blank=True, | ||
null=True, | ||
on_delete=django.db.models.deletion.SET_NULL, | ||
related_name='links', | ||
to='oel_publishing.publishableentity', | ||
), | ||
), | ||
], | ||
options={ | ||
'verbose_name': 'Publishable Entity Link', | ||
'verbose_name_plural': 'Publishable Entity Links', | ||
}, | ||
), | ||
] |
Oops, something went wrong.