iiuni / projektzapisy

System Zapisów na zajęcia w Instytucie Informatyki Uniwersytetu Wrocławskiego
https://zapisy.ii.uni.wroc.pl
31 stars 10 forks source link

IntegrityError: duplicate key value violates unique constraint "courses_courseinformation_slug_key" DETAIL: Key (slug)=(machine-learning-202223-zimowy) already exists. #1352

Open rollbar[bot] opened 2 years ago

rollbar[bot] commented 2 years ago

View details in Rollbar: https://rollbar.com/iiuni/projektzapisy/items/490/

Traceback (most recent call last):
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/schedulersync/management/commands/import_schedule.py", line 253, in handle
    self.import_from_api(dont_delete_terms_flag, write_to_slack_flag, interactive_flag)
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/schedulersync/management/commands/import_schedule.py", line 218, in import_from_api
    scheduler_mapper.map_scheduler_data(scheduler_data)
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/schedulersync/scheduler_mapper.py", line 195, in map_scheduler_data
    courses_map = self._map_courses(scheduler_data.courses)
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/schedulersync/scheduler_mapper.py", line 173, in _map_courses
    mapped_courses[course] = get_course(proposal)
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/schedulersync/scheduler_mapper.py", line 162, in get_course
    course = CourseInstance.create_proposal_instance(proposal, self.semester)
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/enrollment/courses/models/course_instance.py", line 58, in create_proposal_instance
    instance.save()
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/enrollment/courses/models/course_instance.py", line 31, in save
    super().save(*args, **kwargs)
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/enrollment/courses/models/course_information.py", line 83, in save
    super().save(*args, **kwargs)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/base.py", line 753, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/base.py", line 789, in save_base
    parent_inserted = self._save_parents(cls, using, update_fields)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/base.py", line 818, in _save_parents
    updated = self._save_table(
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/base.py", line 895, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/base.py", line 933, in _do_insert
    return manager._insert(
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1254, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1397, in execute_sql
    cursor.execute(sql, params)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
IntegrityError: duplicate key value violates unique constraint "courses_courseinformation_slug_key"
DETAIL:  Key (slug)=(machine-learning-202223-zimowy) already exists.
Traceback (most recent call last):
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
UniqueViolation: duplicate key value violates unique constraint "courses_courseinformation_slug_key"
DETAIL:  Key (slug)=(machine-learning-202223-zimowy) already exists.
Traceback (most recent call last):
  File "/home/zapisy/deploy/releases/20220905194842/zapisy/apps/schedulersync/scheduler_mapper.py", line 159, in get_course
    course = CourseInstance.objects.get(semester=self.semester, offer=proposal)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/zapisy/deploy/current/venv/lib/python3.8/site-packages/django/db/models/query.py", line 429, in get
    raise self.model.DoesNotExist(
DoesNotExist: CourseInstance matching query does not exist.
receek commented 1 year ago

Wyjątek wystąpił w wyniku próby stworzenia instancji obiektu CourseInstance dla przedmiotu Machine Learning. Treść wyjątku informuje, że został powtórzony slug w tabeli CourseInformation (CourseInstance dziedziczy po CourseInformation).

Po przejrzeniu traceback'u wyjątek wystąpił podczas próby stworzenia obiektu CourseInstance dla Machine Learning'u w tym miejscu: https://github.com/iiuni/projektzapisy/blob/master-dev/zapisy/apps/schedulersync/scheduler_mapper.py#L155-L165.

Podczas importu skrypt synchronizuje importowaną ofertę przedmiotów na nadciągający semestr z bieżącym stanem bazy danych. Nowe obiekty CourseInstance są tworzone tylko wtedy, gdy taki obiekt dla importowanego przedmiotu nie istnieje w bazie danych. To czy przedmiot na nowy semestr posiada już swoją instancję jest ustalane na podstawie dwóch parametrów, numeru semestru i propozycji przedmiotu:

                course = CourseInstance.objects.get(semester=self.semester, offer=proposal)

W przypadku Machine Learning'u w Systemie Zapisów istnieją dwie propozycje dla tego przedmiotu. Pada podejrzenie, że wyjątek wystąpił ze względu na to, że instancja CourseInstance została utworzona na podstawie jednej propozycji i kolejno nastąpiła próba importu tego samego przedmiotu z użyciem drugiej propozycji.