• Product-recommendation-manager search endpoints use custom binders for queries and require some Java code for the client generator to make it work (because the generator itself was written in Java and compiles Java code internally)

  • Available products are cached in the DB. The cache is invalidated when there's a new product upload in product-recommendation-manager

  • Private endpoints for overdrafts - they allow creating an overdraft with short periods. Useful for tests. Has to be disabled in prod.

  • Private endpoints for loans - read postings JSON, and handle on loan-manager side. Probably, no longer needed.

  • MoneySerializer - an attempt to standardize monetary BigDecimal serialization to include 5 precision digits. Not used everywhere, and probably it was better to use a custom type for money instead of BigDecimal.

  • PostingHandlers - each one is supposed to handle specific posting instructions. Introduced to make code more maintainable. For better performance posting handlers should be grouped by TransactionType in PostingApiListener for selecting a matched handler. I.e. for-each should be replaced with a map look-up.

  • InitContainer - there was a draft PR long ago on enabling init container for running migration scripts before the app starts. Basically, there has to be a Micronaut event listener that is triggered in the correct stage of app intialization (after Netty server is started or something like that) to make it work.

  • LoanServiceImpl, PersonalLoanEventHandler and LoanActivitiesImpl seem to be tangled up, and their responsibilities got smudged. This is a good candidate for refactoring.

  • I'd move mock classes to the test sources

  • OverdraftActivity was supposed to be an overdraft history record or a list of requested/preformed actions, however it didn't turn out so well. Thus, it is more of a snaphost + ChangeReason as a requested operation + ChangeStatus as a result of that operation.

  • Overdraft summary currentUsed field has never been used and is deprecated

  • Activity options (timeouts, retries, etc) are better be gather in a separate class or externalized to app properties. Currently, they are part of workflow classes

  • Temporal provides some query classes for the temporal cluster itself that can be useful. E.g. in TemporalQueriesImpl there is a query to check if there is a running workflow with some workflowId. Also, there are some useful methods in Workflow class. For example, you can use it to convert a typed workflow like OverdraftWorkflowImpl to an untyped workflow and get its execution, runId and other properties.

  • When requesting an overdraft, if a customerId doesn't exists, it is replaced by UUID(0, 0). Probably, this can be removed as it was needed for testing

  • Testing workflows is a pain. It looks easier if you extract common steps/verifications into separate methods and use custom matchers. Be aware that polymorphic JSON can get deserialized as LinkedHashMap instead of an expected type and break tests. Also, note that the test engine is smart enough to fast forward long periods of waiting, but workflows have to end eventually in tests. I.e. you have to complete/terminate an overdraft in a test. Lastly, activities are mocked in the workflow tests, because the tests are already quite huge, so they only check the order of execution and passed arguments. Checking the whole logic is better be done with itests.

  • The property safi-services.loan-manager.flags.debug-info-in-responses toggles debug info in the API error responses. Enabling it will result in verbose responses with exception messages/stacktraces. It can be helpful in local runs, however, we never really used this feature, so it can be removed.

  • Itests start the whole application context when running, including Kafka listeners, producers, etc. However, we test behaviour of a deployed service. Technically from a QA point of view these are E2E tests, and should be separated from loan-manager code.