If you don't know C# but you are familiar with the actor model please read my problem below as it is more about architecture and data management.
I'm a very junior C# developer and trying to understand what the actor model is. I'm kind of done with it but it's left one point that I cannot get.
Before I tell you a problem let me describe the context in order to provide you with better undersrtanding.
As a test example I want to build an app for an imaginary bank. I'm going to implement this application by using both akka.net and Orleans on learning purpose and to be able to compare them.
Use cases:
- As a user I want to be able to create a new account;
- As a user I want to be able to login to the app using my account unique number;
- As a user I want to be able to deposit money to my account;
- As a user I want to be able to select another user and transfer a specified sum of money to their account;
- As a user I want to be able to withdraw a sum of money from my account.
So, there are the following entities:
- User;
- Account.
Identifying one to one relationship between the user and their account. I'm going to use ORM to store this data in my Database. Obviously the models look something like this:
public class User
{
public Guid Id { get; set; }
public string FullName { get; set; }
....
}
public class Account
{
public Guid Id { get; set; }
public string UniqueNumber { get; set; }
public string Balance { get; set; }
...
}
And I also want to have two actors/grains:
- AccountActor;
- TransactionService;
Their interfaces:
//Or IAccountGrain
public interface IAccountActor
{
void Deposit(Money amount);
void Withdraw(Money amount);
}
//Or ITransactionGrain
public interface ITransactionActor
{
void Transfer(IAccountActor from, IAccountActor to, Money amount);
}
The thing that I don't understand is how to treat the data in the relation database. Let's imagine the following scenario:
50 users are online and vigorously making request via the client app to the REST API of the app. They are withdrawing, depositing and transferring money almost without any pauses.
The question is:
- Should I create one actor per user account? I'm pretty sure that I need because how then I can implement thousands of transactions between different accounts.
- How can I associate the user account with the AccountActor? Is it correct If I load the data from database using repository before actor's activation/start and set up the state?
And the main problem: How to save state back to the database?
Let's image an account A that has 1000$. And It occurs about 100 transactions initiated by the users where this account is involved. Account A changes its state from message to message.
What is the best approach to save these changes to database? I read that If I use calls to the database directly from the actor, I will lose all the benefits because of blocked operations.
Should I create one more actor to process messages from other actors and writes changes to database using repositories?
I mean I can send from AccountActor messages about the account changes to the new actor where I will call the appropriate repository. But, Isn't it a bottleneck? Let's imagine 1000 users online and about 100 000 transactions between accounts. Then the actor that is responsible for saving accounts changes to the database can have too many messages to process.
Sorry for the long text. I tried to find examples of applications that use Orleans or Akka.net but I haven't found anything what utilizes a database.
Thank you for you attention.