【发布时间】:2015-01-02 13:44:09
【问题描述】:
我正在使用job-collection 包执行以下操作:
- 下载包含大量网页元数据的大文件
- 使用 NPM
event-stream包从由正则表达式拆分的文件元数据创建流 - 检查集合中的元数据是否匹配(我一直在尝试将每个网页的元数据流式传输到另一个函数来执行此操作)
文件太大,无法缓冲,因此需要流式传输。 Here is a small file with a few examples of the metadata 如果你想试试这个。
job-collection 包中的每个作业都已经在一个异步函数中:
var request = Npm.require('request');
var zlib = Npm.require('zlib');
var EventStream = Meteor.npmRequire('event-stream');
function (job, callback) {
//This download is much too long to block
request({url: job.fileURL, encoding: null}, function (error, response, body) {
if (error) console.error('Error downloading File');
if (response.statusCode !== 200) console.error(downloadResponse.statusCode, 'Status not 200');
var responseEncoding = response.headers['content-type'];
console.log('response encoding is %s', responseEncoding);
if (responseEncoding === 'application/octet-stream' || 'binary/octet-stream') {
console.log('Received binary/octet-stream');
var regexSplit = /WARC\/1\./;
response.pipe(zlib.createGunzip()
.pipe(EventStream.split(regexSplit))
.pipe(EventStream.map(function (webpageMetaData) {
/* Need parse the metaData or pass each webpageMetaData to function
* This next function could block if it had to */
searchPageMetaData(webpageMetaData); // pass each metadatum to this function to update a collection - this function can be synchronous
}));
} else {
console.error('Wrong encoding');
}
});
}
function searchWebPageMetaData(metaData) {
// Parse JSON and search collection for match
}
- 有没有更好的方法来构建它?我在正确的轨道上吗?
-
Meteor.bindEnvironment应该放在哪里? - 每次传递到searchWebPageMetaData()时我是否绑定环境?我需要在这里明确使用纤维吗? - 如果我将它运行到
process.stdout,则流在运行时会停止。我应该将流放入 Meteor 的包装中吗? - 我知道
Meteor.wrapAsync。我想将最里面的searchWebPageMetaData()函数包装在Meteor.wrapAsync中吗? (认为我在输入时会回答“是”) - 流是否会变慢以补偿 DB 调用的缓慢?我的猜测是否定的,但我该如何处理?
我花了很长时间学习 Meteor 的 wrapAsync 和 bindEnvironment,但无法将它们整合在一起并理解在哪里使用它们。
补充 1
澄清一下,步骤如下:
- 下载文件;
- 创建流;
- 解压;
- 将其拆分为单独的网页 - EventStream 处理此问题
- 将其发送到函数 - 不需要返回值;这可能是阻塞的,它只是一些搜索和数据库调用
我试图做这样的事情,除了我需要帮助的核心代码位于不同文件的函数中。以下代码包含@electric-jesus 的大部分答案。
processJobs('parseWatFile', {
concurrency: 1,
cargo: 1,
pollInterval: 1000,
prefetch: 1
}, function (job, callback) {
if (job.data.watZipFileLink) {
queue.pause();
console.log('queue should be paused now');
var watFileUrl = 'https://s3.amazonaws.com/ja-common-crawl/exampleWatFile.wat.gz';
function searchPageMetaData(webpageMetaData, callback) {
console.log(webpageMetaData); // Would be nice to just get this function logging each webPageMetaData
future.return(callback(webpageMetaData)); //I don't need this to return any value - do I have to return something?
}
if (!watFile)
console.error('No watFile passed to downloadAndSearchWatFileForEntity ');
var future = new Future(); // Doc Brown would be proud.
if(typeof callback !== 'function') future.throw('callbacks are supposed to be functions.');
request({url: watFile, encoding: null}, function (error, response, body) {
if (error) future.throw('Error Downloading File');
if (response.statusCode !== 200) future.throw('Expected status 200, got ' + response.statusCode + '.');
var responseEncoding = response.headers['content-type'];
if (responseEncoding === 'application/octet-stream' || 'binary/octet-stream') {
var regexSplit = /WARC\/1\./;
response.pipe(zlib.createGunzip()
.pipe(EventStream.split(regexSplit))
.pipe(EventStream.map(function (webpageMetaData) {
searchPageMetaData(webpageMetaData, callback);
})
));
} else {
future.throw('Wrong encoding');
}
});
return future.wait();
} else {
console.log('No watZipFileLink for this job');
job.log('ERROR: NO watZipFileLink from commonCrawlJob collection');
}
queue.resume();
job.done;
callback();
}
【问题讨论】:
-
我不认为这是重复的:这个问题没有任何答案可以接近我在这里尝试做的事情。
标签: node.js asynchronous meteor stream