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

后端 未结 3 1771
无人共我
无人共我 2020-11-27 15:50

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

var require = __meteor_bootstrap__.require,
    request = require(\"request\")   


function getServices(         


        
相关标签:
3条回答
  • 2020-11-27 16:11

    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

    0 讨论(0)
  • 2020-11-27 16:15

    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.

    0 讨论(0)
  • 2020-11-27 16:26

    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.

    0 讨论(0)
提交回复
热议问题