JSON will not insert into Meteor Collection (even with Fiber or bindEnvironment)

448 views Asked by At

I realize that similar topics have been discussed, I have browsed through them all and tried to mimic solutions for about 4 hours but none of them seem to solve the problem. I would not have posted this with having exhausted any potential solution I could find.

I am trying to convert a large csv to JSON and then insert it into my Meteor collection following the conversion.

Here is my code using the Meteor.bindElement approach:

if Meteor.isServer
    @Fiber = Meteor.npmRequire("fibers")
    Meteor.startup ->
    #Converter Class
         if Data.find().count() is 0
             Converter = Meteor.npmRequire('csvtojson').core.Converter
             fs = Meteor.npmRequire('fs')
             csvFileName = '/Path/To/My/File.csv'
             fileStream = fs.createReadStream(csvFileName)
             #new converter instance
             csvConverter = new Converter(constructResult: true)
             #end_parsed will be emitted once parsing finished
             csvConverter.on "end_parsed", (jsonObj) ->
                 console.log jsonObj
                 boundFunction = Meteor.bindEnvironment(->
                     Data.insert jsonObj
                     return
                 , (e) ->
                      throw e
                      return
                 )

                 insertToDB boundFunction
                 #read from file
             fileStream.pipe csvConverter
         return

After parsing I am able to log the JSON just fine but when I try to add it to the collection like this:

csvConverter.on "end_parsed", (jsonObj) ->
    console.log jsonObj
    Data.insert jsonObj

I get the error:

throw new Error("Meteor code must always run within a Fiber. " +          
W20141112-20:08:44.306(-8)? (STDERR)           ^
W20141112-20:08:44.306(-8)? (STDERR) Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
W20141112-20:08:44.306(-8)? (STDERR)     at Object.Meteor._nodeCodeMustBeInFiber (packages/meteor/dynamics_nodejs.js:9)
W20141112-20:08:44.306(-8)? (STDERR)     at _.extend.get  (packages/meteor/dynamics_nodejs.js:21)
W20141112-20:08:44.306(-8)? (STDERR)     at Object.DDP.randomStream (packages/ddp/random_stream.js:69)
W20141112-20:08:44.306(-8)? (STDERR)     at self._makeNewID (packages/mongo/collection.js:72)
W20141112-20:08:44.306(-8)? (STDERR)     at Mongo.Collection.(anonymous function) [as insert] (packages/mongo/collection.js:485)
W20141112-20:08:44.307(-8)? (STDERR)     at csvAdv.<anonymous> (server/startup.coffee:16:13)
W20141112-20:08:44.307(-8)? (STDERR)     at csvAdv.emit (events.js:95:17)
W20141112-20:08:44.307(-8)? (STDERR)     at csvAdv.<anonymous> (/Users/samuel_chordas/CurrentClasses/CSCI477a/JPL/JataTwo/packages/npm-container/.build.npm-container/npm/node_modules/csvtojson/libs/core/init_onend.js:9:10)
W20141112-20:08:44.307(-8)? (STDERR)     at csvAdv.emit (events.js:117:20)
W20141112-20:08:44.307(-8)? (STDERR)     at _stream_readable.js:929:16
=> Exited with code: 8

Which I was able to get rid of by wrapping the function in a fiber with the following code but it DOES NOT write to my collection:

if Meteor.isServer
    @Fiber = Meteor.npmRequire("fibers")
    Meteor.startup ->
    #Converter Class
        if Data.find().count() is 0
            Converter = Meteor.npmRequire('csvtojson').core.Converter
            fs = Meteor.npmRequire('fs')
            csvFileName = '/Path/To/My/File.csv'
            fileStream = fs.createReadStream(csvFileName)
            #new converter instance
            csvConverter = new Converter(constructResult: true)
            #end_parsed will be emitted once parsing finished
            csvConverter.on "end_parsed", (jsonObj) ->
                Fiber ->
                    Data.insert jsonObj
                return
            fileStream.pipe csvConverter
        return

So I tried resorting to using the bindEnvironment as shown in the first block of code which results in the same "Error("Meteor code must always run within a Fiber" error.

Here is my collection in my /lib folder:

@Data = new Mongo.Collection 'data'

I am pretty new to Meteor Javascript and Coffescript so any feedback would be appreciated.

Also I would like to add that I can't get .run() to work on Fiber.

1

There are 1 answers

1
user3374348 On BEST ANSWER

Try moving the definition of boundFunction outside of the end_parsed event handler.

boundFunction = Meteor.bindEnvironment((jsonObj) ->
  Data.insert jsonObj
  return
, (e) ->
  throw e
)

csvConverter.on "end_parsed", (jsonObj) ->
  console.log jsonObj
  boundFunction jsonObj
  return

I suspect the "Meteor code must always run within a Fiber." error is not coming from Data.insert but from Meteor.bindEnvironment itself. Meteor.bindEnvironment

  • is called from inside a "Meteor context"
  • takes a function
  • binds that function to the same "Meteor context" that bindEnvironment was called from

In your implementation, by the time you call bindEnvironment, the "Meteor context" has already been lost, so bindEnvironment can't do anything to help.