Стажер у центрі уваги: ​​Уткарш Джадхав

9 вересня 2015 | за

Мене звуть Уткарш Джадхав, я студент магістра комп’ютерних наук у Північно-східному університеті тут, у Бостоні. Останні тринадцять тижнів я провів в edX, працюючи з командою Platform. Команда Platform відповідає за розбудову інфраструктури для продуктів Open edX, зокрема над тим, щоб код працював швидше. У цій публікації я хотів би висвітлити один із моїх головних проектів — Call Stack Manager. Це інструмент, який відстежує унікальні стеки викликів функцій, методів і класів моделі Django.

Студентський модуль (CSM) та Історія студентського модуля Courseware (CSMH) у коді платформи edx відповідають за підтримку стану користувача студентів, які намагаються розв’язати задачі, та їхні відповідні оцінки. Веб-сайт edx.org нещодавно досяг 5 мільйонів учнів; зростаючий розмір CSM і CSMH викликає серйозні занепокоєння щодо виходу з ладу простору та бази даних. Розбиття монолітних областей коду, таких як LMS і CMS, на edx-платформі є життєво важливою потребою, оскільки база коду та обсяг бази даних зростає.

Клієнт стану користувача edX (eUSC)

Спочатку структура клієнта стану користувача була наступною –

Попередня структура User State Client показує зв’язок між edx-платформою та базою даних MySQL через CSM/CSMH

Попередня структура User State Client показує зв’язок між edx-платформою та базою даних MySQL через CSM/CSMH

Вся конструкція була під edx/edx-платформа. Клієнт стану користувача безпосередньо спілкувався з названими таблицями MySQL courseware_studentmodule та courseware_studentmodulehistoryчерез DjangoORM.

Коли я починав стажування, команда вже знала про мінуси цієї архітектури. Щоб виправити це, я допоміг реалізувати запропоновану архітектуру, яка показана на наступному малюнку:

Запропонована структура User State Client, яка показує рівень edx-user-state-client між платформою та серверною частиною бази даних

Запропонована структура User State Client, яка показує рівень edx-user-state-client між платформою та серверною частиною бази даних

У цій новій архітектурі, edx-користувач-стан-клієнт діє як прошарок між edx-платформою та серверними частинами бази даних. Переваг використання такої конструкції багато:

  1. eUSC діятиме як єдиний інтерфейс на абстрактному рівні, через який здійснюватимуться всі звернення до бази даних. Такий шаблон згодом допоможе в ефективній комунікації з базою даних.
  2. eUSC також дозволить легко перемикатися між різними серверними програмами. Цей API дозволить вибирати серверні частини навіть для розподілених завдань.

Як перший крок до створення цієї структури я створив репозиторій під назвою edx/edx-user-state-client. Цей репозиторій містить інтерфейс XBlockUserStateClient, який піклується про всі виклики, зроблені класами моделі Django з базою даних.

Виклик менеджера стека

Команда XBlockUserStateClient відповідає за здійснення всіх звернень до бази даних. Однак, враховуючи величезний розмір кодової бази edX, використання сторонніх розширень (наприклад, XBlocks) і багато звернень до бази даних у різних місцях, справді варто відловлювати виклики до бази даних, які не здійснюються через інтерфейс XBlockUserStateClient.

Щоб задовольнити цю потребу, я розробив бібліотеку під назвою Виклик менеджера стека. Це бібліотека, яка дозволяє нам відстежувати дзвінки, які не здійснюються через інтерфейс, а безпосередньо спілкуються з базою даних. Call Stack Manager реєструє такі виклики в журналі LMS.

Бібліотека реалізує два основних декоратора:

  1. @trackit – який відстежує декоровану сутність
  2. @donottrack – який зупиняє відстеження сутностей, декорованих @trackit.

Основною потребою в розробці цієї бібліотеки було відстеження викликів класів моделі в CSM і CSMH, перш за все Студентський модуль та StudentModuleHistory. Зв’язок із базами даних у Django здійснюється за допомогою визначених користувачем класів, які створюють підкласи Клас «Модель» Django. Модельні класи використовують API QuerySet для створення, отримання та оновлення баз даних. Виклики, здійснені QuerySet API, можна перевизначати за допомогою спеціального менеджера під назвою CallStackManager – визначено в бібліотеці Call Stack Manager. Таким чином було розглянуто окремий випадок відстеження класів моделі Django, які мають прямий доступ до бази даних.

Під час запуску Call Stack Manager у початковій версії я зіткнувся з такими проблемами:

  1. Журнали викликів створювалися неодноразово, захаращуючи журнал LMS.
  2. Без потреби було записано багато дзвінків, про які ми вже знали.
  3. У журналах викликів містилися непотрібні кадри, через що їх було довго та важко читати.

Щоб вирішити ці проблеми, я представив новий декоратор під назвою @donottrack, який зупиняє відстеження для області функції, оформленої цим декоратором. Загалом, виклики відстежуваного методу можна розділити на дві категорії: ті, які здійснюються новою реалізацією інтерфейсу, і ті, що ні. Виклики, які ми вже знаємо та очікуємо, тобто виклики з нової реалізації, можна ігнорувати, оскільки ми зацікавлені лише в тому, щоб перехопити виклики, про які ми не знаємо. Таким чином, ми використовуємо це @donottrack декоратор, щоб приховати будь-які відстежувані виклики, зроблені цією реалізацією. На даний момент відстежуватимуться лише виклики, зроблені поза новою реалізацією.

Таким чином, очікувані та відомі звернення до бази даних (наприклад, через інтерфейс XBlockUserStateClient) не реєструвалися, що дає нам чітке уявлення про те, що робили невідомі виклики. Крім того, повторювані кадри в стеку викликів були відфільтровані за допомогою фільтрів регулярних виразів. Таким чином кількість зареєстрованих дзвінків була меншою, точнішою та легшою для читання.

Приклад стеку викликів, згаданий вище, такий:

Реєстрація нового стеку викликів номер 4 для:
   Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, рядок 240, в упаковці
    return func(*args, **kwargs)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, рядок 176, в упаковці
    return func(*args, **kwargs)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, рядок 127, в упаковці
    return func(request, *args, **kwargs)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, рядок 1896, у rescore_problem
    instructor_task.api.submit_rescore_problem_for_student(request, module_state_key, student)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/api.py”, рядок 110, у submit_rescore_problem_for_student
    return submit_task(request, task_type, task_class, usage_key.course_key, task_input, task_key)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/api_helper.py”, рядок 346, у submit_task
    task_class.apply_async(task_args, task_id=task_id)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/tasks.py”, рядок 80, у rescore_problem
    повернути run_main_task(entry_id, visit_fcn, action_name)
  Файл “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/tasks_helper.py”, рядок 279, у run_main_task
    task_progress = task_fcn(entry_id, course_id, task_input, action_name)
  Файл”/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/tasks_helper.py”, рядок 345, у perform_module_state_update
    modules_to_update = StudentModule.objects.filter(course_id=course_id, module_state_key__in=usage_keys)

Під час розробки бібліотеки Call Stack Manager мені довелося вирішувати численні базові проблеми рівня Python, такі як ефективна обробка класів моделі Django, створення класів моделі Django під час виконання з метою тестування, упаковка функцій, щоб вони не втратили свою ідентичність. , вирішення конфліктів з іншими декораторами, такими як @контракт у PyContracts та багато іншого.

Виклик Stack Manager як загальної бібліотеки

Основною метою диспетчера стека викликів було відстеження викликів Студентський модуль та StudentModuleHistory. Крім того, ми можемо відстежувати будь-яку функцію Python на будь-якому конкретному рівні коду. За потреби відстеження можна призупинити. Використовуючи цю бібліотеку, ми можемо ефективно відмовитися від небажаних функцій шляхом відстеження невідомих викликів. Буде цікаво продовжити розробку цього інструменту як загального інструменту, застосовного до будь-якого проекту Django.

Висновок

Я твердо переконаний, що узагальнене рішення Call Stack Manager можна використовувати як плагін або стандартну бібліотеку для проекту Django/Python з подальшими доповненнями та модифікаціями.

Озираючись на свій досвід стажування, мені сподобалося працювати над кодовою базою edX. Працювати над таким масштабним проектом з відкритим кодом, який має величезний глобальний вплив, дуже цікаво. EdX має команду чудових кодерів, і ставлення до стажерів як до співробітників на повний робочий день з максимальним впливом на кожному рівні. Я працював над передовими технологіями та брав участь у всіх видах технічних обговорень із командою Platform. Робота на базовому рівні Python і вирішення незвичних і неочікуваних проблем була особливо корисною. Я хотів би подякувати Джону Ескью, Калену Пеннінгтону, Алі Мохаммаду, Браяну Беггсу, Мікі Гойялу, Адаму Палею та Неду Батчелдеру за їхню постійну допомогу та підтримку. Робота в edX була захоплюючою та складною можливістю, якою я буду берегти протягом багатьох років.

Loading

Час для більшого? Перегляньте статті нижче.

Корпоративне навчання переходить до Ed Tech
Виклик документів дає чудовий урожай
Конкурс Open edX для доповідей: закінчується 7 грудня
Поступові вдосконалення Open edX
Приєднуйтесь до конференції Open edX 2026!

На конференції Open edX 2026 року будуть представлені інноваційні сценарії використання однієї з найкращих у світі систем керування онлайн-навчанням з відкритим кодом, платформи Open edX, а також відкриються останні досягнення в дизайні навчання, групі курсів і методах роботи та розширення платформи Open edX. , включаючи проривні технології, такі як генеративний ШІ.