Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • the lowest common denominator is the string type (aka JSON blob); this is where we lose the type information
  • the strings are transformed into JSONObjectsJSON Objects; a little bit better than raw strings, but barely more than a hash map
  • a ton of "magic" strings are needed to get/set values
  • this approach makes refactoring unnecessarily more difficult
  • to be able to serve an OpenAPI descriptor (as JSON and YAML) we had to re-introduce the type information at the REST API level with dummy classes that contain only the specified attributes; those classes are only used with the Swagger annotations and no were else
  • some developers skipped the layered architecture and found it too tedious to maintain DTOs and JSON helper classes, and as a result just passed JSONObjects right to the business logic layer
  • now the business logic is unnecessarily aware of how Fineract communicates to the outside world and makes replacing/enhancing the communication protocol (e.g. with GRPC) pretty much impossible

...

Class contains some generic attributes like:

  • username
  • tenant ID
  • username(s)
  • timestamp(s)
  • idempotency key
  • error message (if available)
  • state of execution (when stored to the database)

The actual payload (aka command input parameters) are defined as a generic parameter. It is expected that the modules implement classes that introduce the payload types and inherit from the abstract command class.

...

  • synchronously (required): this is pretty much as we do right now (use virtual threads optionally)
  • asynchronously (optional): with executor service and completable futures (use virtual threads optionally)
  • non-blocking (optional): high perfomance performance LMAX Disruptor non-blocking implementation

These different perfromance performance level implementations need to be absolute drop-in replacements (for each other). It is expected that more performant implementations need more testing due to increased complexity and possible unforseen side effects. In case any problems show up we can always roll back to the required default implementation (synchronous).

NOTE: we should consider providing a command processing implementation based on Apache Camel once this concept is approved and we migrated already a couple of services. They are specialized for exactly this kind of use cases and have more dedicated people working on it's implementation. Could give more flexibility without us needing to maintain code.

Middlewares

Instead of bolting/hardcoding additional features to the command processing engine we propose the concept of middlewares (similar to servlet filters). These pluggable components receive the command object as an input parameter and can execute addtional functionality without the main command processing component being aware of it. One example of such a middleware would be enforcement of idempotence.

References to users

Keep things lightweight and only reference users by their user names.f

Critical patch of execution

...

  • Jan 12-15 2025: First prototype and pull request available
  • Jan 2025: community vote
  • Jan 2025: pick an example Fineract service/feature (e.g. document management) that is less used than others and onboard devs
  • Feb 2025: review the results, lessons learned, performance improvement (or degradation)
  • Feb 2025: community vote if this is a viable approach; if yes, prioritize the migration of Fineract's services/features starting with the least important (Fineract has approximately 50 features/services/"modules" that would need to be migrated)
  • Feb 2026: added audit capabilities
  • Mar 2026: tentative date for completion of migration of 20 modules (currently ca. 10 modules are migrated or close to)

NOTE: the actual refactoring of a feature/service for type-safety will be done with the following steps

...