I've spend >10 hours on a possible Apsotrophe database enhancement, and am stuck on what seems to be an unrelated bug. I was experimenting with switching out MongoDB with a flat file database such as NEDB, LokiJS, or TingoDB. These have the same command set available as MongoDB, sometimes with the exception of a couple of small commands that I was able to add in (in the case listed below using LokiJS, there is no db.collection method, so I wrote a simple one that works fine). The end goal for this is to make hosting tiny Apos projects easier, since you wouldn't need to worry about finding a service to host a MongoDB instance for you - it would all be stored on a local file (although would be very slow if a project got too large - LokiJS should be able to support databases up to 1GB in size without performance issues, theoretically).
I'm seeing data being written to the local database files, so it seems as though it's working. However, the application does not finish starting up. No error's occur, and the application runs continuously, but never seems to get to a point where there is an accessible URL. I spent a LOT of time debugging this, and it appears that any afterConstruct methods stop working when I overwrote the connectToMongo method in apostrophe-db. Somehow, it looks like a callback during apostrophe startup doesn't happen in an async call when initiating modules - but the database change shouldn't effect that, as far as I could tell.
I have a Glitch link that shows the problem. It is very barebones, and the only change from default is the overwriting of the connectToMongo method. You can remix the project for free if you want to debug the node.js side or make edits. If I can ever get this working, I plan to make it into an NPM package so that others can use it as well - at this point I'm pretty stuck though.
https://glitch.com/edit/#!/apos-flat-test
(In case you haven't used Glitch before, you can make a copy of my current code and debug it by clicking the project name at the top left and clicking Remix Project. You can also attach to Chrome's V8 debugger to debug the node stuff - you just click the Logs button at the top left then click the Debug button at the bottom window that pops up).
Thanks!
Many of those afterConstruct functions, including the apostrophe-caches
one, call either db.getCollection
or collection.ensureIndex
. Here is the relevant code from the caches module:
https://gist.github.com/boutell/c4a1b4abda4a19572428b11d0a8babc8
So your implementation must support both of those things, with callbacks or without.
Your implementation of getCollection looks like it should work.
However, the ensureIndex
method of LokiJS
is very different from that in MongoDB. MongoDB expects:
.ensureIndex({ field: 1 }, callback);
While LokiJS
expects:
.ensureIndex(fieldName, force)
This is a very different method with a different impact. It can't be expected to substitute for MongoDB's implementation without additional effort.
Invoking it with an object and a callback doesn't set up the index expected, and more importantly, never invokes the callback. This is why it does not work. Without the invocation of the callback Apostrophe cannot move on with initialization.
So the issue is not afterConstruct itself, but rather an incomplete emulation of the MongoDB API. Apostrophe requires a full implementation of the API to guarantee success. You might have better success with a "Mongo-alike" that attempts a higher level of compatibility, although even CosmosDB does not really come close (it doesn't, for instance, have the commonly used distinct
convenience method).
Thanks for giving this a try and giving the community more data about another Mongo semi-compatible database though - perhaps one will eventually be complete enough, or the Apostrophe community will contribute to making it so.