Мой метод получения информации о тегах Git в Node JS медленный, как я могу ускорить его? - PullRequest
0 голосов
/ 04 января 2019

Я создаю сценарий Node JS, который должен получить все теги Git из репозитория, а также сообщение и дату создания тега, а затем сохранить их как записи в файле JSON. Например:

[{
  "tag": "v1.1.0",
  "message": "Add navigation",
  "date": "Tue Oct 4 10:19:12 2018 +0100"
}, {
  "tag": "v1.1.1",
  "message": "Fix issue with spacing in the navigation",
  "date": "Tue Oct 9 12:13:16 2018 +0100"
}]

Я выяснил, как это сделать, используя несколько модулей Node для доступа к тегам, а затем выполняя некоторые команды Git, чтобы получить всю необходимую мне информацию из каждого тега. Это делается с помощью shelljs .

У меня проблема в том, что это очень медленно. Запуск gitTag.all((tags) = {}) (с использованием git-tag ) выполняется быстро, потому что он просто извлекает имена тегов. Однако, чтобы получить сообщение и дату, я запускаю две отдельные команды для каждого тега в цикле:

let msg = shell.exec(`git for-each-ref refs/tags/${tag} --format='%(subject)'`, {silent:true}).stdout;
let date = shell.exec(`git for-each-ref refs/tags/${tag} --format='%(authordate)'`, {silent:true}).stdout;

Обе эти команды все равно немного медленные, но выполнение их каждый раз для каждого имени тега занимает много времени.

Есть ли для меня более быстрый способ сделать это?

Пожалуйста, помните, что я запускаю это синхронно, потому что другой скрипт Node будет читать этот JSON-файл, и это может привести к гонке. Однако любые асинхронные идеи приветствуются, если они также могут решать эту проблему.

Пожалуйста, смотрите мой полный код ниже :

const gitTag = require('git-tag')({
  localOnly: true,
  dir: '.git'
});
const fs = require('fs-extra');
const shell = require('shelljs');

let tagsAllData = [];

let formatString = (string) => {
  return string.replace(/^'/, '').replace(/'\n+$/, '');
}

// Fetch all git tags
gitTag.all((tags) => {
  tags.forEach(tag => {

    // Collect the tag message and date values
    let msg = shell.exec(`git for-each-ref refs/tags/${tag} --format='%(subject)'`, {silent:true}).stdout;
    let date = shell.exec(`git for-each-ref refs/tags/${tag} --format='%(authordate)'`, {silent:true}).stdout;

    // Create array of tag objects
    tagsAllData.push({
      'tag': tag,
      'message': formatString(msg),
      'date': formatString(date)
    });
  });

  // Write the tag data as a JSON file
  let tagsJSON = JSON.parse(JSON.stringify(tagsAllData));
  fs.writeJSONSync('src/data/tags.json', tagsJSON);
});

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Основываясь на этом другом ответе, я также хотел бы сделать весь подход более асинхронным. foreach блокируется и будет зависеть от индивидуального исхода каждого звонка.

Вместо этого я бы использовал нативный API и создал из него обещание (как объяснено здесь ).

Вы можете использовать Promise.all для агрегирования результатов. Это упрощенный пример выполнения

const dateQueries = [];
const msgQueries = [];

tags.forEach(tag => {
    const dateQuery = exec(`git for-each-ref refs/tags/${tag} --format='%(subject)'`);
    const msgQuery = exec(`git for-each-ref refs/tags/${tag} --format='%(authordate)'`);

    dateQueries.push(dateQuery);
    msgQueries.push(msgQuery);
});
const msgResults = await Promise.all(msgQueries);
const dateResults = await Promise.all(dateQueries);

Однако ответ А.Х. является более производительным, поскольку он оптимизирует сам запрос.

0 голосов
/ 04 января 2019

Ваш реальный код вызывает оболочку дважды для каждого тега. Чтобы ускорить процесс, вы должны вызвать shell и, следовательно, сделать git не более одного раза - для тегов all . В оболочке это выглядит так:

git for-each-ref --sort=v:refname --format "tag: %(refname:strip=2) message: %(subject) date: %(creatordate:iso)" refs/tags

вывод выглядит так:

tag: v2.20.0-rc0 message: Git 2.20-rc0 date: 2018-11-18 18:25:38 +0900
tag: v2.20.0-rc1 message: Git 2.20-rc1 date: 2018-11-21 23:25:15 +0900
tag: v2.20.0-rc2 message: Git 2.20-rc2 date: 2018-12-01 21:45:08 +0900
tag: v2.20.1 message: Git 2.20.1 date: 2018-12-15 12:31:46 +0900

Вы должны сначала разбить этот вывод на отдельные строки, а каждую строку - на поля. Вы можете сделать это намного проще, настроив format таким образом, чтобы облегчить анализ (например, с помощью специальных символов между полями).

...