agenda
agenda copied to clipboard
Error: cyclic dependency detected
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.
@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 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.
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.
Hi guys, I'm having this problem right now. Is there anything you would recommend or anything I can do to help?
@Shahor Try to include the field which needs to be updated instead of whole object.
I don't think we necessarily need to "fix" it in Agenda but would be good to include this scenario in docs. PRs welcome!
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 ✅