Skip to content

Latest commit

 

History

History
113 lines (92 loc) · 9.24 KB

README.md

File metadata and controls

113 lines (92 loc) · 9.24 KB

Business Banking with Akka.NET

Intro

This project utilizes the actor model and event sourcing via Akka.NET to build business banking functionality. Event sourcing is implemented with Akka.Persistence via PostgreSQL. Akka.Cluster.Sharding is used for account and employee actors. Future/recurring actor message scheduling with PostgreSQL persistence is set up with Quartz.NET.

Use Cases

  1. Automatic Balance Management
    • Maintain a zero balance after each transaction
    • Maintain a daily target balance by allowing a partner account to absorb excess cash or replenish cash to the target account
    • Distribute balance among multiple accounts within an org on a per-transaction, daily, or twice-monthly schedule
  2. Employee Purchases
  3. Move money between accounts within your organization
  4. Transfer money immediately or on a future date to other organizations on the platform
  5. Payment requests between organizations on the platform
  6. Domestic transfers are sent to a Mock Domestic Transfer Processor service to mock the interaction of sending money to accounts outside the platform, such as an ACH transfer via Plaid. Integration with Akka circuit breaker allows pending transfers to be reprocessed if they previously failed due to intermittent network issues.
  7. Recurring maintenance fee for each billing cycle unless a qualified deposit found or a daily account balance threshold met.
  8. Manage daily/monthly employee purchase limits per employee card
  9. Monitor employee purchases and other activities on the platform
  10. Billing statements issued for each billing cycle
  11. Emails sent for account open/close, employee invites, billing statement, purchase declined, transfer deposited, etc.

8-29-business-banking

UI

The UI is built with React libraries for the F# landscape. See Feliz.

SignalR is used to provide feedback from actors to the UI:

  • Overall account state
  • History of transactions on the account
  • Toggling between a transfer sender & receiver account (internal to the bank) demonstrates debits in one account and credits in the other
  • A system operations navbar displays circuit breaker open/closed status for domestic transfers to the 3rd party bank mock server
  • When the circuit breaker closes, pending domestic transfers are reprocessed & corresponding Approved/Rejected events are interpolated into the table

Demonstration

Automatic Balance Management

auto-balance-manage

Analytics

analytics-timeseries analytics-top-n

Transactions

transaction-back-button transactions-date

More Demonstration GIFs included at the bottom of the README.

Running with Kubernetes via minikube

  1. Dependencies: .NET 8, minikube, pulumi, Node.js 18
  2. sh build.sh -t RunK8sApp
  3. Browser opens automatically after all K8s resources start up
  4. Enable postgres port forwarding if you want to inspect postgres in a local client: sh postgres-port-forward-k8s.sh (Server=postgres;Database=akkabank;Uid=testuser;Pwd=testpass)
  5. View Akka cluster and actor info via Petabridge.Cmd:
    > minikube kubectl -- exec --stdin --tty account-cluster-0 -- /bin/bash
    > dotnet tool run pbm
    > cluster show
    > actor hierarchy
    

Running with Docker

  1. Dependencies: .NET 8, Node.js 18
  2. sh build.sh -t RunDockerApp
  3. Navigate to localhost:3000
  4. If you want to inspect postgres in a dashboard you can visit localhost:5008 (Server=postgres;Database=akkabank;Uid=postgres;Pwd=password)

Running without Docker or K8s

  1. Dependencies: .NET 8, Node.js 18, PostgreSQL & psql
  2. Create a database (Server=localhost;Database=akkabank;Uid=postgres;Pwd=password)
  3. Seed the database: psql postgres < Infrastructure/Migrations/*.sql
  4. cd into ./Web, ./Account.Service, ./Scheduler.Service, & ./MockThirdPartyBankTransferReceiver & dotnet run in each
  5. cd into ./UI and npm run build or npm start

Deploying to Azure AKS

  1. Dependencies: .NET 8, Azure CLI, Pulumi, Node.js 18
  2. sh build.sh -t DeployAllStaging (You will be prompted to sign in to Pulumi & Azure CLI)
  3. One pulumi stack of Azure AKS resources and another Pulumi stack for K8s resources will be created. A Pulumi ESC staging environment will be created and app environment configuration will be set. Your local kubeconfig file will be modified to include details needed to connect to the AKS cluster. See kubectl get all --namespace akkabank & kubectl get all --namespace app-routing-system. App images are currently being pulled from my public docker hub repos. Ingress is partially configured - An IP will be exported to the console when Pulumi finishes creating resources.

Running tests

  1. sh build.sh -t Test

Archive

Inspiration for this project stemmed from reading Functional Programming in C# by Enrico Buonanno.

The first iteration of this project (see CSharpWithLanguageExt directory) expands on Enrico Buonanno's banking account example actor and domain logic to include additional business use cases as well as integration with more tech such as EventStoreDB and the de facto library for functional programming in C#, language-ext.

The second iteration (see FSharpWithAkka directory) is close to a one-to-one representation of the CSharpWithLanguageExt directory, with all use cases rewritten in F# and Paul Louth's echo-process actor library replaced with Akka. I saw that F#'s type inference, computation expressions and immutable data structures made writing programs with typed functional programming more second nature than with C# so I decided to continue with it for the final iteration.

Additional Demonstration

Payments

payments

Employee Card Management & Employee History

card-purchase-limits-and-nickname card-lock-employee-history employee-history employee-management

Transfers within an org & between orgs on the platform

transfer-internal

Transactions

transactions-money-flow transactions-transfers transactions-initiated-by transactions-employee-card transactions-category

Domestic transfers to a mock 3rd party bank server with circuit breaker integration:

bank-domestic-transfer-1-30