Meteor._wrapAsync вызывает 100% загрузку ЦП

Приложение использует пакет meteor-redis для выполнения запроса Redis, который иногда может занять 30 секунд, чтобы вернуть 100 000 результатов. В течение этого времени ожидания Meteor зависает и загружает ЦП на 100% в ожидании результатов запроса.

var client = redis.createClient(port, url)
client.zrangebyscoreSync = Meteor._wrapAsync(client.zrangebyscore)

client.zrangebyscoreSync(['game:scores', '', '+inf'], function(err, scores) {

    _.each(scores, function(score, player) {
        var doc = { ... }
        Scores.insert(doc)
    })


})

Вопрос. Можно ли как-то разрешить Meteor делать что-то еще, ожидая, пока Redis вернет огромный набор данных? Если client.zrangebyscore не обернут Meteor._wrapAsync, Meteor выдаст ошибку

 Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

и трассировка указывает на строку Scores.insert(doc).


person Nyxynyx    schedule 08.07.2014    source источник
comment
Поскольку вы пытаетесь использовать Redis, интересно, заинтересует ли вас интеграция Meteor-Redis, над которой я работаю: groups.google.com/forum/#!topic/meteor-core/Jl5Jt739wdA   -  person imslavko    schedule 09.07.2014


Ответы (1)


В общем случае Meteor позволит запускать другие методы, если вы сначала запустите this.unblock() для них, тем самым превращая эти запросы в новые волокна.

Причина, по которой вы получаете 100% загрузку ЦП, вероятно, является комбинацией того, что делает холостые волокна ЦП, и задачи, выполняемой под ними.

Если это проблема, вы можете попробовать вместо этого использовать Meteor.bindEnvironment, который не будет использовать будущее для ожидания и по-прежнему использовать обратные вызовы, чтобы убедиться, что все остается разблокированным:

client.zrangebyscore(['game:scores', '', '+inf'], Meteor.bindEnvironment(function(err, result) {
    _.each(scores, function(score, player) {
        var doc = { ... }
        Scores.insert(doc)
    })
}));

Meteor bindEnvironment — это почти то же самое, что и Meteor._wrapAsync, за исключением того, что в нем отсутствуют части, ожидающие результата. Похоже, вы не используете этот бит, поскольку вы не ищете результаты, выходящие из client.zrangebyscoreSync. Meteor.bindEnvironment может быть лучше для этого использования, он оборачивает ваши обратные вызовы в Fiber, поэтому вы можете использовать в них код Meteor.

person Tarang    schedule 08.07.2014
comment
scores, возвращенный client.zrangebyscsore, используется _.each. Можем ли мы по-прежнему использовать Meteor.bindEnvironment? - person Nyxynyx; 08.07.2014
comment
@Nyxynyx, все должно быть в порядке. Я немного не уверен, что именно вырывает вас из волокна (кроме setTimeout), я думаю, что это использование собственных методов узла, таких как запрос и fs и прочее. Если это что-то вроде forEach, все должно быть в порядке. Обновление - только что проверил его источник, все должно быть в порядке, потому что он использует .call для привязки обратного вызова или в любом случае использует forEach под капотом. - person Tarang; 08.07.2014