public UnitOfWorkTest() { transactionOptions = new TransactionOptions(readPreference: ReadPreference.Primary, readConcern: ReadConcern.Local, writeConcern: WriteConcern.WMajority); cancellationToken = CancellationToken.None; clientSessionHandle = Substitute.For <IClientSessionHandle>(); clientSessionHandle .WithTransactionAsync( Arg.Any <Func <IClientSessionHandle, CancellationToken, Task <bool> > >(), Arg.Any <TransactionOptions>(), Arg.Any <CancellationToken>()) .Returns(true); clientSessionHandle .WithTransaction( Arg.Any <Func <IClientSessionHandle, CancellationToken, bool> >(), Arg.Any <TransactionOptions>(), Arg.Any <CancellationToken>()) .Returns(true); mongoClient = Substitute.For <IMongoClient>(); mongoClient.StartSessionAsync().Returns(clientSessionHandle); mongoClient.StartSession().Returns(clientSessionHandle); unitOfWork = new UnitOfWorkMongo.UnitOfWork(mongoClient, transactionOptions); }
public override async Task <IList <TransactionLog> > PerformTransactions( IEnumerable <Transaction <T> > transactions, CancellationToken token = default) { List <Action> adjustBalanceActions = new List <Action>(); using IClientSessionHandle session = await _mongoClient.StartSessionAsync(cancellationToken : token); var transactionLogEntries = await session.WithTransactionAsync(async (sessionInner, tokenInner) => { IList <TransactionLog> logEntries = new List <TransactionLog>(); foreach (Transaction <T> transaction in transactions) { TransactionLog log = await PerformSingleTransaction(transaction, sessionInner, tokenInner); // defer all in-memory adjustments until the end in case any of the transactions failed. adjustBalanceActions.Add(() => _currencyFieldSetter(transaction.User, log.NewBalance)); logEntries.Add(log); } return(logEntries); }, new TransactionOptions(), token); await session.CommitTransactionAsync(token); adjustBalanceActions.ForEach(action => action()); return(transactionLogEntries); }
public async Task ExecuteAsync(Action <BsonDocument, bool, CancellationToken> assertOperationCallback, CancellationToken cancellationToken) { await _session.WithTransactionAsync( callbackAsync : (session, token) => { foreach (var operationItem in _operations) { assertOperationCallback(operationItem.AsBsonDocument, true, token); } return(Task.FromResult <object>(null)); }, transactionOptions : _options, cancellationToken : cancellationToken); }
public async Task <IImmutableList <Badge> > TransferBadges( IImmutableList <Badge> badges, string?recipientUserId, string reason, IDictionary <string, object?> additionalData) { Instant now = _clock.GetCurrentInstant(); List <Badge> updatedBadges = new(); using (IClientSessionHandle sessionOuter = await Collection.Database.Client.StartSessionAsync()) { await sessionOuter.WithTransactionAsync(async (txSession, txToken) => { foreach (Badge badge in badges) { Badge updatedBadge = await TransferBadge(badge, recipientUserId, txSession, txToken); Debug.Assert(badge.Id == updatedBadge.Id); updatedBadges.Add(updatedBadge); } foreach (Badge badge in badges) { await _badgeLogRepo.LogWithSession( badge.Id, reason, recipientUserId, now, additionalData, txSession); } return((object?)null); }); } foreach (var tpl in badges.Select(b => (b.UserId, b.Species)).Distinct()) { (string?previousOwnerUserId, PkmnSpecies species) = tpl; if (previousOwnerUserId != null && !await HasUserBadge(previousOwnerUserId, species)) { UserLostBadgeSpecies?.Invoke(this, new UserLostBadgeSpeciesEventArgs(previousOwnerUserId, species)); } } return(updatedBadges.ToImmutableList()); }
public Task <TResult> WithTransactionAsync <TResult>(Func <IClientSessionHandle, CancellationToken, Task <TResult> > callbackAsync, TransactionOptions?transactionOptions = null, CancellationToken cancellationToken = default) { return(_sessionHandle.WithTransactionAsync(callbackAsync, transactionOptions, cancellationToken)); }