예제 #1
0
        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());
     }
 }
예제 #3
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
            }));
        }
예제 #12
0
        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);
        }
예제 #13
0
        /// <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));
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
            }
        }
예제 #16
0
        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);
        }
예제 #17
0
        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);
        }
예제 #18
0
        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
            });
        }
예제 #19
0
        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();
        }
예제 #21
0
        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");
            }
예제 #23
0
        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);
        }
예제 #24
0
        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);
        }
예제 #25
0
        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);
        }