Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BEMINFO-1380 Implement queue for link overriding #41

Merged
merged 4 commits into from
Aug 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/tasks/libraries-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,9 @@ module.exports = {
}

Object.keys(registry[lib].versions).forEach(function (version) {
result.push({ lib: lib, version: version });
var item = { lib: lib, version: version };
target.getChanges().getLibraries().addAdded(item);
result.push(item);
});
});
return result;
Expand Down
277 changes: 218 additions & 59 deletions src/tasks/override-links.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ var util = require('util'),
logger = require('../logger'),

REGEXP = {
HREF: /<a\s+(?:[^>]*?\s+)?href="([^"]*)"/g, // <a href="...">
SRC: /<img\s+(?:[^>]*?\s+)?src="([^"]*)"/g, // <img src="...">
RELATIVE: {
DOC: /^\.?\/?(?:\.\.\/)+?([\w|-]+)\.?[md|html|ru\.md|en\.md]?/,
VERSION_DOC: /^\.?\/?(\d+\.\d+\.\d+)\-([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/,
BLOCK: /^\.\.?\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/,
BLOCKS: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.[md|html|ru\.md|en\.md]/,
LEVEL: /^\.\.?\/\.\.\/([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/,
BLOCK_FILES: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.(?![md|html|ru\.md|en\.md])/,
JSON: /\w+\.json/
}
};
HREF: /<a\s+(?:[^>]*?\s+)?href="([^"]*)"/g, // <a href="...">
SRC: /<img\s+(?:[^>]*?\s+)?src="([^"]*)"/g, // <img src="...">
RELATIVE: {
DOC: /^\.?\/?(?:\.\.\/)+?([\w|-]+)\.?[md|html|ru\.md|en\.md]?/,
VERSION_DOC: /^\.?\/?(\d+\.\d+\.\d+)\-([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/,
BLOCK: /^\.\.?\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/,
BLOCKS: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.[md|html|ru\.md|en\.md]/,
LEVEL: /^\.\.?\/\.\.\/([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/,
BLOCK_FILES: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.(?![md|html|ru\.md|en\.md])/,
JSON: /\w+\.json/
}
},
PORTION_SIZE = 100;

function buildHref(a) {
return util.format('<a href="%s"', a);
Expand Down Expand Up @@ -242,7 +243,7 @@ function overrideLinks(content, node, urlHash, lang, doc) {
});

var existedLinks = _.values(urlHash);
// nativeHref = href;
// nativeHref = href;

if (isMailTo(href) || isAnchor(href)) {
return buildHref(href);
Expand Down Expand Up @@ -311,7 +312,21 @@ function overrideLinks(content, node, urlHash, lang, doc) {
return content;
}

/**
* Creates url hash for resolve links

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to resolve

* @param {TargetBase} target object
* @returns {Promise}
*/
function collectUrls(target) {
/**
* Выбираем все записи документов (обычные посты и документация библиотек)
* Фильтруем записи документов по критерию наличия url - адреса документа на github
* и строим hash соответствия ключа записи - url
* Загружаем все записи из пространства ключей NODE
* строим итоговый хэш в котором значениями являются урлы страниц на сайте
* а ключами урлы на гитхабе или id записей в случае блоков или отсутствия соответствий
* url github -> site url
*/
return levelDb.get().getByKeyRange(target.KEY.DOCS_PREFIX, target.KEY.NODE_PREFIX)
.then(function (docRecords) {
return vow.all([
Expand Down Expand Up @@ -345,46 +360,171 @@ function collectUrls(target) {
});
}

module.exports = function (target) {
logger.info('Start overriding links', module);
/**
* Reads document page records from db
* @param {TargetBase} target object
* @param {Object[]} changedLibVersions - array with changed library versions
* @returns {Promise}
*/
function getDocumentRecordsFromDb (target, changedLibVersions) {
/**
* Здесь происходит выборка из пространства ключей NODE
* по критериям:
*
* 1. view страницы должно быть 'post'
* 2. Если это документ версии библиотеки, то версия библиотеки должна быть в модели измененных
*/
return levelDb.get().getByCriteria(function (record) {
var value = record.value,
route = value.route,
conditions, lib, version;

if (value.view !== 'post') {
return false;
}

if (!target.getChanges().areModified()) {
logger.warn('No changes were made during this synchronization. This step will be skipped', module);
return vow.resolve(target);
}
conditions = route.conditions;
if (conditions && conditions.lib && conditions.version) {
lib = conditions.lib;
version = conditions.version;

var languages = utility.getLanguages(),
librariesChanges = target.getChanges().getLibraries(),
changedLibVersions = []
.concat(librariesChanges.getAdded())
.concat(librariesChanges.getModified());
return changedLibVersions.some(function (item) {
return item.lib === lib && item.version === version;
});
}

return vow.all([
levelDb.get().getByCriteria(function (record) {
var value = record.value,
route = value.route,
conditions, lib, version;
return true;
}, { gte: target.KEY.NODE_PREFIX, lt: target.KEY.PEOPLE_PREFIX, fillCache: true });
}

conditions = route.conditions;
if (conditions && conditions.lib && conditions.version) {
lib = conditions.lib;
version = conditions.version;
/**
* Reads block pages from database
* @param {TargetBase} target object
* @param {Object[]} changedLibVersions - array with changed library versions
* @returns {Promise}
*/
function getBlockRecordsFromDb(target, changedLibVersions) {
/**
* Здесь происходит выборка из пространства ключей NODE
* по критериям:
*
* 1. view страницы должно быть 'block'
* 2. Должен быть source.data - ссылка на запись с документацией блока
* 3. Версия библиотеки должна быть в модели измененных
*/
return levelDb.get().getByCriteria(function (record) {
var value = record.value,
route = value.route,
conditions, lib, version;

if (value.view !== 'block') {
return false;
}

return changedLibVersions.some(function (item) {
return item.lib === lib && item.version === version;
});
}
if (!value.source || !value.source.data) {
return false;
}

return true;
}, { gte: target.KEY.NODE_PREFIX, lt: target.KEY.PEOPLE_PREFIX, fillCache: true }),
collectUrls(target)
])
.spread(function (nodeRecords, urlsHash) {
logger.debug('Urls were collected. Start to process pages ...', module);
return vow.all(nodeRecords.map(function (nodeRecord) {
var nodeValue = nodeRecord.value;
conditions = route.conditions;
if (conditions && conditions.lib && conditions.version) {
lib = conditions.lib;
version = conditions.version;

return changedLibVersions.some(function (item) {
return item.lib === lib && item.version === version;
});
}

return false;
}, { gte: target.KEY.NODE_PREFIX, lt: target.KEY.PEOPLE_PREFIX, fillCache: true });
}

/**
* Overrides links for document page records
* @param {TargetBase} target object
* @param {Object} urlsHash - url comparison hash
* @param {String []} languages - array of language identifiers
* @param {Object[]} changedLibVersions - array with changed library versions
* @returns {Promise}
*/
function overrideLinksInDocuments (target, urlsHash, languages, changedLibVersions) {
logger.debug('Start to override links in documents', module);

/**
* 1. Выбираем страницы документов из бд
* 2. Делим массив полученных записей на массивы по 100 штук
* 3. Последовательно выполняем переопределение ссылок для каждой порции записей
* 3.1 Внутри порции переопредление ссылок для записей происходит параллельно
* 3.2 Для каждой записи страницы выбираем связанную с ней запись документа
* 3.3 Еслитаковая присутствует, то скармливаем ее content в переопределятор
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Еслитаковая

* 3.4 Сохраняем запись документа с измененным контентом
*/
return getDocumentRecordsFromDb(target, changedLibVersions).then(function (records) {
logger.debug(util.format('Document records count: %s', records.length), module);
var portionSize = PORTION_SIZE,
portions = _.chunk(records, portionSize);

logger.debug(util.format('Document records were divided into %s portions', portions.length), module);

return portions.reduce(function (prev, item, index) {
prev = prev.then(function () {
logger.debug(util.format('override document links in range %s - %s',
index * portionSize, (index + 1) * portionSize), module);
return vow.allResolved(item.map(function (_item) {
var nodeValue = _item.value;
return vow.all(languages.map(function (lang) {
var docKey = util.format('%s%s:%s', target.KEY.DOCS_PREFIX, nodeValue.id, lang);
return levelDb.get().get(docKey)
.then(function (docValue) {
if (!docValue || !docValue.content) {
return vow.resolve();
}
docValue.content = overrideLinks(docValue.content, nodeValue, urlsHash, lang, docValue);
return levelDb.get().put(docKey, docValue);
});
}));
}));
});
return prev;
}, vow.resolve());
});
}

/**
* Overrides links for block page records
* @param {TargetBase} target object
* @param {Object} urlsHash - url comparison hash
* @param {String []} languages - array of language identifiers
* @param {Object[]} changedLibVersions - array with changed library versions
* @returns {Promise}
*/
function overrideLinksInBlocks(target, urlsHash, languages, changedLibVersions) {
logger.debug('Start to override links in blocks', module);

/**
* 1. Выбираем страницы блоков из бд
* 2. Делим массив полученных записей на массивы по 100 штук
* 3. Последовательно выполняем переопределение ссылок для каждой порции записей
* 3.1 Внутри порции переопредление ссылок для записей происходит параллельно
* 3.2 Для каждой записи страницы выбираем связанную с ней запись докуметации блока
* 3.3 Если таковая присутствует, то скармливаем ее content в переопределятор
* с учетом различных форматов документации для разных библиотек и наличия нескольких языков
* 3.4 Сохраняем запись документации блока с измененным контентом
*/
return getBlockRecordsFromDb(target, changedLibVersions).then(function (records) {
logger.debug(util.format('Block records count: %s', records.length), module);
var portionSize = PORTION_SIZE,
portions = _.chunk(records, portionSize);

logger.debug(util.format('Block records were divided into %s portions', portions.length), module);

return portions.reduce(function (prev, item, index) {
prev = prev.then(function () {
logger.debug(util.format('override block links in range %s - %s',
index * portionSize, (index + 1) * portionSize), module);
return vow.allResolved(item.map(function (_item) {
var nodeValue = _item.value;

if (nodeValue.source && nodeValue.source.data) {
return levelDb.get().get(nodeValue.source.data).then(function (blockValue) {
if (!blockValue) {
return vow.resolve();
Expand Down Expand Up @@ -421,20 +561,39 @@ module.exports = function (target) {

return levelDb.get().put(nodeValue.source.data, blockValue);
});
}

return vow.all(languages.map(function (lang) {
var docKey = util.format('%s%s:%s', target.KEY.DOCS_PREFIX, nodeValue.id, lang);
return levelDb.get().get(docKey)
.then(function (docValue) {
if (!docValue || !docValue.content) {
return vow.resolve();
}
docValue.content = overrideLinks(docValue.content, nodeValue, urlsHash, lang, docValue);
return levelDb.get().put(docKey, docValue);
});
}));
}));
});
return prev;
}, vow.resolve());
});
}

module.exports = function (target) {
logger.info('Start overriding links', module);

if (!target.getChanges().areModified()) {
logger.warn('No changes were made during this synchronization. This step will be skipped', module);
return vow.resolve(target);
}

var languages = utility.getLanguages(),
librariesChanges = target.getChanges().getLibraries(),
changedLibVersions = []
.concat(librariesChanges.getAdded())
.concat(librariesChanges.getModified()),
urlsHash;

return collectUrls(target)
.then(function (_urlsHash) {
logger.debug('Urls were collected. Start to process pages ...', module);
urlsHash = _urlsHash;
return urlsHash;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe return _urlsHash; without 588-line?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нет, на нужно сохранить в переменную чтобы воспользоваться в операциях ниже.
См стр. 583

})
.then(function () {
return overrideLinksInDocuments(target, urlsHash, languages, changedLibVersions);
})
.then(function () {
return overrideLinksInBlocks(target, urlsHash, languages, changedLibVersions);
})
.then(function () {
logger.info('Links were successfully overrided', module);
Expand Down