public async Task DownloadAsync(FileModel fileModel, Stream output, long from = 0, long to = 0, CancellationToken cancellationToken = default(CancellationToken)) { if (to == 0) { to = fileModel.Length - 1; } var fileLocator = await FileStore.FileLocatorGetAsync(fileModel.Identifier); var evt = new FileDownloadEvent { FileIdentifier = fileModel.Identifier }; evt.Populate(fileModel); await EventSender.SendAsync(evt); await BackendClient.ReadFileAsync( await LoadConfigurationAsync(fileModel.Identifier as OrganizationIdentifier), fileLocator, output, from, to, fileModel.Length, cancellationToken ); }
public async Task <bool> UploadData( [GraphQLNonNullType] UploadDataInput input, [Service] IUploadDataRepository repo, [Service] IEventSender eventSender ) { try { var dataobj = repo.UploadData(input.encodedData, input.encodedConfig); foreach (var sensorId in dataobj.sensorIds) { await eventSender.SendAsync(new OnDataInsert( sensorId, new CreatedDataValues() { sensorId = sensorId, fromDate = dataobj.fromDate, toDate = dataobj.toDate } )).ConfigureAwait(true); } return(true); } catch { throw new QueryException(ErrorBuilder.New().SetMessage("There occured an error with either with encoded file string or the parser type given.").Build()); } }
public async Task <Book> AddBook(AddBookInput book, [Service] IEventSender eventSender) { var newBook = _bookService.Add(book); await eventSender.SendAsync(new OnBookAddedMessage(newBook)); return(newBook); }
public async Task <Review> CreateReview(Episode episode, Review review, [Service] IEventSender eventSender) { _repository.AddReview(episode, review); await eventSender.SendAsync(new OnReviewMessage(episode, review)); return(review); }
public async Task <ValidatorResult <TResponse> > ValidateAsync <TRequest, TResponse, TFluentValidator>(TRequest request, IToasterEvent toasterEvent, CancellationToken cancellationToken = default) where TRequest : new() where TResponse : BaseResponse, new() where TFluentValidator : AbstractValidator <TRequest>, new() { var response = new TResponse(); var fluentValidator = new TFluentValidator(); var result = new ValidatorResult <TResponse>(); var validation = await fluentValidator.ValidateAsync(request, cancellationToken); if (!validation.IsValid) { response.Succeeded = false; foreach (var failure in validation.Errors) { response.Errors.Add(failure.ErrorMessage); } await _eventSender.SendAsync(toasterEvent.TransformInFailure()); result.Failed = true; result.Response = new BadRequestObjectResult(response); return(result); } response.Succeeded = true; result.Response = new OkObjectResult(response); return(result); }
public async Task <Customer> AddCustomer([Service] Store store, [Service] IEventSender eventSender, Customer customer) { store.AddCustomer(customer); await eventSender.SendAsync(new OnAddCustomerMessage(customer)); return(customer); }
public async Task <int> SaveAsync(IToasterEvent toasterEvent, int expectedResult = 1) { var result = await _context.SaveChangesAsync(); if (result == expectedResult) { var success = EventBuilder.BuildToasterEvent(toasterEvent); await _eventSender.SendAsync(success.ToJson()); } else { var failure = toasterEvent.TransformInFailure(); await _eventSender.SendAsync(failure); } return(result); }
public async Task <CreateCustomerAndOrders_Output> CreateCustomerAndOrdersTxn(CreateCustomerAndOrders_Input input, [Service] IEventSender eventSender) { CreateCustomerAndOrders_Output output = await new CreateCustomerAndOrdersTxn().Execute(input); if (output.resultConfirmation.ResultPassed) { await eventSender.SendAsync(new OnEventMessageDefault <Customer>(eventName : "onCustomerCreated", argumentTag : "id", argumentValue : "any", outputType : output.customer)); } return(output); }
public static async Task Run( [QueueTrigger("highbush-automation-queue", Connection = "AzureWebJobsStorage")] IotEvent iotEvent, [Inject] IEventSender eventSender, ILogger log) { log.LogInformation($"C# Queue trigger function processed: {iotEvent}"); log.LogInformation($"Event type: {iotEvent.DoorEvent.DoorEventType}"); string topicName = Environment.GetEnvironmentVariable("EventGridTopicEndpoint"); string topicKey = Environment.GetEnvironmentVariable("EventGridTopicKey"); await eventSender.SendAsync(iotEvent.DoorEvent, topicName, topicKey); }
public async Task <Todo> Add( TodoInput input, [Service] IEventSender eventSender) { var todo = new Todo(Guid.NewGuid(), input.Title, input.Status); await _todoRepository.Add(todo); await eventSender.SendAsync(new OnTodoAdded(todo)); return(todo); }
public Task SubscribeOneConsumer_SendMessage_ConsumerReceivesMessage() { return(TryTest(async() => { // arrange var cts = new CancellationTokenSource(30000); var eventDescription = new EventDescription( Guid.NewGuid().ToString()); // act IEventStream consumer = await _registry .SubscribeAsync(eventDescription); var outgoing = new EventMessage(eventDescription, "bar"); await _sender.SendAsync(outgoing); // assert IEventMessage incoming = await consumer.ReadAsync(cts.Token); Assert.Equal(outgoing.Payload, incoming.Payload); })); }
public async Task <AddOrdersToCustomerTxn_Output> AddOrdersToCustomerTxn(AddOrdersToCustomerTxn_Input input, [Service] IEventSender eventSender) { AddOrdersToCustomerTxn_Output output = await new AddOrdersToCustomerTxn().Execute(input); if (output.resultConfirmation.ResultPassed) { await eventSender.SendAsync(new OnEventMessageDefault <List <Order> >(eventName : "onOrdersAdded", argumentTag : "customerId", argumentValue : output.customer.CustomerId.ToString(), outputType : output.customer.Orders)); } return(output); }
/// <summary> /// Creates a review for a given Star Wars episode. /// </summary> public async Task <CreateReviewPayload> CreateReview( CreateReviewInput input, [Service] IReviewRepository repository, [Service] IEventSender eventSender) { var review = new Review(input.Stars, input.Commentary); repository.AddReview(input.Episode, review); await eventSender.SendAsync(new OnReviewMessage(input.Episode, review)); return(new CreateReviewPayload(input.Episode, review)); }
public async Task <Book> CreateBook(CreateBookInput inputBook, [Service] IEventSender eventSender) { var book = _bookService.Create(inputBook); await eventSender.SendAsync(new OnReviewMessage(new Review() { BookId = book.Id, Stars = 1, Commentary = "Default comment created" } )); await eventSender.SendAsync(new OnReviewMessageWithBookId(book.Id, new Review() { BookId = book.Id, Stars = 1, Commentary = "Default comment created" } )); return(book); }
protected virtual async Task FireEvent(EventBase e, TIdentifier identifier) { if (e != null) { if (e is IHasIdentifier <TIdentifier> ) { ((IHasIdentifier <TIdentifier>)e).Identifier = identifier; } await EventSender.SendAsync(e); } }
public async Task <MoveResult> Move( MoveInput input, [Service] IGameManager gameManager, [Service] IEventSender eventSender, CancellationToken cancellationToken ) { MoveResult result = await gameManager.Move(input.ToMove(), cancellationToken); if (result.IsValid) { await eventSender.SendAsync(new OnMoveMessage(result.Move)); } return(result); }
public async Task <BookReview> CreateBookReview( [Service] IEventSender eventSender, [Service] IBookReviewRepository repository, CreateBookReviewInput input ) { var bookReview = repository.Create(new BookReview { BookId = input.BookId, Name = input.Name, Title = input.Title, Content = input.Content }); await eventSender.SendAsync(new OnBookReviewAddedMessage(input.BookId, bookReview)); return(bookReview); }
public async Task <SearchResults> FileSearch(SearchRequest searchRequest) { searchRequest.Paging = searchRequest.Paging ?? new PagingArguments { PageSize = 100, PageIndex = 0 }; var results = await this.Search.Search( SecurityContext.SecurityIdentifiers, searchRequest ); await EventSender.SendAsync(new SearchEvent { DebugQuery = results.DebugQuery, SearchRequest = searchRequest }); return(new SearchResults { Rows = results.Rows .Select(r => new IndexedItem { FileIdentifier = r.FileIdentifier, Name = r.Name, MimeType = r.MimeType, Extension = r.Extension, Metadata = r.Metadata, Fields = r.Fields, Created = r.Created, Modified = r.Modified, Highlights = r.Highlights }), TotalMatches = results.TotalMatches, Facets = results.Facets, DebugQuery = results.DebugQuery }); }
public async Task Setup(Guid sessionId, long templateId, string templateVersionId, Language language, AuthorInfo authorInfo) { if (language == Language.Unspecified) { throw new SessionCannotBeCreatedException("Language must be explicitly specified."); } var templateDescriptor = await _templatesStorageReader.GetTemplateDescriptor(templateId, templateVersionId); var sessionDescriptor = new SessionDescriptor { TemplateId = templateDescriptor.Id, TemplateVersionId = templateDescriptor.VersionId, Language = language, BinaryElementTemplateCodes = templateDescriptor.GetBinaryElementTemplateCodes() }; var request = new PutObjectRequest { BucketName = _filesBucketName, Key = sessionId.AsS3ObjectKey(Tokens.SessionPostfix), CannedACL = S3CannedACL.PublicRead, ContentType = ContentType.Json, ContentBody = JsonConvert.SerializeObject(sessionDescriptor, SerializerSettings.Default) }; var expiresAt = SessionDescriptor.CurrentTime().Add(_sessionExpiration); var metadataWrapper = MetadataCollectionWrapper.For(request.Metadata); metadataWrapper.Write(MetadataElement.ExpiresAt, expiresAt); metadataWrapper.Write(MetadataElement.Author, authorInfo.Author); metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin); metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName); await _eventSender.SendAsync(_sessionsTopicName, new SessionCreatingEvent(sessionId, expiresAt)); await _cephS3Client.PutObjectAsync(request); _createdSessionsMetric.Inc(); }
public async Task Subscribe() { // arrange var services = new ServiceCollection(); services.AddRedisSubscriptionProvider(_configuration); IServiceProvider serviceProvider = services.BuildServiceProvider(); var cts = new CancellationTokenSource(30000); string name = "field_" + Guid.NewGuid().ToString("N"); IQueryExecutor executor = SchemaBuilder.New() .AddServices(serviceProvider) .AddQueryType(d => d .Name("foo") .Field("a") .Resolver("b")) .AddSubscriptionType(d => d.Name("bar") .Field(name) .Resolver("baz")) .Create() .MakeExecutable(); var eventDescription = new EventDescription(name); // act IExecutionResult result = executor.Execute( "subscription { " + name + " }"); var outgoing = new EventMessage(eventDescription, "bar"); await _sender.SendAsync(outgoing); // assert var stream = (IResponseStream)result; IReadOnlyQueryResult message = await stream.ReadAsync(cts.Token); Assert.Equal("baz", message.Data.First().Value); stream.Dispose(); }
private async Task <string> PutObject( long id, string versionId, AuthorInfo authorInfo, IEnumerable <IObjectElementDescriptor> currentObjectElements, IObjectDescriptor objectDescriptor) { PreprocessObjectElements(objectDescriptor.Elements); await VerifyObjectElementsConsistency(id, objectDescriptor.Language, objectDescriptor.Elements); var metadataForBinaries = await RetrieveMetadataForBinaries(id, currentObjectElements, objectDescriptor.Elements); await _eventSender.SendAsync(_objectEventsTopic, new ObjectVersionCreatingEvent(id, versionId)); var totalBinariesCount = 0; PutObjectRequest putRequest; MetadataCollectionWrapper metadataWrapper; foreach (var elementDescriptor in objectDescriptor.Elements) { var(elementPersistenceValue, binariesCount) = ConvertToPersistenceValue(elementDescriptor.Value, metadataForBinaries); var elementPersistenceDescriptor = new ObjectElementPersistenceDescriptor(elementDescriptor, elementPersistenceValue); totalBinariesCount += binariesCount; putRequest = new PutObjectRequest { Key = id.AsS3ObjectKey(elementDescriptor.Id), BucketName = _bucketName, ContentType = ContentType.Json, ContentBody = JsonConvert.SerializeObject(elementPersistenceDescriptor, SerializerSettings.Default), CannedACL = S3CannedACL.PublicRead }; metadataWrapper = MetadataCollectionWrapper.For(putRequest.Metadata); metadataWrapper.Write(MetadataElement.Author, authorInfo.Author); metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin); metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName); await _s3Client.PutObjectAsync(putRequest); } var objectKey = id.AsS3ObjectKey(Tokens.ObjectPostfix); var objectVersions = await _objectsStorageReader.GetObjectLatestVersions(id); var elementVersions = objectVersions.Where(x => !x.Id.EndsWith(Tokens.ObjectPostfix)).ToList(); var objectPersistenceDescriptor = new ObjectPersistenceDescriptor { TemplateId = objectDescriptor.TemplateId, TemplateVersionId = objectDescriptor.TemplateVersionId, Language = objectDescriptor.Language, Properties = objectDescriptor.Properties, Elements = elementVersions }; putRequest = new PutObjectRequest { Key = objectKey, BucketName = _bucketName, ContentType = ContentType.Json, ContentBody = JsonConvert.SerializeObject(objectPersistenceDescriptor, SerializerSettings.Default), CannedACL = S3CannedACL.PublicRead }; metadataWrapper = MetadataCollectionWrapper.For(putRequest.Metadata); metadataWrapper.Write(MetadataElement.Author, authorInfo.Author); metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin); metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName); metadataWrapper.Write( MetadataElement.ModifiedElements, string.Join(Tokens.ModifiedElementsDelimiter.ToString(), objectDescriptor.Elements.Select(x => x.TemplateCode))); await _s3Client.PutObjectAsync(putRequest); _referencedBinariesMetric.Inc(totalBinariesCount); objectVersions = await _objectsStorageReader.GetObjectLatestVersions(id); return(objectVersions.Where(x => x.Id.EndsWith(Tokens.ObjectPostfix)) .Select(x => x.VersionId) .Single()); }
public async Task <string> SendFoo([Service] IEventSender sender) { await sender.SendAsync(new EventMessage("foo")); return("sendBar"); }
public async Task <LoadChatAndUpdateUnseenForUserTxn_Output> Execute(LoadChatAndUpdateUnseenForUserTxn_Input input, MVCDbContext contextFather = null, bool autoCommit = true, IEventSender eventSender = null, IEventRegistry eventRegistry = null) { LoadChatAndUpdateUnseenForUserTxn_Output output = new LoadChatAndUpdateUnseenForUserTxn_Output(); output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "TXN_NOT_STARTED"); // Error handling bool error = false; // To Handle Only One Error DateTime nowUTC = DateTime.UtcNow; List <notification> notifications = new List <notification>(); List <comment> allSeen = new List <comment>(); try { MVCDbContext contextMGT = (contextFather != null) ? contextFather : new MVCDbContext(); // An using statement is in reality a try -> finally statement, disposing the element in the finally. So we need to take advance of that to create a DBContext inheritance try { // DBContext by convention is a UnitOfWork, track changes and commits when SaveChanges is called // Multithreading issue: so if we use only one DBContext, it will track all entities (_context.Customer.Add) and commit them when SaveChanges is called, // No Matter what transactions or client calls SaveChanges. // Note: Rollback will not remove the entities from the tracker in the context. so better dispose it. //***** 0. Make The Validations - Be careful : Concurrency. Same name can be saved multiple times if called at the exact same time. Better have an alternate database constraint // Call database to validate ChatId and UserId existance or just try to execute the query and if it fails is because one of those is wrong chat chatDb = await contextMGT.Chat .Where(x => x.chatId == input.Chat.chatId) .Where(x => x.participants.Any(y => y.userAppId.Equals(input.User.userAppId))) .FirstOrDefaultAsync(); if (chatDb == null) { error = true; output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "USER_NOT_AUTHORIZED_ERROR", _ResultDetail: ""); return(output); } if (!error) //***** 1. Retrieve the unseen Comments (Atomic because is same Context DB) { // Get the N unseen comments if any bool someAllseen = false; output.Comments = await contextMGT.Comment .Where(x => x.chatId == chatDb.chatId) .Where(x => x.commentsInfo.Any(y => y.userAppId.Equals(input.User.userAppId) && y.seen == false)) .OrderBy(o => o.commentId) .Take(input.Take) .ToListAsync(); if (output.Comments.Count() > 0) { // Update the commentsInfo to the context List <int> keys = output.Comments.Select(y => y.commentId).ToList(); List <commentInfo> details = await contextMGT.CommentInfo .Where(x => keys.Contains(x.commentId)) .Where(x => x.userAppId.Equals(input.User.userAppId)) .ToListAsync(); details.ForEach(x => { x.seen = true; x.seenAt = nowUTC; }); contextMGT.CommentInfo.UpdateRange(details); // Commit? Yes I need it for the next step await contextMGT.SaveChangesAsync(); // allSeen = await contextMGT.Comment .Include(i => i.commentsInfo) .Where(x => keys.Contains(x.commentId)) .Where(x => x.commentsInfo.Count() == x.commentsInfo.Count(y => y.seen == true)) .ToListAsync(); if (allSeen.Count() > 0) { someAllseen = true; allSeen.ForEach(x => x.seenByAll = true); contextMGT.UpdateRange(allSeen); await contextMGT.SaveChangesAsync(); } } else // Get the N newest seen comments if any { output.Comments = await contextMGT.Comment .Where(x => x.chatId == chatDb.chatId) .OrderByDescending(o => o.commentId) .Take(input.Take) .OrderBy(o => o.commentId) // Reorder .ToListAsync(); } //***** 4. Save and Commit to the Database (Atomic because is same Context DB) if (!error && autoCommit) { // This commit returns the user from Database and updates input.Comment await contextMGT.SaveChangesAsync(); // Call it only once so do all other operations first } /* * // Save the notifications - No need to? * * String chatGroup = (chatDb.Participants.Count > 1) ? chatDb.Name : ""; */ if (someAllseen) { // Send the message for himself too, it's the way to know which message has been seen by all List <comment> CommentsIds = (from ids in allSeen select new comment { commentId = ids.commentId, chatId = ids.chatId, seenByAll = ids.seenByAll }).ToList(); // Create a Notification for each user var queryNotification = from user in contextMGT.Participant where user.chatId == chatDb.chatId // where user.UserAppId != input.User.UserAppId // Send the message for himself too, because this include previous all seen messages select new notification { notificationId = 0, type = "CommentSeen", title = "*CommentSeen*", subtitle = "", body = JsonConvert.SerializeObject(CommentsIds), message = "COMMENTS_SEEN", toUserAppId = user.userAppId, route = "Comment", routeAction = "Seen", routeId = user.chatId.ToString(), createdAt = nowUTC, seen = false }; notifications = queryNotification.ToList(); // Save the Notifications to the context - No need to. //contextMGT.Notification.AddRange(notifications); } if (!error && autoCommit) { // This commit returns the user from Database and updates input.Comment await contextMGT.SaveChangesAsync(); // Call it only once so do all other operations first } //***** 5. Execute Send e-mails or other events once the database has been succesfully saved //***** If this task fails, there are options -> 1. Retry multiple times 2. Save the event as Delay, 3.Rollback Database, Re //***** 6. Confirm the Result (Pass | Fail) If gets to here there are not errors then return the new data from database output.ResultConfirmation = resultConfirmation.resultGood(_ResultMessage: "COMMENTS_SUCESSFULLY_SEEN"); // If OK }// if (!error) if (!error) // Send the notification to the subscriptors { // Send the notification to each user * New Logic * foreach (var notification in notifications) { var result = eventSender.SendAsync(new OnEventMessageDefault <notification>(eventName: "onNotificationToUser", argumentTag: "userAppId", argumentValue: notification.toUserAppId, outputType: notification)); } } } finally { // If the context Father is null the context was created on his own, so dispose it if (contextMGT != null && contextFather == null) { contextMGT.Dispose(); } } } catch (Exception ex) // Main try { System.Diagnostics.Debug.WriteLine("Error: " + ex.Message); string innerError = (ex.InnerException != null) ? ex.InnerException.Message : ""; System.Diagnostics.Debug.WriteLine("Error Inner: " + innerError); output = new LoadChatAndUpdateUnseenForUserTxn_Output(); // Restart variable to avoid returning any already saved data output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "EXCEPTION", _ResultDetail: ex.Message); } finally { // Save Logs if needed } return(output); }
public async Task <AddCommentToChatTxn_Output> Execute(AddCommentToChatTxn_Input input, MVCDbContext contextFather = null, bool autoCommit = true, IEventSender eventSender = null, IEventRegistry eventRegistry = null) { AddCommentToChatTxn_Output output = new AddCommentToChatTxn_Output(); output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "TXN_NOT_STARTED"); // Error handling bool error = false; // To Handle Only One Error DateTime nowUTC = DateTime.UtcNow; List <notification> notifications = new List <notification>(); try { MVCDbContext contextMGT = (contextFather != null) ? contextFather : new MVCDbContext(); // An using statement is in reality a try -> finally statement, disposing the element in the finally. So we need to take advance of that to create a DBContext inheritance try { // DBContext by convention is a UnitOfWork, track changes and commits when SaveChanges is called // Multithreading issue: so if we use only one DBContext, it will track all entities (_context.Customer.Add) and commit them when SaveChanges is called, // No Matter what transactions or client calls SaveChanges. // Note: Rollback will not remove the entities from the tracker in the context. so better dispose it. //***** 0. Make The Validations - Be careful : Concurrency. Same name can be saved multiple times if called at the exact same time. Better have an alternate database constraint // Call database to validate ChatId and UserId existance or just try to execute the query and if it fails is because one of those is wrong /* * Chat chatDb = await contextMGT.Chat.Where(x => x.ChatId == input.Comment.ChatId).FirstOrDefaultAsync(); * * if (chatDb == null) * { * error = true; * output.ResultConfirmation = ResultConfirmation.resultBad(_ResultMessage: "CHAT_DOES_NOT_EXIST_ERROR", _ResultDetail: ""); * } */ // Call Database to validate that: 1. ChatId exists 2. User Exists 3. User is part of the Company 4. User is Participant of the Chat chat chatDb0 = await contextMGT.Chat.Include(o => o.participants) .Where(x => x.chatId == input.Comment.chatId) .Where(x => x.participants.Any(y => y.userAppId.Equals(input.Comment.userAppId))) .FirstOrDefaultAsync(); chat chatDb = await contextMGT.Chat .Where(x => x.chatId == input.Comment.chatId) .Where(x => x.participants.Any(y => y.userAppId.Equals(input.Comment.userAppId))) .Include(o => o.participants) //.ThenInclude(i => i.User) .FirstOrDefaultAsync(); /* * var blogs = context.Blogs * .Include(blog => blog.Posts) * .ThenInclude(post => post.Author) * .ThenInclude(author => author.Photo) * .ToList(); */ //.Where(x => x.ChatId == input.Comment.ChatId) ; // 1. ChatId exists if (chatDb == null) { error = true; output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "USER_NOT_AUTHORIZED"); } // Find and validate user. Future: Create a transaction userApp userApp = await contextMGT.UserApp.Where(x => x.userAppId.Equals(input.Comment.userAppId)).FirstOrDefaultAsync(); if (userApp == null) { error = true; output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "USER_NOT_FOUND"); } if (!error) { //***** 1. Create the Comment (Atomic because is same Context DB) // Update the Chat chatDb.updatedAt = nowUTC; contextMGT.Chat.Update(chatDb); // Create the Chat To Save input.Comment.commentId = 0; input.Comment.createdAt = DateTime.UtcNow; // Create and Save the CommentInfo for each user. var query = from user in chatDb.participants where !user.userAppId.Equals(input.Comment.userAppId) select new commentInfo { commentInfoId = 0, commentId = 0, createdAt = nowUTC, delivered = false, seen = false, userAppId = user.userAppId }; // the current user must be Seen = True; SeenAt = NowUTC commentInfo ThisUser = new commentInfo { commentInfoId = 0, commentId = 0, createdAt = nowUTC, delivered = false, seen = true, seenAt = nowUTC, userAppId = input.Comment.userAppId }; input.Comment.commentsInfo = new List <commentInfo>(); input.Comment.commentsInfo = query.ToList(); input.Comment.commentsInfo.Add(ThisUser); // Save the chat to the context contextMGT.Comment.Add(input.Comment); //***** 4. Save and Commit to the Database (Atomic because is same Context DB) if (!error && autoCommit) { // This commit returns the user from Database and updates input.Comment await contextMGT.SaveChangesAsync(); // Call it only once so do all other operations first } // Save the notifications String chatGroup = (chatDb.participants.Count > 1) ? chatDb.name : ""; // Send to everyone except to himself var queryNotification = from user in chatDb.participants where user.userAppId != userApp.userAppId select new notification { notificationId = 0, type = "NewComment", title = "*NewComment*", subtitle = chatGroup, body = chatGroup + " *has a new comment from* " + userApp.userName, message = input.Comment.message, toUserAppId = user.userAppId, route = "Comment", routeAction = "New", routeId = input.Comment.commentId.ToString(), createdAt = nowUTC, seen = false }; notifications = queryNotification.ToList(); // Save the Notifications to the context contextMGT.Notification.AddRange(notifications); if (!error && autoCommit) { // This commit returns the user from Database and updates input.Comment await contextMGT.SaveChangesAsync(); // Call it only once so do all other operations first } //***** 5. Execute Send e-mails or other events once the database has been succesfully saved //***** If this task fails, there are options -> 1. Retry multiple times 2. Save the event as Delay, 3.Rollback Database, Re //***** 6. Confirm the Result (Pass | Fail) If gets to here there are not errors then return the new data from database output.ResultConfirmation = resultConfirmation.resultGood(_ResultMessage: "COMMENT_SUCESSFULLY_CREATED"); // If OK output.Comment = input.Comment; }// if (!error) if (!error) // Send the notification to the subscriptors { // Create a Notification Queue //var result = eventSender.SendAsync(new OnEventMessageDefault<Comment>(eventName: "onCommentAddedToChat", argumentTag: "chatId", argumentValue: output.Comment.ChatId.ToString(), outputType: output.Comment)); // Send the notification to each user * New Logic * foreach (var notification in notifications) { var result = eventSender.SendAsync(new OnEventMessageDefault <notification>(eventName: "onNotificationToUser", argumentTag: "userAppId", argumentValue: notification.toUserAppId, outputType: notification)); } /* * String chatGroup = (chatDb.Participants.Count > 1) ? " @ " + chatDb.Name : ""; * * int countDelivered = 0; * foreach (var user in chatDb.Participants) * { * String message = output.Comment.Message + " Mr. " + user.UserAppId; * * message = userApp.UserName + " Says " + output.Comment.Message + chatGroup; * Notification notification = new Notification { NotificationId = 0, Created = nowUTC, Message = message }; * var result = eventSender.SendAsync(new OnEventMessageDefault<Notification>(eventName: "onNotificationToUser", argumentTag: "userAppId", argumentValue: user.UserAppId, outputType: notification)); * * if (result.IsCompletedSuccessfully) * { * countDelivered++; * } * * * } */ // } } finally { // If the context Father is null the context was created on his own, so dispose it if (contextMGT != null && contextFather == null) { contextMGT.Dispose(); } } } catch (Exception ex) // Main try { System.Diagnostics.Debug.WriteLine("Error: " + ex.Message); string innerError = (ex.InnerException != null) ? ex.InnerException.Message : ""; System.Diagnostics.Debug.WriteLine("Error Inner: " + innerError); output = new AddCommentToChatTxn_Output(); // Restart variable to avoid returning any already saved data output.ResultConfirmation = resultConfirmation.resultBad(_ResultMessage: "EXCEPTION", _ResultDetail: ex.Message); } finally { // Save Logs if needed } return(output); }
public async Task <Recipe> InsertRecipe(InsertRecipeInput recipeInput, IEventSender eventSender) { var user = await userRepository.GetUserByIdWithRecipes(recipeInput.UserId); if (user == null) { return(null); } var recipe = new Recipe() { UserId = user.Id, Title = recipeInput.Title, PrepTime = recipeInput.PrepTime, Image = recipeInput.Image, Kcal = recipeInput.Kcal, Protein = recipeInput.Protein, Fat = recipeInput.Fat, Carbs = recipeInput.Carbs }; await recipeRepository.InsertRecipe(recipe); var savedRecipe = await recipeRepository.GetRecipeByTitle(recipe.Title); var foundTags = await tagRepository.GetTagsByNames(recipeInput.Tags.Select(t => t.Name).ToList()); foreach (var inputTag in recipeInput.Tags) { if (foundTags.Any() && foundTags.Select(t => t.Name).Contains(inputTag.Name)) { var existingTag = foundTags.First(t => t.Name == inputTag.Name); var recipeTag = new RecipeTag() { Recipe = savedRecipe, RecipeId = savedRecipe.Id, Tag = existingTag, TagId = existingTag.Id, }; recipe.RecipeTags.Add(recipeTag); existingTag.RecipeTags.Add(recipeTag); } else { var tag = new Tag() { Name = inputTag.Name }; await tagRepository.InsertTag(tag); var savedTag = await tagRepository.GetTagByName(inputTag.Name); var recipeTag = new RecipeTag() { Recipe = savedRecipe, RecipeId = savedRecipe.Id, Tag = savedTag, TagId = savedTag.Id, }; recipe.RecipeTags.Add(recipeTag); savedTag.RecipeTags.Add(recipeTag); } } await recipeRepository.Save(); var userRecipeInfo = new UserRecipeInfo() { UserId = user.Id, UserName = user.Name, RecipeId = savedRecipe.Id, RecipeCount = user.Recipes.Count }; await eventSender.SendAsync(new OnInsertRecipeMessage(user.Id, userRecipeInfo)); return(savedRecipe); }