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

只谈情不闲聊 提交于 2019-11-26 20:06:06

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.

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

Based on my tests you have to wrap the insert in code I tested that is similar to the above example.

For example, I did this and it still failed with Fibers error.

function insertPost(args) {
  if(args) {
Fiber(function() { 
    post_text = args.text.slice(0,140);
    T.post('statuses/update', { status: post_text }, 
        function(err, reply) {          
            if(reply){
                // TODO remove console output
                console.log('reply: ' + JSON.stringify(reply,0,4));
                console.log('incoming twitter string: ' + reply.id_str);
                // TODO insert record
                var ts = Date.now();
                id = Posts.insert({
                    post: post_text, 
                    twitter_id_str: reply.id_str,
                    created: ts
                });
            }else {
                console.log('error: ' + JSON.stringify(err,0,4));
                // TODO maybe store locally even though it failed on twitter
                // and run service in background to push them later?
            }
        }
    );
}).run();
  }
}

I did this and it ran fine with no errors.

function insertPost(args) {
  if(args) { 
post_text = args.text.slice(0,140);
T.post('statuses/update', { status: post_text }, 
    function(err, reply) {          
        if(reply){
            // TODO remove console output
            console.log('reply: ' + JSON.stringify(reply,0,4));
            console.log('incoming twitter string: ' + reply.id_str);
            // TODO insert record
            var ts = Date.now();
            Fiber(function() {
                id = Posts.insert({
                    post: post_text, 
                    twitter_id_str: reply.id_str,
                    created: ts
                });
            }).run();
        }else {
            console.log('error: ' + JSON.stringify(err,0,4));
            // TODO maybe store locally even though it failed on twitter
            // and run service in background to push them later?
        }
    }
);
  }
}

I thought this might help others encountering this issue. I have not yet tested calling the asynchy type of external service after internal code and wrapping that in a Fiber. That might be worth testing as well. In my case I needed to know the remote action happened before I do my local action.

Hope this contributes to this question thread.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!