agenda icon indicating copy to clipboard operation
agenda copied to clipboard

Error: cyclic dependency detected

Open 0x62 opened this issue 7 years ago • 7 comments

While using Agenda, I accidentally attached a Sequelize model instance, instead of a plain JS object. This triggered a rather cryptic error, generated by MongoDB, as the object couldn't be serialized.

Uncaught Error: cyclic dependency detected
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:296:33)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:776:17)
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:308:18)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:776:17)
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:308:18)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:776:17)
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:308:18)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:776:17)
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:308:18)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:776:17)
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:308:18)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:618:17)
      at serializeObject (node_modules/bson/lib/bson/parser/serializer.js:308:18)
      at serializeInto (node_modules/bson/lib/bson/parser/serializer.js:776:17)
      at BSON.serialize (node_modules/bson/lib/bson/bson.js:58:27)
      at Query.toBin (node_modules/mongodb-core/lib/connection/commands.js:140:25)
      at Pool.write (node_modules/mongodb-core/lib/connection/pool.js:986:23)
      at executeWrite (node_modules/mongodb-core/lib/wireprotocol/3_2_support.js:73:10)
      at WireProtocol.insert (node_modules/mongodb-core/lib/wireprotocol/3_2_support.js:84:3)
      at Server.insert (node_modules/mongodb-core/lib/topologies/server.js:564:35)
      at Server.insert (node_modules/mongodb/lib/server.js:390:17)
      at insertDocuments (node_modules/mongodb/lib/collection.js:743:19)
      at insertOne (node_modules/mongodb/lib/collection.js:438:3)
      at Collection.insertOne (node_modules/mongodb/lib/collection.js:426:44)
      at Agenda.module.exports [as saveJob] (node_modules/agenda/lib/agenda/save-job.js:95:22)
      at Job.module.exports [as save] (node_modules/agenda/lib/job/save.js:9:15)
      at Agenda.module.exports [as now] (node_modules/agenda/lib/agenda/now.js:19:7)

I'd suggest that agenda attempt to serialize objects before passing them directly to the mongo driver, and if not possible, throws a more descriptive error.

0x62 avatar Dec 21 '17 16:12 0x62

@simison @vkarpov15 should we check if object has a toJSON method and call that before saving to DB incase the object is a class, etc?

OmgImAlexis avatar Dec 21 '17 23:12 OmgImAlexis

@OmgImAlexis there's a few alternatives here. The MongoDB driver looks for a toBSON() function before serializing (https://github.com/mongodb/js-bson/pull/231) so you can do stuff like this:

var BSON = require('bson');

var bson = new BSON();

class CustomSerialize {
  toBSON() {
    return 42;
  }
}

const obj = { answer: new CustomSerialize() };
// "{ answer: 42 }"
console.log(bson.deserialize(bson.serialize(obj)));

I put in a PR to sequelize for supporting that, see sequelize/sequelize#8810 . If they're not interested in supporting that, we can also implement a separate lib like mongodb-moment that attaches the toBSON() function.

I can see the benefit of agenda using toJSON() because very few people are even aware of toBSON() as far as I know. However, if sequelize merges my PR then this issue goes away transparently for agenda and all other mongodb clients (mongoose, connect-mongodb-session, connect-mongo, etc.) so I'd prefer to see what they say first.

vkarpov15 avatar Dec 22 '17 18:12 vkarpov15

Noting here a comment from https://github.com/sequelize/sequelize/pull/8810#issuecomment-354412896:

Yeah, its better if this is handled at application code or as a plugin.

simison avatar Jan 25 '18 15:01 simison

Hi guys, I'm having this problem right now. Is there anything you would recommend or anything I can do to help?

Shahor avatar Feb 09 '18 19:02 Shahor

@Shahor Try to include the field which needs to be updated instead of whole object.

RahulSaini202 avatar Feb 13 '18 13:02 RahulSaini202

I don't think we necessarily need to "fix" it in Agenda but would be good to include this scenario in docs. PRs welcome!

simison avatar Jul 20 '18 07:07 simison

If you run into this problem, stringify your JSON data before providing it to agenda, and then parse it when you're ready to use it. I used Flatted and it did the job for me ✅

kayode0x avatar May 26 '22 06:05 kayode0x