public async Task CreateFoo(FooDto item) { var doc = _mapper.Map <FooDoc>(item); using (var session = await _client.StartSessionAsync()) { await _collection.InsertOneAsync(session, doc); } }
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); }
private static Task <IClientSessionHandle> GetSessionAsync( IMongoClient client, ClientSessionOptions options, CancellationToken ctok = default) { return(client.StartSessionAsync(options, ctok)); }
public async Task <ITransaction> StartTransaction(CancellationToken token) { var session = await _mongoClient.StartSessionAsync(null, token); session.StartTransaction(); return(new MongoDbTransaction(session)); }
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 <IClientSessionHandle> StartSession(CancellationToken cancellactionToken = default(CancellationToken)) { var session = await _client.StartSessionAsync(cancellationToken : cancellactionToken); Session = session; return(session); }
public async Task <IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) { var session = await _mongoClient.StartSessionAsync(cancellationToken : cancellationToken).ConfigureAwait(false); CurrentTransaction = new MongoDbContextTransaction(session); return(CurrentTransaction); }
public async Task <ITransaction> StartTransactionAsync() { IClientSessionHandle session = await _client.StartSessionAsync(); session.StartTransaction(); return(new MongoTransaction(session)); }
/// <summary> /// Start Transaction /// </summary> public async Task StartTransaction() { _transactionStartDateTime = DateTime.Now; _session = await _client.StartSessionAsync(); _session.StartTransaction(); }
public async Task EnsureSessionCreatedAsync() { if (SessionHandle != null) { return; } SessionHandle = await Client.StartSessionAsync(new ClientSessionOptions { CausalConsistency = false }); }
public async Task <IEnumerable <TodoReadDTO> > GetTodoList() { _logger.LogInformation("Call to GetTodo function was made"); using (var session = await _client.StartSessionAsync()) { try { List <TodoReadDTO> models = new List <TodoReadDTO>(); //var results = await this.Todos.Find<TodoModel>(session, new BsonDocument()).ToListAsync(); var results = await this.Todos.Find <TodoModel>(session, x => true).ToListAsync(); foreach (var item in results) { var modelDTO = _mapper.Map <TodoReadDTO>(item); models.Add(modelDTO); } _logger.LogInformation("Call to GetTodo function completed."); return(models); } catch (Exception ex) { _logger.LogInformation("Call to GetTodo function was terminated."); throw new Exception("Call to GetTodo function was terminated."); } } }
public async Task <ITransaction> StartTransaction(CancellationToken token) { if (_options.SupportTransaction) { _session = await _mongoClient.StartSessionAsync(null, token); _session.StartTransaction(); return(new MongoDbTransaction(_session)); } _session = null; return(new MongoDbTransaction()); }
public async Task <int> SaveChanges() { using (Session = await _client.StartSessionAsync()) { Session.StartTransaction(); var commandTasks = _commands.Select(x => x()); await Task.WhenAll(commandTasks); await Session.CommitTransactionAsync(); } return(_commands.Count); }
public async Task <T> ExecuteInTransaction <T>(Func <IClientSessionHandle, CancellationToken, Task <T> > execute, CancellationToken cancellationToken) { using (var session = await _client.StartSessionAsync(new ClientSessionOptions(), cancellationToken)) { var transactionOptions = new TransactionOptions( readPreference: ReadPreference.Primary, readConcern: ReadConcern.Majority, writeConcern: WriteConcern.W1); return(await session.WithTransactionAsync( execute, transactionOptions, cancellationToken)); } }
public async Task <bool> CommitTransactionAsync() { using (var session = await _mongoClient.StartSessionAsync()) { session.StartTransaction(); var commandTasks = _commands.Select(c => c()); await Task.WhenAll(commandTasks); await session.CommitTransactionAsync(); _commands.Clear(); IsInTransaction = false; } return(_commands.Count > 0); }
private async Task <IClientSessionHandle> CreateSessionAsync(IMongoClient client, CancellationToken cancellationToken = default) { var stopwatch = Logger.StartStopwatch(); Logger.LogInformation($"Start CreateSessionAsync"); var session = await client.StartSessionAsync(cancellationToken : cancellationToken); if (_dbContextOptions.Timeout.HasValue) { session.AdvanceOperationTime(new BsonTimestamp(_dbContextOptions.Timeout.Value)); } session.StartTransaction(); stopwatch?.Stop(); Logger.LogInformation("End CreateSessionAsync, elapsed time: {elapsedTime}", Logger.GetElapsedTime(stopwatch)); stopwatch = null; return(session); }
private static async Task MakeSureDatabaseCreated(IMongoClient mongoDbClient) { try { var database = mongoDbClient.GetDatabase("BookStoreDB"); using (var session = await mongoDbClient.StartSessionAsync()) { var collections = DbCollection.All(); foreach (var collectionName in collections) { if (await database.ExistsCollection(collectionName)) { continue; } await database.CreateCollectionAsync(session, collectionName); } //var bookCollection = database.GetCollection<Book>("Book"); //bookCollection.InsertOne(new Book //{ // Name = "First book", // Author = "Tan Nguyen", // Category = "No name", // CreatedAt = DateTime.Now, // CreatedBy = "Tan" //}); } } catch (Exception e) { Console.WriteLine(e); // // TODO: Handle can't make sure database created throw; } }
public async Task StoreAsync(AuditTrailRecord record, CancellationToken cancellationToken) { var hash = new byte[Sha256.Sha256HashSize]; Sha256.Shared.ComputeHash(record.Raw.Span, hash); SignedTreeHead?signedTreeHead = null; if (_tree != null) { signedTreeHead = await _tree.AppendAsync(hash); } var payload = record.Token.Payload !; // Is it posible to fail here ? MemoryMarshal.TryGetArray(record.Raw, out var segment); var block = new AuditTrailBlock ( iss: payload[JwtClaimNames.Iss.EncodedUtf8Bytes].GetString() !, jti: payload[JwtClaimNames.Jti.EncodedUtf8Bytes].GetString() !, iat: payload[JwtClaimNames.Iat.EncodedUtf8Bytes].GetInt64(), aud: payload[JwtClaimNames.Aud.EncodedUtf8Bytes].GetStringArray() !, txn: payload[SecEventClaimNames.Txn].GetString(), toe: payload[SecEventClaimNames.Toe].GetInt64(), events: payload[SecEventClaimNames.Events.EncodedUtf8Bytes].GetJsonDocument(), raw: segment.Array !, hash: hash, rootHash: signedTreeHead?.Hash ); using var session = await _client.StartSessionAsync(cancellationToken : cancellationToken); try { session.StartTransaction(); await _auditTrails.InsertOneAsync(block, cancellationToken : cancellationToken); //var kid = record.Token.Header[JwtHeaderParameterNames.Kid.EncodedUtf8Bytes].GetString()!; //if (!_keyringInMemory.HasKey(kid)) //{ // var filter = Builders<Keyring>.Filter.Eq("keys.kid", kid); // var storedKey = await _keyring.Find(filter).FirstOrDefaultAsync(cancellationToken); // if (storedKey is null) // { // var key = SerializeKey(record.Token.SigningKey!); // var jwksFilter = Builders<Keyring>.Filter.Eq("iss", record.Issuer); // var push = Builders<Keyring>.Update.Push("keys", key) // .SetOnInsert("iss", record.Issuer); // await _keyring.UpdateOneAsync(jwksFilter, push, new UpdateOptions { IsUpsert = true }, cancellationToken); // } //} await session.CommitTransactionAsync(cancellationToken); } catch (MongoWriteException e) when(e.WriteError.Category == ServerErrorCategory.DuplicateKey) { _logger.LogWarning("Duplicate document. The document will be ignored."); await session.AbortTransactionAsync(); } catch (Exception e) { _logger.LogError(e, "Failed to store the document."); await session.AbortTransactionAsync(); } _logger.LogInformation("'{Jti}' has been recorded.", block.Jti); }
public Task <IClientSessionHandle> StartSessionAsync(ClientSessionOptions?clientSessionOptions = null, CancellationToken cancellationToken = default) => _client.StartSessionAsync(clientSessionOptions, cancellationToken);
public Task <IClientSessionHandle> CreateAsync() { return(_client.StartSessionAsync()); }
public virtual Task <IClientSessionHandle> StartSessionAsync(CancellationToken cancellationToken) { return(Client.StartSessionAsync(cancellationToken: cancellationToken)); }
public Task <IClientSessionHandle> StartSessionAsync( ClientSessionOptions?options = null, CancellationToken cancellationToken = default) { return(_client.StartSessionAsync(options, cancellationToken)); }
/// <inheritdoc /> public async Task <string[]> Delete(string requestingUserId, string directoryId) { using var session = await client.StartSessionAsync(); session.StartTransaction(); try { var deleteResult = await directoryCollection.FindOneAndDeleteAsync(session, x => x.Id == directoryId && x.IsRootDirectory == false && x.Permissions.Any(y => y.Permission.HasFlag(Permission.ReadWrite) && y.UserId == requestingUserId )); // If the result is null permissions are not granted or directory does not exists or is not // deletable in the case of the root directory if (deleteResult == null) { throw new ObjectNotResolvableException( $"Deletion of directory {directoryId} could not be performed by user {requestingUserId}"); } // Find subdirectories and get a list of all files var subDirectories = await directoryCollection .AsQueryable() .Where(x => x.PathIds.Contains(directoryId)) .Select(x => new { Id = x.Id, Files = x.FileIds }) .ToListAsync(); // Delete subdirectories var directoryIds = subDirectories.Select(x => x.Id); var deleteDirectoryTask = directoryCollection.DeleteManyAsync(session, x => directoryIds.Contains(x.Id)); // Delete files var fileIds = subDirectories.SelectMany(x => x.Files).ToArray(); var deleteFilesTask = filesCollection.DeleteManyAsync(session, x => fileIds.Contains(x.Id)); // Get all revisions (in order to remove bucket blobs later on) var revisionIds = await fileRevisionCollection .AsQueryable() .Where(x => fileIds.Contains(x.File)) .Select(x => x.Id) .ToListAsync(); // Delete file revisions var deleteRevisionsTask = fileRevisionCollection.DeleteManyAsync(session, x => fileIds.Contains(x.File)); await Task.WhenAll(deleteDirectoryTask, deleteFilesTask, deleteRevisionsTask); await session.CommitTransactionAsync(); return(revisionIds.ToArray()); } catch (ObjectNotResolvableException) { await session.AbortTransactionAsync(); throw; } catch (InvalidParameterException) { await session.AbortTransactionAsync(); throw; } catch (MongoException e) { await session.AbortTransactionAsync(); throw new DatabaseException("Database error during file inserting. See inner exception.", e); } catch (Exception e) { await session.AbortTransactionAsync(); throw new Exception("Unknown error during file inserting. See inner exception.", e); } }
public async Task BeginTransactionAsync() { _session = await _mongoClient.StartSessionAsync(); _session.StartTransaction(); }
/// <inheritdoc /> public async Task <string[]> Delete(string requestingUserId, string fileId) { using var session = await client.StartSessionAsync(); try { session.StartTransaction(); var directoryUpdate = Builders <DirectoryDto> .Update.Pull(x => x.FileIds, fileId); var updatedDirectoryTask = await directoryCollection.UpdateOneAsync(session, x => x.FileIds.Contains(fileId) && (x.OwnerId == requestingUserId || x.Permissions.Any(y => y.Permission.HasFlag(Permission.ReadWrite) && y.UserId == requestingUserId )), directoryUpdate); if (updatedDirectoryTask.ModifiedCount == 0) { throw new ObjectNotResolvableException( $"Parent directory of file {fileId} could not be found or accessed by user {requestingUserId} during file delete"); } if (updatedDirectoryTask.ModifiedCount > 1) { throw new UnexpectedBehaviourException( $"Delete of file {fileId} by user {requestingUserId} changed {updatedDirectoryTask.ModifiedCount} parent directories but must exactly change 1"); } var revisionsTask = fileRevisionCollection.DeleteManyAsync(session, x => x.File == fileId); var deleteFileTask = filesCollection.FindOneAndDeleteAsync( session, x => x.Id == fileId, new FindOneAndDeleteOptions <FileDto, TempRevisionView> { Projection = Builders <FileDto> .Projection.Include(x => x.RevisionIds) }); await Task.WhenAll(deleteFileTask, revisionsTask); await session.CommitTransactionAsync(); return(deleteFileTask.Result.RevisionIds.ToArray()); } catch (ObjectNotResolvableException) { await session.AbortTransactionAsync(); throw; } catch (UnexpectedBehaviourException) { await session.AbortTransactionAsync(); throw; } catch (MongoException e) { await session.AbortTransactionAsync(); throw new DatabaseException("Database error during file delete. See inner exception.", e); } catch (Exception e) { await session.AbortTransactionAsync(); throw new Exception("Unknown error during file delete. See inner exception.", e); } }
public async Task <SignedTreeHead> AppendAsync(byte[] hash) { MerkleNode leafNode = new MerkleNode(_hasher.HashLeaf(hash)); var session = await _client.StartSessionAsync(); try { //session.StartTransaction(); var root = await _roots.Find(session, _ => true) .Sort(new SortDefinitionBuilder <MerkleRoot>() .Descending(r => r.TreeSize)).Limit(1).SingleOrDefaultAsync(); if (root is null) { MerkleLeaf leaf = new MerkleLeaf(0, _hasher.HashLeaf(hash)); await _leaves.InsertOneAsync(session, leaf); await _nodes.InsertOneAsync(session, leafNode); root = new MerkleRoot(leafNode.Level, leafNode.Hash, 1ul, _signer.Sign(leafNode.Hash), ""); await _roots.InsertOneAsync(session, root); } else { var existingLeaf = await _leaves.Find(session, n => n.Hash == leafNode.Hash).AnyAsync(); if (existingLeaf) { _logger.LogInformation("The leaf {leafHash} already exist in the tree {treeHash}. Nothing was appended.", hash.ByteToHex(), root.Hash.ByteToHex()); return(CreateSignedTreeHead(root)); } else { var nodesToInsert = new List <MerkleNode>(root.Level + 1) { leafNode }; var stack = new Stack <MerkleNode>(root.Level + 1); var currentNode = await _nodes.Find(session, n => n.Hash == root.Hash).SingleAsync(); MerkleNode node; if (currentNode.IsFull) { bool isFullNode = currentNode.Level == leafNode.Level && leafNode.IsFull; node = new MerkleNode(new[] { currentNode.Hash, leafNode.Hash }, currentNode.Level + 1, _hasher.HashNode(currentNode.Hash, leafNode.Hash), isFullNode); nodesToInsert.Add(node); } else { do { var left = await _nodes.Find(session, n => n.Hash == currentNode.Left).SingleAsync(); stack.Push(left); var right = await _nodes.Find(session, n => n.Hash == currentNode.Right).SingleAsync(); currentNode = right; } while (!currentNode.IsFull); stack.Push(currentNode); stack.Push(leafNode); do { var right = stack.Pop(); var left = stack.Pop(); bool isFullNode = left.Level == right.Level && left.IsFull && right.IsFull; node = new MerkleNode(new[] { left.Hash, right.Hash }, left.Level + 1, _hasher.HashNode(left.Hash, right.Hash), isFullNode); nodesToInsert.Add(node); stack.Push(node); } while (stack.Count != 1); } MerkleLeaf leaf = new MerkleLeaf(root.TreeSize, _hasher.HashLeaf(hash)); await _leaves.InsertOneAsync(session, leaf); await _nodes.InsertManyAsync(session, nodesToInsert); root = new MerkleRoot(node.Level, node.Hash, root.TreeSize + 1, _signer.Sign(node.Hash), ""); await _roots.InsertOneAsync(session, root); } } //session.CommitTransaction(); _logger.LogInformation("The leaf {leafHash} was appended to tree {treeHash}.", hash.ByteToHex(), root.Hash.ByteToHex()); return(CreateSignedTreeHead(root)); } catch (Exception e) { //session.AbortTransaction(); _logger.LogError(e, "An error occurred while appending the leaf {leaf}.", hash.ByteToHex()); throw new MerkleTreeException($"An error occurred while appending the leaf {hash.ByteToHex()}.", e); } }
public Task <IClientSessionHandle> CreateAsync() => _client.StartSessionAsync();
public async Task <TResult> WithTransactionAsync <TResult>(Func <IClientSessionHandle, CancellationToken, Task <TResult> > callbackAsync, CancellationToken cancellationToken = default) { using var session = await mongoClient.StartSessionAsync(); return(await session.WithTransactionAsync(callbackAsync, transactionOptions, cancellationToken)); }
public Task <IClientSessionHandle> StartSessionAsync(ClientSessionOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { return(wrapped.StartSessionAsync(options, cancellationToken)); }
/// <inheritdoc /> public async Task <bool> InsertUser(string userId, string rootDirectoryId, string email, string hashedPassword, string salt, string publicKey, string encryptedPrivateKey) { using (var session = await client.StartSessionAsync()) { // Begin transaction session.StartTransaction(); try { var newRootDirectory = new DirectoryDto { Id = rootDirectoryId, IsRootDirectory = true, OwnerId = userId, ObjectName = "__root_dir__", DirectoryIds = new List <string>(), FileIds = new List <string>(), PathIds = new[] { rootDirectoryId }, Permissions = new[] { new BasicPermissionDto { UserId = userId, Permission = Permission.Read | Permission.ReadWrite | Permission.ReadPermissions | Permission.ReadWritePermissions } }, }; var insertRootDirectoryTask = directoryCollection.InsertOneAsync(session, newRootDirectory); var newUser = new UserDto { Id = userId, RootDirectory = newRootDirectory.Id, Email = email, PasswordHash = hashedPassword, Salt = salt, PublicKey = publicKey, EncryptedPrivateKey = encryptedPrivateKey }; var insertUserTask = userCollection.InsertOneAsync(session, newUser); await Task.WhenAll(insertRootDirectoryTask, insertUserTask); await session.CommitTransactionAsync(); } catch (MongoException e) { await session.AbortTransactionAsync(); throw new DatabaseException("Database error during user creating. See inner exception.", e); } catch (Exception e) { await session.AbortTransactionAsync(); throw new Exception("Unknown error during file inserting. See inner exception.", e); } } return(true); }