1

I'm using rawCollection().aggregate() to temporarily clone fairly large MongoDB collections from within Meteor. The original collections hold financial data continually updated from websocket, and the copies are to be used for backtesting that data on the fly while the master data continues to update every minute from websocket.

The concept works, and will clone a collection of ~1.2 million records (~1.2gb) in anywhere between 30 and 60 seconds. Smaller collections (50,000 records) are instantaneous.

The problem: once complete, the await resolves and copied records are present and can be counted, but Meteor remains frozen. The front end does not load new pages, the datatables and live price updates stall, and the server console stops logging. After ~ 7 minutes all frees up again, and data which has been brought in during the freeze is processed, and datatables update again. The server console takes another ~2 minutes to catch up on logging.

The intent is that the app remain functional while backtesting goes on in the background - but this renders the front end useless for a significant period. Perhaps this is expected, but I had hoped that the aggregate approach would prevent the lock up. It completes quickly - but what is then causing the subsequent freeze?

Code is below. Any help at all appreciated.

A two-line method takes the Meteor.call, then calls:

async function startBacktest_async(exchange_id, datainterval) {

const removeOldData = await removeCollectionFromBacktest(exchange_id, datainterval);

if (removeOldData === true) {
    console.log("Backtest: Existing data removed");
} else {
    console.log("Backtest: No data removed");
};

if (removeOldData) {

    const collectionForCopy = data_collections[exchange_id + datainterval];
    const copyCollectionCount = await copyCollectionForBacktest(exchange_id, datainterval, collectionForCopy);

    if (copyCollectionCount) {
        console.log("Backtest copy: Collection " + exchange_id + datainterval + " || " + copyCollectionCount + " records copied");
        const copiedCollection = data_collections[exchange_id + datainterval + "_Backtest"];
        
        // DO STUFF HERE

        return "Backtest on (data replaced)";

    };
};

Remove old data - appears to have no effect on problem:

async function removeCollectionFromBacktest(exchange_id, datainterval) {

const collectionToRemove = data_collections[exchange_id + datainterval + "_Backtest"]
const removeRecordsPresent = await collectionToRemove.rawCollection().count();

if (!removeRecordsPresent > 0) { return "no records" } else {
    const removeComplete = await collectionToRemove.rawCollection().drop();
    if (removeComplete) {
        console.log("Backtest remove: Collection " + exchange_id + datainterval + " || " + removeRecordsPresent + " records removed")
        return true;
    };
};

};

Copy function:

async function copyCollectionForBacktest(exchange_id, datainterval, collectionForCopy) {

const collectionNameLower = (exchange_id + datainterval).toLowerCase();

const raw = collectionForCopy.rawCollection();
const aggregate = Meteor.wrapAsync(raw.aggregate, raw);
const query = [{ $match: {} }, { $out: collectionNameLower + "_backtest" }];
const backtestcollection = aggregate(query, { "allowDiskUse": true });

const copyComplete = await backtestcollection.toArray();

if (copyComplete) {
    try {
        delete copyComplete;
        const collectionToCount = data_collections[exchange_id + datainterval + "_Backtest"]
        const countToReturn = await collectionToCount.rawCollection().count();
        return countToReturn;
    } catch (error) {
        console.log(error);
        return;
    };
};

};

  • Does this help: https://stackoverflow.com/questions/12298640/meteors-subscription-and-sync-are-slow/19599027#19599027 ? – Christian Fritz Aug 20 '21 at 01:58
  • @ChristianFritz Thanks. Have taken a look. Templating shouldn't be a concern, as new collection is not sent to the front end at all, and isn't being published. This got me thinking, however, and I've altered to create the new temporary collections only on the server side. This sped up the copy (down to 22 seconds now for the 1.2gb), but doesn't resolve the freeze - in fact, may have slowed down further. Last test was > 10 minutes locked up. – ClancyoftheOverflow Aug 20 '21 at 03:51
  • Can you try to run the whole code within a `Meteor.defer` environment? That would obviously remove the async functionality but you could still call some callback function then – Jankapunkt Aug 20 '21 at 08:35
  • @Jankapunkt Thanks for the suggestion. I hadn't considered `Meteor.defer` - will give it a go. – ClancyoftheOverflow Aug 21 '21 at 00:44
  • @Jankapunkt No luck, I'm afraid. – ClancyoftheOverflow Aug 21 '21 at 10:24
  • this.unblock() could help you out.https://docs.meteor.com/api/methods.html#DDPCommon-MethodInvocation-unblock – Nicholas Tsaoucis Nov 05 '21 at 01:03

0 Answers0