jpos / jPOS-EE

jPOS Extended Edition
http://jpos.org
GNU Affero General Public License v3.0
107 stars 152 forks source link

Balance cache is not created till reaches the safe window #219

Closed nalasra closed 3 years ago

nalasra commented 3 years ago

Hi,

I was running some tests and found balance cache mechanism looks a bit broken to me.

Scenario is my transentry and transacc table are empty and I am running my very first GL transaction.

The method getSafeMaxGLEntryId returns zero till the safe window difference is reached MAX(maxGLEntryId - SAFE_WINDOW, 0) https://github.com/jpos/jPOS-EE/blame/master/modules/minigl/src/main/java/org/jpos/gl/GLSession.java#L2026

The method createFinalbalanceCache doesn't create the cache because the following condition is not met maxId != c.getRef() https://github.com/jpos/jPOS-EE/blame/master/modules/minigl/src/main/java/org/jpos/gl/GLSession.java#L1547

Not sure if this is the intended purpose of balance cache, but I think it should be created starting from the very first GL entry?

If we initialize the ref with -1 in BalanceCache class constructor. So if a balance cache is not found and a new one is going to be created the following condition should allow it maxId != c.getRef()

I know we can override the safe window, but doing so will increase the chances of race condition and kill the purpose of the safe window.

ar commented 3 years ago

It's actually intended behavior. The BalanceCache doesn't intend to be synchronized with the very latest transaction for a given account at a given journal for a given set of layers. It's totally OK for miniGL to read a bunch of transaction entries (in the hundreds) to get the actual balance of a given account. That's very fast and performed by a database native query (on supported database).

The basic idea behind the BalanceCache is to prevent having to start for the very beginning of transentries and having to scan in some situations thousands of records.

We've choose the safe window value of 1000 because on heavy loaded systems, that's usually just a few seconds/minutes away from the latest transaction, and prevents some race conditions for in-flight transactions.

It was a mistake (my fault) to expose the balance caches as a public method of GLSession. It's actually a miniGL internal thing. Today we use the BalanceCache, tomorrow we could use something else, what we want is to provide fast balances. Something similar happens with CheckPoints. I hope to correct that design fault in future versions (and actually have some ideas in mind that I'm experimenting in PoC).

nalasra commented 3 years ago

Thanks for the great explanation. It all makes sense now.