Destaque do estagiário: Utkarsh Jadhav

9 de setembro de 2015 | Por

Meu nome é Utkarsh Jadhav, e sou estudante de mestrado em Ciência da Computação na Northeastern University, aqui em Boston. Passei as últimas treze semanas na edX trabalhando com a equipe da plataforma. A equipe da plataforma é responsável por construir a infraestrutura para os produtos Open edX, principalmente trabalhando para tornar o código mais rápido. Neste post, gostaria de destacar um dos meus principais projetos, o Call Stack Manager. É uma ferramenta que rastreia pilhas de chamadas exclusivas de funções, métodos e classes do Django Model.

Módulo do aluno de material didático (CSM) eHistórico do Módulo do Aluno do Curso (CSMH) no código da plataforma edx são responsáveis ​​por manter o estado de usuário dos alunos que tentam resolver os problemas e suas respectivas notas. O site edx.org atingiu recentemente 5 milhões de alunos; o tamanho crescente do CSM e do CSMH está causando sérias preocupações sobre falhas de espaço e banco de dados. A quebra de áreas de código monolítico, como o LMS e o CMS na plataforma edx, é uma necessidade vital à medida que a base de código e o volume do banco de dados aumentam.

Cliente de estado do usuário edX (eUSC)

Originalmente, a estrutura do cliente de estado do usuário era a seguinte –

Estrutura anterior do User State Client mostrando a comunicação entre a plataforma edx e o banco de dados MySQL via CSM/CSMH

Estrutura anterior do User State Client mostrando a comunicação entre a plataforma edx e o banco de dados MySQL via CSM/CSMH

Toda a estrutura estava sob plataforma edx/edx. O cliente de estado do usuário estava se comunicando diretamente com as tabelas MySQL denominadas courseware_studentmodule e courseware_studentmodulehistoryatravés do DjangoORM.

Quando comecei meu estágio, a equipe já conhecia as desvantagens dessa arquitetura. Para corrigir isso, ajudei a implementar a arquitetura proposta que é mostrada na figura a seguir:

Estrutura proposta do User State Client mostrando uma camada edx-user-state-client entre a plataforma e o back-end do banco de dados

Estrutura proposta do User State Client mostrando uma camada edx-user-state-client entre a plataforma e o back-end do banco de dados

Nesta nova arquitetura, edx-usuário-estado-cliente atua como uma camada entre a plataforma edx e os back-ends do banco de dados. Há muitas vantagens de usar essa estrutura:

  1. O eUSC atuará como uma interface única em um nível abstrato através do qual todas as chamadas ao banco de dados serão feitas. Tal padrão acabará por ajudar na comunicação eficaz com o banco de dados.
  2. O eUSC também permitirá alternar facilmente entre diferentes back-ends. Essa API permitirá a escolha de back-ends, mesmo para tarefas distribuídas.

Como primeiro passo para a criação dessa estrutura, criei um repositório chamado edx/edx-usuário-estado-cliente. Este repositório contém a interface XBlockUserStateClient, que cuida de todas as chamadas feitas pelas classes de modelo do Django com o banco de dados.

Gerenciador de pilha de chamadas

O XBlockUserStateClient é responsável por fazer todas as chamadas para o banco de dados. No entanto, considerando o imenso tamanho da base de código edX, uso de extensões de terceiros (por exemplo, XBlocks) e muitas chamadas feitas ao banco de dados em vários lugares, vale a pena capturar chamadas para o banco de dados que não são feitas pela interface XBlockUserStateClient.

Para atender a essa necessidade, desenvolvi uma biblioteca chamada Gerenciador de pilha de chamadas. Esta é uma biblioteca que permite rastrear chamadas que não são feitas via interface, e estão se comunicando diretamente com o banco de dados. O Call Stack Manager registra essas chamadas no log do LMS.

A biblioteca implementa dois decoradores principais:

  1. @trackit – que rastreia a entidade decorada
  2. @não rastreie – que interrompe o rastreamento de entidades decoradas por @trackit.

A principal necessidade de desenvolver esta biblioteca era rastrear chamadas de classes Model em CSM e CSMH, principalmente Módulo Aluno e StudentModuleHistórico. A comunicação com bancos de dados no Django é feita por classes definidas pelo usuário que subclassificam o Classe 'Modelo' do Django. As classes de modelo usam o API QuerySet para criar, recuperar e atualizar bancos de dados. As chamadas feitas pela API QuerySet podem ser substituídas usando um gerenciador personalizado chamado CallStackManager – definido na biblioteca Call Stack Manager. Dessa forma, foi tratado o caso particular de rastreamento de classes Django Model que acessam diretamente o banco de dados.

Ao executar o Call Stack Manager em sua versão inicial, enfrentei os seguintes problemas:

  1. Os registros de chamadas eram feitos repetidamente, sobrecarregando o registro do LMS.
  2. Muitas ligações que já sabíamos foram gravadas desnecessariamente.
  3. Os registros de chamadas continham quadros desnecessários, tornando-os longos e difíceis de ler.

Para resolver esses problemas, apresentei um novo decorador, chamado @não rastreie, que interrompe o rastreamento para o escopo da função decorada com este decorador. Em geral, as chamadas para um método rastreado podem ser segregadas em duas categorias: aquelas que são feitas pela implementação da nova interface e aquelas que não são. Chamadas que já conhecemos e esperamos – ou seja, aquelas chamadas da nova implementação – podem ser ignoradas, pois estamos interessados ​​apenas em capturar chamadas que não conhecemos. Assim, usamos este @não rastreie decorador para ocultar quaisquer chamadas rastreadas feitas por essa implementação. Neste ponto, as únicas chamadas sendo rastreadas serão aquelas feitas fora da nova implementação.

Desta forma, chamadas esperadas e conhecidas feitas ao banco de dados (por exemplo, via interface XBlockUserStateClient) não foram registrados, dando-nos uma visão clara do que as chamadas desconhecidas estavam fazendo. Além disso, os quadros duplicados na pilha de chamadas foram filtrados usando filtros de expressão regular. Desta forma, o número de chamadas gravadas foi menor, mais preciso e mais fácil de ler.

Um exemplo de uma pilha de chamadas mencionado acima é o seguinte –

Registrando nova pilha de chamadas número 4 para:
   Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, linha 240, envolto
    retornar função(*args, **kwargs)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, linha 176, envolto
    retornar função(*args, **kwargs)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, linha 127, envolto
    return func(solicitação, *args, **kwargs)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py”, linha 1896, em rescore_problem
    instrutor_task.api.submit_rescore_problem_for_student(solicitação, module_state_key, aluno)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/api.py”, linha 110, em submit_rescore_problem_for_student
    return submit_task(request, task_type, task_class, using_key.course_key, task_input, task_key)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/api_helper.py”, linha 346, em submit_task
    task_class.apply_async(task_args, task_id=task_id)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/tasks.py”, linha 80, em rescore_problem
    retornar run_main_task(entry_id, visit_fcn, action_name)
  Arquivo “/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/tasks_helper.py”, linha 279, em run_main_task
    task_progress = task_fcn(entry_id, course_id, task_input, action_name)
  File”/edx/app/edxapp/edx-platform/lms/djangoapps/instructor_task/tasks_helper.py”, linha 345, em perform_module_state_update
    module_to_update = StudentModule.objects.filter(course_id=course_id, module_state_key__in=usage_keys)

Durante o desenvolvimento da biblioteca Call Stack Manager, tive que resolver vários problemas básicos de nível Python, como manipulação eficaz de classes Django Model, criação de classes Django Model em tempo de execução para fins de teste, encapsulamento de funções para que não perdessem sua identidade , lidando com confrontos com outros decoradores, como @contrato em PyContracts e muito mais.

Call Stack Manager como uma biblioteca geral

O principal objetivo do Call Stack Manager era rastrear chamadas de Módulo Aluno e StudentModuleHistórico. Além disso, podemos rastrear qualquer função Python em qualquer nível específico de código. O rastreamento pode ser interrompido quando necessário. Com o uso desta biblioteca, podemos descontinuar funções indesejadas de forma eficaz, rastreando chamadas desconhecidas. Será interessante buscar o desenvolvimento desta ferramenta como uma ferramenta genérica aplicável a qualquer projeto Django.

Conclusão

Eu acredito fortemente que a solução generalizada do Call Stack Manager pode ser usada como um plugin ou biblioteca padrão para o projeto Django/Python com mais adições e modificações.

Olhando para trás na minha experiência de estágio, gostei de trabalhar na base de código edX. Trabalhar em um projeto de código aberto de grande escala que tem um enorme impacto global é muito emocionante. A EdX tem uma equipe de programadores incríveis e tratou os estagiários como funcionários em tempo integral com exposição máxima em todos os níveis. Eu me encontrei trabalhando em tecnologias de ponta e participei de todos os tipos de discussões técnicas com a equipe da plataforma. Trabalhar no nível básico do python e resolver problemas incomuns e inesperados foi especialmente gratificante. Gostaria de agradecer a John Eskew, Calen Pennington, Ali Mohammad, Brian Beggs, Miki Goyal, Adam Palay e Ned Batchelder por sua ajuda e apoio contínuos. Trabalhar na edX foi uma oportunidade fascinante e desafiadora que vou guardar com carinho nos próximos anos.

Carregando

Tempo para mais? Confira os artigos abaixo.

Aprendizagem corporativa faz sua mudança para Ed Tech
Chamada de artigos rende uma colheita abundante
Open edX Call for Papers: termina em 7 de dezembro
Melhorias incrementais no Open edX
Participe da Conferência Open edX 2026!

A Conferência Open edX 2026 apresentará casos de uso inovadores para um dos melhores sistemas de gerenciamento de aprendizagem on-line de código aberto do mundo, a plataforma Open edX, e descobrirá os mais recentes avanços em design instrucional, constelação de cursos e métodos para operar e estender a plataforma Open edX , incluindo tecnologias inovadoras, como a IA generativa.