Como a API em lote funciona internamente?

19

Corri para um problema de tempo limite usando migrar no outro dia e comecei a me perguntar como a API do Lote funciona internamente.

Pelo que entendi, na sua forma mais simples, você passará uma matriz de valores (nids por exemplo) e uma função para operar com esses valores. A API do lote processa um número fixo desses valores com cada solicitação até que seja concluída.

Quando um lote está sendo executado, a página parece usar solicitações do Ajax para mostrar o progresso da operação do lote (% de concluídos e mensagens). Suponho que aguarde até que a solicitação termine para atualizar o andamento e inicie a próxima solicitação imediatamente depois?

Se a página com a solicitação de lote estiver fechada, o processamento do lote será interrompido? Será reiniciado quando o mesmo URL for aberto novamente? Às vezes, o módulo de migração continua, mas provavelmente está usando filas?

uwe
fonte

Respostas:

40

É assim que o lote funciona (com base no meu entendimento)

1. Inicialize

  1. Inicialize o processamento em lote. Com base na configuração dos clientes (Navegadores), se o JavaScript está ativado ou não.
  2. Clientes habilitados para JavaScript são identificados pelo conjunto de cookies 'has_js' em drupal.js. Se nenhuma página ativada para JavaScript tiver sido visitada durante a sessão atual do navegador do usuário, a versão não JavaScript será retornada.
  3. Se o Lote ativado por JavaScript usar a solicitação ajax, mantenha a conexão ativa através da solicitação.
  4. Se o JavaScript não estiver ativado, o Batch usa define uma metatag em html para fazer intervalos regulares de atualização para manter a conexão ativa através da solicitação.

(É assim que a barra de progresso é atualizada sobre o andamento da tarefa concluída.)

Processo descontínuo

  1. Para iniciar o processo, o Lote cria uma Fila e adiciona todas as operações (funções e argumentos) que você define na matriz de lotes, como

    $batch = array (
    'operations' => array(
      array('batch_example_process', array($options1, $options2)),
      array('batch_example_process', array($options3, $options4)),
      ),
    'finished' => 'batch_example_finished',
    'title' => t('Processing Example Batch'),
    'init_message' => t('Example Batch is starting.'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Example Batch has encountered an error.'),
    'file' => drupal_get_path('module', 'batch_example') . '/batch_example.inc',
    );

    Além disso, também atribui um ID de lote que é único entre os lotes.

  2. Agora, as chamadas em lote reivindicam os itens da fila um por um e executam a função definida com os argumentos definidos nele.

  3. Esta é uma parte crucial. A função (Operação) que implementa a operação em lote deve agrupar os dados e processá-los de maneira muito eficiente, tendo em mente o limite de memória do PHP, Time out . Não fazer isso terminará no seu problema.

Corri para um problema de tempo limite usando migrar no outro dia e comecei a me perguntar como a API em lote funciona internamente.

A função de lote

As funções que implementam o Lote devem executar as seguintes ações com muito cuidado,

  • Número de itens nas operações para processar como,

    if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}'));
    }
  • Limitar o número de itens a serem processados ​​em uma chamada de função, como configurar um limite,

    // For this example, we decide that we can safely process 5 nodes at a time without a timeout.
    $limit = 5;
  • Atualização no processo para pós-processamento como,

    // Update our progress information.
        $context['sandbox']['progress']++;
        $context['sandbox']['current_node'] = $node->nid;
        $context['message'] = t('Now processing %node', array('%node' => $node->title));
  • Informar o mecanismo do Lote se o Lote foi concluído ou não,

    // Inform the batch engine that we are not finished,
    // and provide an estimation of the completion level we reached.
    if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
      $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
     }

A maioria dos pontos acima é realizada pelas operações em lote do Drupal, se houver falta na função Implementing. Mas é sempre melhor definir na função de implementação

Retorno de chamada finalizado em lote

  • Esta é a última chamada de retorno chamada quando definida na matriz de lotes. Geralmente, um relatório de quanto processado etc ...

RESPOSTAS

Se a página com a solicitação de lote estiver fechada, o processamento do lote será interrompido? Será reiniciado quando o mesmo URL for aberto novamente? Às vezes, o módulo de migração continua, mas provavelmente está usando filas?

Sim, o ideal é reiniciar o lote e, como dito acima, é baseado na função que você implementa.

Para resolver seu problema de tempo limite do PHP, use o lote Drush, disponível no módulo de migração, mas primeiro desenterre as funções de lote do migrate e tente dividir seus dados de processamento.

Dinesh Kumar Sarangapani
fonte
1
Terrific walk-through. Eu também gostaria de salientar que o lote inicia o processamento durante o que, pelo menos para o usuário, parece ser a "Inicialização". tela. Ou seja, se levar 4 segundos para configurar e 10 segundos para processar o primeiro item de lote, o usuário verá o processo "Inicializando". por catorze segundos neste exemplo. Isso faz sentido porque a primeira mensagem na tela não init é "n concluída", que só funcionaria depois que algumas forem processadas. Se isso estiver errado, por favor me corrija!
precisa saber é o seguinte
Além disso, pela minha experiência. Se você sair da página, a operação em lote / parte em processo ainda consumirá recursos até que seja concluída. Ele não dispara mais o trabalho em lotes, mas conclui o atual.
Elias Lynn
10

Se a página com a solicitação de lote estiver fechada, o processamento do lote será interrompido?

Sim, será parado.

Será reiniciado quando o mesmo URL for aberto novamente? Às vezes, o módulo de migração continua, mas provavelmente está usando filas?

Como disse Dinesh, isso depende da implementação.

Você deve executar a migração usando drush, porque

Drush é executado na linha de comando e não está sujeito a nenhum limite de tempo (em particular, o max_execution_time do PHP não se aplica). Portanto, quando você inicia um processo de migração em execução via drush, ele simplesmente é iniciado e continua sendo executado até terminar.

Ao executar processos por meio de uma interface da web, aplica-se o tempo max_execution_time do PHP (normalmente 30 segundos, se não menos). Assim, para processos de longa execução, precisamos usar a API do Lote, que gerencia a divisão de um processo em várias solicitações. Portanto, um processo de migração será iniciado, executado por aproximadamente 25 segundos, e então parará e permitirá que a API do Lote emita uma nova solicitação de página, na qual o processo de migração é reiniciado, ad infinitum.

Então, entendendo isso, por que Drush é melhor?

É mais rápido

A API do Lote apresenta muita sobrecarga - desligando e reinvocando as solicitações de página, o processo de migração precisa executar todos os construtores necessários novamente, as conexões com o banco de dados restabelecidas e as consultas executadas novamente, etc. E, para uma importação parcial, é necessário escolher onde parou - se os primeiros 500 registros de origem foram importados, ele precisa encontrar o 501 ° registro. Dependendo do seu formato de origem e de como é construído, isso pode ou não ser dimensionado - se você estiver usando marcas d'água alta com uma fonte SQL, a própria consulta poderá eliminar os registros anteriores e começar exatamente de onde você parou. Caso contrário, o Migrate precisa rolar pelos dados de origem procurando o primeiro registro não importado. Com, digamos, um grande arquivo XML como sua fonte,

É mais confiável

A execução de migrações pelo navegador adiciona sua área de trabalho e sua conexão local à Internet, como pontos de falha. Uma falha na rede quando a API do Lote está passando para a solicitação da próxima página, uma falha no navegador, um fechamento acidental da guia ou janela errada podem interromper sua migração. A execução drush reduz as partes móveis - você elimina sua área de trabalho e a conexão local à Internet como fatores.

É mais útil

Se algo der errado durante a execução no Drush, se houver alguma mensagem de erro útil, você as verá. As falhas no uso da API do Lote geralmente são engolidas e tudo o que você vê é a completamente inútil "Uma solicitação HTTP AJAX foi encerrada de forma anormal. A seguir, são fornecidas informações de depuração. Caminho: / batch? Id = 901 & op = do StatusText: ResponseText: ReadyState: 4".

Você pode encontrar mais informações sobre isso aqui .

Enquanto isso, se você deseja executar o lote, mesmo que a janela do navegador esteja fechada, considere o módulo Processo em Segundo Plano . Ele tem um submódulo em lote de plano de fundo que faz o truque.

Esse módulo assume a API em lote existente e executa tarefas em lote em um processo em segundo plano. Isso significa que, se você sair da página de lote, os trabalhos continuarão e você poderá retornar ao indicador de progresso posteriormente.

Mathankumar
fonte
uau, usar drush para migrar fez uma enorme melhoria. Eu tenho que migrar para um site ativo e isso coloca muito menos carga no sistema! Obrigado!
Uwe
0

Entenda cuidadosamente a API do lote e estes módulos ajudarão você a:

1- Progerss Esta é uma tentativa de implementar uma estrutura genérica para acompanhar qualquer progresso

2- O progresso em segundo plano assume a API em lote existente e executa tarefas em lote em um processo em segundo plano

Mohammed Gomma
fonte