public void Close() { lock (ConcurrencyLock) { _state = BankAccountState.Closed; } }
public void Open() { lock (ConcurrencyLock) { _state = BankAccountState.Open; } }
public BankAccount(long id, String number, Decimal balance, OverdraftPolicy overdraftPolicy, BankAccountState state) { this.id = id; this.number = number; this.Balance = balance; this.overdraftPolicy = overdraftPolicy; this.state = state; }
/// <summary> /// Initialize the state. /// TODO: isolate the State object in 3 differnt buckets: base info, operations, standing orders. /// This will improve perf in serialize/deserialize /// </summary> public Task InitializeState(string accountOwner, double openingBalance) { ActorEventSource.Current.ActorMessage(this, "@BankAccount.InitializeState for account '{0}'", Id.GetStringId()); BankAccountState state = new BankAccountState(); state.AccountNumber = Id.GetStringId(); // accountNumber; state.CustomerName = accountOwner; state.Balance = openingBalance; state.LastOperations = new List <Operation>(); state.StandingOrders = new List <StandingOrder>(); // inconditional set of data in instance's state return(StateManager.SetStateAsync("AccountState", state)); }
/// <summary> /// Add a standing order to a given account /// </summary> public async Task AddStandingOrder(string toAccount, double amount, short minute) { ActorEventSource.Current.ActorMessage(this, "@BankAccount.AddStandingOrder for account '{0}', min = {1}", Id.GetStringId(), minute); BankAccountState state = await StateManager.GetStateAsync <BankAccountState>("AccountState"); state.StandingOrders.Add(new StandingOrder { Amount = amount, ToAccountNumber = toAccount, RecurrenceMinute = minute }); StateManager.SetStateAsync("AccountState", state).GetAwaiter().GetResult(); // could have just returned thread here -- testing return; }
/// <summary> /// Actor's Reminder - 1 hearbeat per minute /// </summary> public async Task ReceiveReminderAsync(string reminderName, byte[] context, TimeSpan dueTime, TimeSpan period) { if (reminderName.Equals("process standing orders")) { BankAccountState state = StateManager.GetStateAsync <BankAccountState>("AccountState").GetAwaiter().GetResult(); DateTime now = DateTime.Now; foreach (StandingOrder so in state.StandingOrders) { if (so.RecurrenceMinute == now.Minute) { ActorEventSource.Current.ActorMessage(this, "@BankAccount.ReceiveReminderAsync paying from '{0}' to '{1}': €{2:f2}", Id.GetStringId(), so.ToAccountNumber, so.Amount); // time to pay, says Roy Batty Random r = new Random(); int newOperationId = r.Next(0, int.MaxValue); // remove money from this account state.Balance -= so.Amount; state.LastOperations.Add(new Operation { AccountNumber = so.ToAccountNumber, Amount = -so.Amount, When = now, OperationId = newOperationId }); await StateManager.SetStateAsync("AccountState", state); // test if it can cause issues: mutiple payments in same account/minute? // send money to target account IBankAccount accountProxy = ActorProxy.Create <IBankAccount>(new ActorId(so.ToAccountNumber), "fabric:/SFActors.BankAccounts"); await accountProxy.Transfer(Id.GetStringId(), so.Amount, now, newOperationId); } } } return; }
/// <summary> /// Receive a payment from another Actor or client /// </summary> public async Task <bool> Transfer(string sourceAccount, double amount, DateTime when, int uniqueOperationId) { ActorEventSource.Current.ActorMessage(this, "@BankAccount.Transfer for account '{0}' of {1}", Id.GetStringId(), amount); BankAccountState state = await StateManager.GetStateAsync <BankAccountState>("AccountState"); // idempotency protection for repeated messages foreach (Operation op in state.LastOperations) { if (op.OperationId == uniqueOperationId) { return(false); } } // validate positive amount (we are receiving money) if (amount <= 0) { return(false); } // accept the money :-) state.LastOperations.Add(new Operation { AccountNumber = sourceAccount, Amount = amount, When = when, OperationId = uniqueOperationId }); state.Balance += amount; await StateManager.SetStateAsync("AccountState", state); return(true); }
//------------------------------------------------------------------------- public void ChangeState(BankAccountState aBankAcountState) { AccountState = aBankAcountState; }
public void setState(BankAccountState state) { this.state = state; }
public override BankAccountState ApplyTo(BankAccountState state) => state;
public abstract BankAccountState ApplyTo(BankAccountState state);
public override BankAccountState ApplyTo(BankAccountState state) => state.WithFrozen(false);
public void ChangeState(BankAccountState newState) { AccountState = newState; }
public override BankAccountState ApplyTo(BankAccountState state) => state.WithBalance(AmountDeposited + state.CurrentBalance);