Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

medici

Package Overview
Dependencies
Maintainers
2
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

medici - npm Package Compare versions

Comparing version 5.0.0 to 5.1.0

87

build/Book.js

@@ -16,2 +16,10 @@ "use strict";

const balance_1 = require("./models/balance");
const GROUP = {
$group: {
_id: null,
balance: { $sum: { $subtract: ["$credit", "$debit"] } },
notes: { $sum: 1 },
lastTransactionId: { $max: "$_id" },
},
};
class Book {

@@ -23,2 +31,4 @@ constructor(name, options = {}) {

this.balanceSnapshotSec = options.balanceSnapshotSec != null ? options.balanceSnapshotSec : 24 * 60 * 60;
this.expireBalanceSnapshotSec =
options.expireBalanceSnapshotSec != null ? options.expireBalanceSnapshotSec : 2 * this.balanceSnapshotSec;
if (typeof this.name !== "string" || this.name.trim().length === 0) {

@@ -36,2 +46,5 @@ throw new errors_1.BookConstructorError("Invalid value for name provided.");

}
if (typeof this.expireBalanceSnapshotSec !== "number" || this.expireBalanceSnapshotSec < 0) {
throw new errors_1.BookConstructorError("Invalid value for expireBalanceSnapshotSec provided.");
}
}

@@ -47,3 +60,2 @@ entry(memo, date = null, original_journal) {

let accountForBalanceSnapshot;
let needToDoBalanceSnapshot = true;
if (this.balanceSnapshotSec) {

@@ -57,4 +69,4 @@ accountForBalanceSnapshot = query.account ? [].concat(query.account).join() : undefined;

if (balanceSnapshot) {
// Use cached balance
parsedQuery._id = { $gt: balanceSnapshot.transaction };
needToDoBalanceSnapshot = Date.now() > balanceSnapshot.createdAt.getTime() + this.balanceSnapshotSec * 1000;
}

@@ -65,11 +77,3 @@ }

};
const group = {
$group: {
_id: null,
balance: { $sum: { $subtract: ["$credit", "$debit"] } },
notes: { $sum: 1 },
lastTransactionId: { $max: "$_id" },
},
};
const result = (await transaction_1.transactionModel.collection.aggregate([match, group], options).toArray())[0];
const result = (await transaction_1.transactionModel.collection.aggregate([match, GROUP], options).toArray())[0];
let balance = 0;

@@ -84,12 +88,53 @@ let notes = 0;

notes += result.notes;
if (needToDoBalanceSnapshot && result.lastTransactionId) {
await (0, balance_1.snapshotBalance)({
book: this.name,
account: accountForBalanceSnapshot,
meta,
transaction: result.lastTransactionId,
balance,
notes,
expireInSec: this.balanceSnapshotSec * 2, // Keep the document twice longer than needed in case this particular balance() query is not executed very often.
}, options);
// We can do snapshots only if there is at least one entry for this balance
if (this.balanceSnapshotSec && result.lastTransactionId) {
// It's the first (ever?) snapshot for this balance. We just need to save whatever we've just aggregated
// so that the very next balance query would use cached snapshot.
if (!balanceSnapshot) {
await (0, balance_1.snapshotBalance)({
book: this.name,
account: accountForBalanceSnapshot,
meta,
transaction: result.lastTransactionId,
balance,
notes,
expireInSec: this.expireBalanceSnapshotSec,
}, options);
}
else {
// There is a snapshot already. But let's check if it's too old.
const tooOld = Date.now() > balanceSnapshot.createdAt.getTime() + this.balanceSnapshotSec * 1000;
// If it's too old we would need to cache another snapshot.
if (tooOld) {
delete parsedQuery._id;
const match = {
$match: { ...parsedQuery, ...(0, flattenObject_1.flattenObject)(meta, "meta") },
};
// Important! We are going to recalculate the entire balance from the day one.
// Since this operation can take seconds (if you have millions of documents)
// we better run this query IN THE BACKGROUND.
// If this exact balance query would be executed multiple times at the same second we might end up with
// multiple snapshots in the database. Which is fine. The chance of this happening is low.
// Our main goal here is not to delay this .balance() method call. The tradeoff is that
// database will use 100% CPU for few (milli)seconds, which is fine. It's all fine (C)
transaction_1.transactionModel.collection
.aggregate([match, GROUP], options)
.toArray()
.then((results) => {
const resultFull = results[0];
return (0, balance_1.snapshotBalance)({
book: this.name,
account: accountForBalanceSnapshot,
meta,
transaction: resultFull.lastTransactionId,
balance: parseFloat(resultFull.balance.toFixed(this.precision)),
notes: resultFull.notes,
expireInSec: this.expireBalanceSnapshotSec,
}, options);
})
.catch((error) => {
console.error("medici: Couldn't do background balance snapshot.", error);
});
}
}
}

@@ -96,0 +141,0 @@ }

{
"name": "medici",
"version": "5.0.0",
"version": "5.1.0",
"description": "Simple double-entry accounting for Node + Mongoose",

@@ -5,0 +5,0 @@ "main": "build/index.js",

@@ -405,2 +405,13 @@ # medici

### v5.1.0
The balance snapshots were never recalculated from the beginning of the ledger. They were always based on the most recent snapshot. It gave us speed. Although, if one of the snapshots gets corrupt or an early ledger entry gets manually edited/deleted then we would always get wrong number from the `.balance()` method. Thus, we have to calculate snapshots from the beginning of the ledger at least once in a while.
BUT! If you have millions of documents in `medici_transactions` collection a full balance recalculation might take up to 10 seconds. So, we can't afford aggregation of the entire database during the `.blance()` invocation. Solution: let's aggregate it **in the background**. Thus, v5.1 was born.
New feature:
- In addition to the existing `balanceSnapshotSec` option, we added `expireBalanceSnapshotSec`.
- The `balanceSnapshotSec` tells medici how often you want those snapshots to be made **in the background** (right after the `.balance()` call). Default value - 24 hours.
- The `expireBalanceSnapshotSec` tells medici when to evict those snapshots from the database (TTL). It is recommended to set `expireBalanceSnapshotSec` higher than `balanceSnapshotSec`. Default value - twice the `balanceSnapshotSec`.
### v5.0.0

@@ -407,0 +418,0 @@

@@ -81,2 +81,3 @@ // Generated by dts-bundle-generator v6.2.0

balanceSnapshotSec: number;
expireBalanceSnapshotSec: number;
constructor(name: string, options?: {

@@ -86,2 +87,3 @@ precision?: number;

balanceSnapshotSec?: number;
expireBalanceSnapshotSec?: number;
});

@@ -88,0 +90,0 @@ entry(memo: string, date?: Date, original_journal?: string | Types.ObjectId): Entry<U, J>;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc