Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Meteor code must always run within a Fiber" when calling Collection.insert on server

I have the following code in server/statusboard.js;

var require = __meteor_bootstrap__.require,     request = require("request")      function getServices(services) {   services = [];   request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {     var resJSON = JSON.parse(body);      _.each(resJSON, function(data) {        var host = data["host_name"];        var service = data["service_description"];        var hardState = data["last_hard_state"];        var currState = data["current_state"];        services+={host: host, service: service, hardState: hardState, currState: currState};        Services.insert({host: host, service: service, hardState: hardState, currState: currState});     });   }); }  Meteor.startup(function () {   var services = [];   getServices(services);   console.log(services); }); 

Basically, it's pulling some data from a JSON feed and trying to push it into a collection.

When I start up Meteor I get the following exception;

app/packages/livedata/livedata_server.js:781       throw exception;             ^ Error: Meteor code must always run within a Fiber     at [object Object].withValue (app/packages/meteor/dynamics_nodejs.js:22:15)     at [object Object].apply (app/packages/livedata/livedata_server.js:767:45)     at [object Object].insert (app/packages/mongo-livedata/collection.js:199:21)     at app/server/statusboard.js:15:16     at Array.forEach (native)     at Function.<anonymous> (app/packages/underscore/underscore.js:76:11)     at Request._callback (app/server/statusboard.js:9:7)     at Request.callback (/usr/local/meteor/lib/node_modules/request/main.js:108:22)     at Request.<anonymous> (/usr/local/meteor/lib/node_modules/request/main.js:468:18)     at Request.emit (events.js:67:17) Exited with code: 1 

I'm not too sure what that error means. Does anyone have any ideas, or can suggest a different approach?

like image 269
Andrew Beresford Avatar asked Apr 17 '12 14:04

Andrew Beresford


People also ask

What is _ID in each document in Meteor?

Each document is a EJSON object. It includes an _id property whose value is unique in the collection, which Meteor will set when you first create the document.

How do I create a collection in Mongo Meteor?

Meteor stores data in collections. To get started, declare a collection with new Mongo.Collection. Constructor for a Collection The name of the collection. If null, creates an unmanaged (unsynchronized) local collection. The server connection that will manage this collection.

How do I Turn Off autopublish in Meteor?

By default, Meteor automatically publishes every document in your collection to each connected client. To turn this behavior off, remove the autopublish package, in your terminal: and instead call Meteor.publish to specify which parts of your collection should be published to which users.


2 Answers

Just wrapping your function in a Fiber might not be enough and can lead to unexpected behavior.

The reason is, along with Fiber, Meteor requires a set of variables attached to a fiber. Meteor uses data attached to a fiber as a dynamic scope and the easiest way to use it with 3rd party api is to use Meteor.bindEnvironment.

T.post('someurl', Meteor.bindEnvironment(function (err, res) {   // do stuff   // can access Meteor.userId   // still have MongoDB write fence }, function () { console.log('Failed to bind environment'); })); 

Watch these videos on evented mind if you want to know more: https://www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables https://www.eventedmind.com/posts/meteor-what-is-meteor-bindenvironment

like image 59
imslavko Avatar answered Sep 18 '22 02:09

imslavko


As mentioned above it is because your executing code within a callback.

Any code you're running on the server-side needs to be contained within a Fiber.

Try changing your getServices function to look like this:

function getServices(services) {   Fiber(function() {      services = [];     request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {       var resJSON = JSON.parse(body);        _.each(resJSON, function(data) {          var host = data["host_name"];          var service = data["service_description"];          var hardState = data["last_hard_state"];          var currState = data["current_state"];          services+={host: host, service: service, hardState: hardState, currState: currState};          Services.insert({host: host, service: service, hardState: hardState, currState: currState});       });     });   }).run();   } 

I just ran into a similar problem and this worked for me. What I have to say though is that I am very new to this and I do not know if this is how this should be done.

You probably could get away with only wrapping your insert statement in the Fiber, but I am not positive.

like image 20
Zeman4323 Avatar answered Sep 20 '22 02:09

Zeman4323