flash-oss / medici

Double-entry accounting system for nodejs + mongoose
MIT License
307 stars 84 forks source link

Version 5: ACID-Transactions and Typescript #35

Closed Uzlopak closed 2 years ago

Uzlopak commented 2 years ago

@koresar I open this PR, so that others can also do a code review :)

Uzlopak commented 2 years ago

@clintonb

No this is work of 5 days and night. I will not rip this apart. I simply dont have the energy to do it. Also I am very confident in the code.

Also despite that it shows that 45 files were changed, only only 13 are active code files. The rest are configuration files, unit tests, interfaces etc.. So if you only focus on the 13 files in the src folder, you can manage it. Also keep in mind, that you have 100% test coverage. You can e.g. go to book.spec.ts, make .only for the book-describe, than e.g. select balance and do a npm run test:coverage and check if the code is covered by 100% or not. If 100% than check the unit tests if they are really complete and do make sense or not. Or start with the helper methods.

Please clone the repo and read the code with your favorite IDE. This would already help alot. :)

clintonb commented 2 years ago

It’s nice you’ve done this work, but I’m not reviewing it. This isn’t my project, and the scope of the pull request is simply too large.

You already have separate commits. I highly recommend breaking this into multiple pull requests to make the work easier to review. As a maintainer of other open source projects, it’s far easier/faster for me to review small, focused, pull requests than giant ones like this. 100% test coverage does not mean 100% bug-free.

Uzlopak commented 2 years ago

@clintonb I know what you mean. In OSS you have alot of Contributors and it is easier to review one small PR than a whole rewrite. But my experience as a professional Software Developery is that you have sometimes get out of the comfort zone and do the hard work and research to get the best result. :) Also this package is fairly simple.

And breaking it to multiple PRs is not an option, so I have to decline your suggestion. I mean, come on... these are basically 13 files. I have regularly PRs with more than hundred file changes... Not ideal, but you get used to it. And having a good code coverage and a good test structure helps you to review each file in a fair amount of time. If you of course do a unit test which does everything, than yeah you get 100% coverage fairly easy. But that garbage gets rejected by me also regularly.

Best Regards :)

Uzlopak commented 2 years ago

@koresar

Good morning to Australia. Medici should have now an awesome status. Only the pagination in balance is kind of inconsistent. Maybe you can tell if and what I should do with it? Keep it as is? Rip out Pagination? Fix Pagination?

Other than that, my PR is so far ready. I dont know what else you can do to improve the performance.

Uzlopak commented 2 years ago

The current Changelog

Uzlopak commented 2 years ago

@koresar If you want to remove paginated balance #36

Uzlopak commented 2 years ago

@nicolasburtey Implemented a lockAccounts method on book, which should be called as last operation in the transaction. This improves the performance of transactions in my unit test drastically. Before it had about 700 ms duration. Now it has about 200 ms duration. I took this idea from MongoDB Performance Tuning (2021), p. 217

If we move the contentious statement to the end of the transaction, then the chance
of a TransientTransactionError will be reduced, since the window for conflict will be
reduced to the final few moments in the execution of the transaction.

@koresar + @nicolasburtey

I am not that happy with the name .lockAccounts(). Do you have any suggestions?

But yeah, I guess the performance improvement is not to neglect. :)

Uzlopak commented 2 years ago

@koresar I am gone for 10 days. I hope the code is good to merge. Looking forward

koresar commented 2 years ago

Hi. I'm going through changes commit by commit. I'm loving the fact you are doing small commits rather than pushing huge ball of code in one go!

Random thoughts in no order:

export function extractObjectIdKeysFromSchema(schema: Schema) {
  const result: Set<string> = new Set();
  for (const [key, value] of Object.entries(schema.paths)) {
    if (value instanceof Schema.Types.ObjectId) {
      result.add(key);
    }
  }
  return result;
}

IMPORTANT!

The typescript-migration branch contains lock "account" feature code. That's no good. This PR is too much to merge. Could you please contact me in twitter DM?

Uzlopak commented 2 years ago

Regarding the for loop: I prefer the Classic for loops as they were always the fastest. Actually using for(var i = 0, il = arr.length ... Is the fastest loop and not using let. Also with the new stuff it could be that the memory consumption is bigger, as it potentially creates new Objects and Variables. But I guess we could easily argue that not the for loop is the bottleneck but the database operations.

So I am totally Ok if you want to use for-of instead of classical for-loop.

koresar commented 2 years ago

I'd change it to for-of because code is mostly read than written. We should write for readability. The current for loop usage is premature optimisaiton IMO.

koresar commented 2 years ago

We'll continue development in the next branch. Without any PRs for now. I'll publish v5.0.0-next to npm.