private void PublishExceptionAsync(ProcessingCommand processingCommand, IPublishableException exception, int retryTimes) { _ioHelper.TryAsyncActionRecursively("PublishExceptionAsync", () => _exceptionPublisher.PublishAsync(exception), currentRetryTimes => PublishExceptionAsync(processingCommand, exception, currentRetryTimes), result => { CompleteCommand(processingCommand, CommandStatus.Failed, exception.GetType().Name, (exception as Exception).Message); }, () => { var serializableInfo = new Dictionary <string, string>(); exception.SerializeTo(serializableInfo); var exceptionInfo = string.Join(",", serializableInfo.Select(x => string.Format("{0}:{1}", x.Key, x.Value))); return(string.Format("[commandId:{0}, exceptionInfo:{1}]", processingCommand.Message.Id, exceptionInfo)); }, errorMessage => { _logger.Fatal(string.Format("Publish event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage)); }, retryTimes, true); }
public async Task RunApprenticeshipUpdateJob(string jobId) { _logger.Info($"{nameof(AcademicYearEndExpiryProcessor)} run at {_currentDateTime.Now} for Academic Year CurrentAcademicYearStartDate: {_academicYearProvider.CurrentAcademicYearStartDate}, CurrentAcademicYearEndDate: {_academicYearProvider.CurrentAcademicYearEndDate}, LastAcademicYearFundingPeriod: {_academicYearProvider.LastAcademicYearFundingPeriod}, JobId: {jobId}"); var expiredApprenticeshipUpdates = (await _apprenticeshipUpdateRepository .GetExpiredApprenticeshipUpdates(_academicYearProvider.CurrentAcademicYearStartDate)) .Where(m => m.Cost != null || m.TrainingCode != null || m.StartDate != null) .ToArray(); _logger.Info($"Found {expiredApprenticeshipUpdates.Length} apprenticeship updates that will be set to expired, JobId: {jobId}"); foreach (var update in expiredApprenticeshipUpdates) { _logger.Info($"Updating ApprenticeshipUpdate to expired, ApprenticeshipUpdateId: {update.Id}, JobId: {jobId}"); await _apprenticeshipUpdateRepository.ExpireApprenticeshipUpdate(update.Id); var apprenticeship = await _apprenticeshipRepository.GetApprenticeship(update.ApprenticeshipId); await _messagePublisher.PublishAsync(new ApprenticeshipUpdateCancelled( apprenticeship.EmployerAccountId, apprenticeship.ProviderId, apprenticeship.Id)); } var expiredApprenticeshipUpdatesAfterJob = (await _apprenticeshipUpdateRepository .GetExpiredApprenticeshipUpdates(_academicYearProvider.CurrentAcademicYearStartDate)) .Where(m => m.Cost != null || m.TrainingCode != null || m.StartDate != null) .ToArray(); if (expiredApprenticeshipUpdatesAfterJob.Length != 0) { throw new Exception($"AcademicYearEndProcessor not completed successfull, Should not be any pending ApprenticeshipUpdates after job done, There are {expiredApprenticeshipUpdatesAfterJob.Length} , JobId: {jobId}"); } }
public async Task <IProcessResult> Process(UpdateProductPriceCommand command) { var model = await databaseContext.Products.FindAsync(command.Id); if (model is null) { return(ProcessResult.NotFound()); } model.UpdatePrice(Money.FromDecimal(command.Price)); await databaseContext.ProductPrices.AddAsync(model.InitializePrice(Money.FromDecimal(command.Price))); await databaseContext.SaveChangesAsync(); await messagePublisher.PublishAsync(new ProductPriceUpdatedIntegrationEvent { Id = model.Id, Price = model.Price }); return(ProcessResult.Ok()); }
public async Task Can_Create_Messaging_Bus_Fluently_For_A_Queue() { // Arrange var services = new ServiceCollection() .AddLogging((p) => p.AddXUnit(OutputHelper)) .AddJustSaying( (builder) => { builder.Client((options) => options.WithBasicCredentials("accessKey", "secretKey").WithServiceUri(TestEnvironment.SimulatorUrl)) .Messaging((options) => options.WithRegions("eu-west-1")) .Publications((options) => options.WithQueue <QueueMessage>()) .Subscriptions((options) => options.ForQueue <QueueMessage>()) .Services((options) => options.WithMessageMonitoring(() => new MyMonitor())); }) .AddJustSayingHandler <QueueMessage, QueueHandler>(); IServiceProvider serviceProvider = services.BuildServiceProvider(); IMessagePublisher publisher = serviceProvider.GetRequiredService <IMessagePublisher>(); IMessagingBus listener = serviceProvider.GetRequiredService <IMessagingBus>(); using (var source = new CancellationTokenSource(TimeSpan.FromSeconds(20))) { // Act listener.Start(source.Token); var message = new QueueMessage(); await publisher.PublishAsync(message, source.Token); // Assert while (!source.IsCancellationRequested && !QueueHandler.MessageIds.Contains(message.Id)) { await Task.Delay(TimeSpan.FromSeconds(0.2), source.Token); } QueueHandler.MessageIds.ShouldContain(message.Id); } }
private void PublishDomainEventAsync(ProcessingCommand processingCommand, DomainEventStreamMessage eventStream, int retryTimes) { _ioHelper.TryAsyncActionRecursively("PublishEventAsync", () => _domainEventPublisher.PublishAsync(eventStream), currentRetryTimes => PublishDomainEventAsync(processingCommand, eventStream, currentRetryTimes), result => { if (_logger.IsDebugEnabled) { _logger.DebugFormat("Publish event success, {0}", eventStream); } var commandHandleResult = processingCommand.CommandExecuteContext.GetResult(); var commandResult = new CommandResult(CommandStatus.Success, processingCommand.Message.Id, eventStream.AggregateRootId, commandHandleResult, typeof(string).FullName); CompleteCommand(processingCommand, commandResult); }, () => string.Format("[eventStream:{0}]", eventStream), errorMessage => { _logger.Fatal(string.Format("Publish event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage)); }, retryTimes, true); }
public async Task Can_Create_Messaging_Bus_With_Contributors() { // Arrange var services = new ServiceCollection() .AddLogging((p) => p.AddXUnit(OutputHelper)) .AddJustSaying() .AddSingleton <IMessageBusConfigurationContributor, AwsContributor>() .AddSingleton <IMessageBusConfigurationContributor, MessagingContributor>() .AddSingleton <IMessageBusConfigurationContributor, QueueContributor>() .AddSingleton <IMessageBusConfigurationContributor, RegionContributor>() .AddJustSayingHandler <QueueMessage, QueueHandler>() .AddSingleton <MyMonitor>(); IServiceProvider serviceProvider = services.BuildServiceProvider(); IMessagePublisher publisher = serviceProvider.GetRequiredService <IMessagePublisher>(); IMessagingBus listener = serviceProvider.GetRequiredService <IMessagingBus>(); using (var source = new CancellationTokenSource(TimeSpan.FromSeconds(20))) { // Act await listener.StartAsync(source.Token); await publisher.StartAsync(source.Token); var message = new QueueMessage(); await publisher.PublishAsync(message, source.Token); // Assert while (!source.IsCancellationRequested && !QueueHandler.MessageIds.Contains(message.Id)) { await Task.Delay(TimeSpan.FromSeconds(0.2), source.Token); } QueueHandler.MessageIds.ShouldContain(message.Id); } }
private async Task PublishAsync( IMessagePublisher publisher, Message message, PublishMetadata metadata, int attemptCount, CancellationToken cancellationToken) { attemptCount++; try { var watch = Stopwatch.StartNew(); await publisher.PublishAsync(message, metadata, cancellationToken) .ConfigureAwait(false); watch.Stop(); Monitor.PublishMessageTime(watch.Elapsed); } catch (Exception ex) { if (attemptCount >= Config.PublishFailureReAttempts) { Monitor.IssuePublishingMessage(); _log.LogError(0, ex, "Failed to publish a message of type '{MessageType}'. Halting after attempt number {PublishAttemptCount}.", message.GetType(), attemptCount); throw; } _log.LogWarning(0, ex, "Failed to publish a message of type '{MessageType}'. Retrying after attempt number {PublishAttemptCount} of {PublishFailureReattempts}.", message.GetType(), attemptCount, Config.PublishFailureReAttempts); var delayForAttempt = TimeSpan.FromMilliseconds(Config.PublishFailureBackoff.TotalMilliseconds * attemptCount); await Task.Delay(delayForAttempt, cancellationToken).ConfigureAwait(false); await PublishAsync(publisher, message, metadata, attemptCount, cancellationToken).ConfigureAwait(false); } }
public async Task <IProcessResult> Process(CreateSpecificAttributeCommand command) { var product = await databaseContext.Products.FindAsync(command.ProductId); if (product is null) { return(ProcessResult.BadRequest("Product not exists.")); } var attribute = product.InitializeSpecificAttribute(Name.FromString(command.Name), command.Value); await databaseContext.SpecificAttributes.AddAsync(attribute); await databaseContext.SaveChangesAsync(); await messagePublisher.PublishAsync(new SpecificAttributeCreatedIntegrationEvent { Id = attribute.Id, ProductId = product.Id, Name = attribute.Name, Value = attribute.Value }); return(ProcessResult.Ok()); }
private async Task AssertMessagePublishedAndReceivedAsync <T>( IServiceCollection services, IHandlerAsync <T> handler, TaskCompletionSource <object> completionSource) where T : Message, new() { IServiceProvider serviceProvider = services.BuildServiceProvider(); IMessagePublisher publisher = serviceProvider.GetRequiredService <IMessagePublisher>(); IMessagingBus listener = serviceProvider.GetRequiredService <IMessagingBus>(); using var source = new CancellationTokenSource(Timeout); listener.Start(source.Token); var message = new T(); // Act await publisher.PublishAsync(message, source.Token); // Assert completionSource.Task.Wait(source.Token); await handler.Received(1).Handle(Arg.Is <T>((p) => p.UniqueKey() == message.UniqueKey())); }
private async Task ApproveApprenticeshipUpdate(AcceptApprenticeshipChangeCommand command, Apprenticeship apprenticeship, ApprenticeshipUpdate pendingUpdate) { var commitment = await _commitmentRepository.GetCommitmentById(apprenticeship.CommitmentId); if (commitment.ProviderId == null) { throw new InvalidOperationException($"The provider id on commitment {apprenticeship.CommitmentId} is null when calling {nameof(ApproveApprenticeshipUpdate)}"); } var historyService = new HistoryService(_historyRepository); historyService.TrackUpdate(commitment, CommitmentChangeType.EditedApprenticeship.ToString(), commitment.Id, null, command.Caller.CallerType, command.UserId, apprenticeship.ProviderId, apprenticeship.EmployerAccountId, command.UserName); historyService.TrackUpdate(apprenticeship, ApprenticeshipChangeType.Updated.ToString(), null, apprenticeship.Id, command.Caller.CallerType, command.UserId, apprenticeship.ProviderId, apprenticeship.EmployerAccountId, command.UserName); _mapper.ApplyUpdate(apprenticeship, pendingUpdate); await Task.WhenAll( _apprenticeshipUpdateRepository.ApproveApprenticeshipUpdate(pendingUpdate, apprenticeship, command.Caller), CreateEvents(commitment, apprenticeship, pendingUpdate), historyService.Save(), _messagePublisher.PublishAsync(new ApprenticeshipUpdateAccepted(commitment.EmployerAccountId, commitment.ProviderId.Value, command.ApprenticeshipId)), _v2EventsPublisher.PublishApprenticeshipUpdatedApproved(commitment, apprenticeship) ); }
private Task PublishExceptionAsync(ProcessingCommand processingCommand, IDomainException exception, int retryTimes, TaskCompletionSource <bool> taskSource) { exception.MergeItems(processingCommand.Message.Items); _ioHelper.TryAsyncActionRecursivelyWithoutResult("PublishExceptionAsync", () => _exceptionPublisher.PublishAsync(exception), currentRetryTimes => PublishExceptionAsync(processingCommand, exception, currentRetryTimes, taskSource), async() => { await CompleteCommand(processingCommand, CommandStatus.Failed, exception.GetType().Name, (exception as Exception).Message).ConfigureAwait(false); taskSource.SetResult(true); }, () => { var serializableInfo = new Dictionary <string, string>(); exception.SerializeTo(serializableInfo); var exceptionInfo = string.Join(",", serializableInfo.Select(x => string.Format("{0}:{1}", x.Key, x.Value))); return(string.Format("[commandId:{0}, exceptionInfo:{1}]", processingCommand.Message.Id, exceptionInfo)); }, null, retryTimes, true); return(taskSource.Task); }
public async Task <bool> Handle(OrderPlacedEvent message) { // Returning true would indicate: // The message was handled successfully // The message can be removed from the queue. // Returning false would indicate: // The message was not handled successfully // The message handling should be retried (configured by default) // The message should be moved to the error queue if all retries fail try { _logger.LogInformation("Order {orderId} for {description} received", message.OrderId, message.Description); // This is where you would actually handle the order placement // Intentionally left empty for the sake of this being a sample application _logger.LogInformation("Order {OrderId} ready", message.OrderId); await Task.Delay(RandomNumberGenerator.GetInt32(50, 100)); var orderReadyEvent = new OrderReadyEvent { OrderId = message.OrderId }; await _publisher.PublishAsync(orderReadyEvent).ConfigureAwait(false); return(true); } catch (Exception ex) { _logger.LogError(ex, "Failed to handle message for {orderId}", message.OrderId); return(false); } }
public override async Task ProcessBatchAsync(ICollection <EventContext> contexts) { var stacks = new Dictionary <string, Tuple <bool, Stack> >(); foreach (var ctx in contexts) { if (String.IsNullOrEmpty(ctx.Event.StackId)) { // only add default signature info if no other signature info has been added if (ctx.StackSignatureData.Count == 0) { ctx.StackSignatureData.AddItemIfNotEmpty("Type", ctx.Event.Type); ctx.StackSignatureData.AddItemIfNotEmpty("Source", ctx.Event.Source); } string signatureHash = ctx.StackSignatureData.Values.ToSHA1(); ctx.SignatureHash = signatureHash; Tuple <bool, Stack> value; if (stacks.TryGetValue(signatureHash, out value)) { ctx.Stack = value.Item2; } else { ctx.Stack = await _stackRepository.GetStackBySignatureHashAsync(ctx.Event.ProjectId, signatureHash).AnyContext(); if (ctx.Stack != null) { stacks.Add(signatureHash, Tuple.Create(false, ctx.Stack)); } } if (ctx.Stack == null) { Logger.Trace().Message("Creating new event stack.").Write(); ctx.IsNew = true; string title = _formattingPluginManager.GetStackTitle(ctx.Event); var stack = new Stack { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, SignatureInfo = new SettingsDictionary(ctx.StackSignatureData), SignatureHash = signatureHash, Title = title?.Truncate(1000), Tags = ctx.Event.Tags ?? new TagSet(), Type = ctx.Event.Type, TotalOccurrences = 1, FirstOccurrence = ctx.Event.Date.UtcDateTime, LastOccurrence = ctx.Event.Date.UtcDateTime }; ctx.Stack = stack; stacks.Add(signatureHash, Tuple.Create(true, ctx.Stack)); } } else { ctx.Stack = await _stackRepository.GetByIdAsync(ctx.Event.StackId, true).AnyContext(); if (ctx.Stack == null || ctx.Stack.ProjectId != ctx.Event.ProjectId) { ctx.SetError("Invalid StackId."); continue; } ctx.SignatureHash = ctx.Stack.SignatureHash; if (!stacks.ContainsKey(ctx.Stack.SignatureHash)) { stacks.Add(ctx.Stack.SignatureHash, Tuple.Create(false, ctx.Stack)); } else { stacks[ctx.Stack.SignatureHash] = Tuple.Create(false, ctx.Stack); } } if (!ctx.IsNew && ctx.Event.Tags != null && ctx.Event.Tags.Count > 0) { if (ctx.Stack.Tags == null) { ctx.Stack.Tags = new TagSet(); } List <string> newTags = ctx.Event.Tags.Where(t => !ctx.Stack.Tags.Contains(t)).ToList(); if (newTags.Count > 0) { ctx.Stack.Tags.AddRange(newTags); // make sure the stack gets saved if (!stacks.ContainsKey(ctx.Stack.SignatureHash)) { stacks.Add(ctx.Stack.SignatureHash, Tuple.Create(true, ctx.Stack)); } else { stacks[ctx.Stack.SignatureHash] = Tuple.Create(true, stacks[ctx.Stack.SignatureHash].Item2); } } } ctx.Event.IsFirstOccurrence = ctx.IsNew; // sync the fixed and hidden flags to the error occurrence ctx.Event.IsFixed = ctx.Stack.DateFixed.HasValue; ctx.Event.IsHidden = ctx.Stack.IsHidden; } var stacksToAdd = stacks.Where(kvp => kvp.Value.Item1 && String.IsNullOrEmpty(kvp.Value.Item2.Id)).Select(kvp => kvp.Value.Item2).ToList(); if (stacksToAdd.Count > 0) { await _stackRepository.AddAsync(stacksToAdd, true, sendNotification : stacksToAdd.Count == 1).AnyContext(); if (stacksToAdd.Count > 1) { await _publisher.PublishAsync(new ExtendedEntityChanged { ChangeType = ChangeType.Added, Type = typeof(Stack).Name, OrganizationId = contexts.First().Organization.Id, ProjectId = contexts.First().Project.Id }).AnyContext(); } } var stacksToSave = stacks.Where(kvp => kvp.Value.Item1 && !String.IsNullOrEmpty(kvp.Value.Item2.Id)).Select(kvp => kvp.Value.Item2).ToList(); if (stacksToSave.Count > 0) { await _stackRepository.SaveAsync(stacksToSave, true, sendNotification : false).AnyContext(); // notification will get sent later in the update stats step } // Set stack ids after they have been saved and created contexts.ForEach(ctx => { ctx.Event.StackId = ctx.Stack?.Id; }); }
private void PublishMessage(TTo msg) { _publisher.PublishAsync(msg); }
public async Task <IActionResult> Notify( [FromServices] IMessagePublisher messagePublisher) { var log = new Dictionary <string, object>(); string out_trade_no = null; try { using var ms = new System.IO.MemoryStream(); await this.Request.Body.CopyToAsync(ms); var xml_data = System.Text.Encoding.UTF8.GetString(ms.ToArray()); //IOHelper.StreamToString(ms); log["notify_data"] = xml_data; var notify_data = this.wxPayApi.ParseNotifyData(xml_data); log["notify_data_model"] = notify_data; out_trade_no = this.__parse_order_no__(notify_data.out_trade_no); log["out_trade_no"] = out_trade_no; { //收到回调不管怎么样都添加记录 var notify_data_log = this.__get_notify_log__(notify_data, out_trade_no, xml_data); log["notify_data_log"] = notify_data_log; await messagePublisher.PublishAsync(notify_data_log); } if (ValidateHelper.IsEmpty(out_trade_no)) { throw new WxPayException("回调信息中未找到订单号"); } log["publish"] = true; if (!notify_data.IsSuccess()) { throw new WxPayException("通知状态为不成功"); } var my_sign = this.wxPayApi.MD5Sign(notify_data.Parameters, out var sign_str); log["notify_sign_str"] = sign_str; if (notify_data.sign != my_sign) { throw new WxPayException("签名校验失败"); } var count = await this.orderService.SetAsPayed(out_trade_no, notify_data.transaction_id, PayMethodEnum.Wechat); if (count <= 0) { throw new WxPayException("更新订单失败"); } { var order = await this.orderService.GetOrderByNo(out_trade_no); if (order != null) { await this.AddOrderStatusHistoryLog(order.UID); } else { this._logger.AddErrorLog("____pls_notice____"); } } return(this.__response__(true)); } catch (WxPayException e) { log["out_exception"] = e.Message; log["out_exception_info"] = e.Info; //更新状态失败,检查订单状态是否时已支付,如果是就直接返回成功 if (ValidateHelper.IsNotEmpty(out_trade_no)) { try { var success = await this.__return_success__(out_trade_no); if (success) { return(this.__response__(true)); } } catch (Exception err) { log["retry_in_ex_block"] = new { err.Message, err.GetType().FullName, }; } } var info = log.ToJson(); this._logger.AddErrorLog($"处理微信支付回调失败:{info}", e); return(this.__response__(false, e.Message.Take(50).JoinAsString(string.Empty))); } }
public static Task PublishAsync(this IMessagePublisher publisher, Message message) { return(publisher.PublishAsync(message, CancellationToken.None)); }
/// <summary> /// Serializes the message to JSON and sends a single message to the queue. /// </summary> /// <param name="messagePublisher">The message publisher.</param> /// <param name="message">The message.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task.</returns> public static Task PublishAsJsonAsync <T>(this IMessagePublisher <T> messagePublisher, T message, CancellationToken cancellationToken = default) { return(messagePublisher.PublishAsync(ConvertToMessage(message), cancellationToken)); }
public void TestSendReceiveAs(string format) { string exchange = GetType().Name; const string routingKeyPrefix = "Messages"; IConnectionFactory connectionFactory = new ConnectionFactory { HostName = "localhost" }; IMessageSource <IMessage> messageSource = CreateMessageSource(format, connectionFactory, exchange, routingKeyPrefix); IMessagePublisher <IMessage> messagePublisher = CreateMessagePublisher(format, connectionFactory, exchange, routingKeyPrefix); List <TestMessage> receivedMessages1 = new List <TestMessage>(); messageSource.Messages .OfType <TestMessage>() .Subscribe(msg => { Console.WriteLine(msg); receivedMessages1.Add(msg); }, Console.WriteLine, () => Console.WriteLine("Completed!")); List <TestMessage> receivedMessages2 = new List <TestMessage>(); messageSource.Messages .OfType <TestMessage>() .Subscribe(msg => { Console.WriteLine(msg); receivedMessages2.Add(msg); }, Console.WriteLine, () => Console.WriteLine("Completed!")); List <TestMessage> messages = new List <TestMessage> { new TestMessage { Data = "Hello" }, new TestMessage { Data = "World!" }, new TestMessage { Data = "..." }, new TestMessage { Data = "Good" }, new TestMessage { Data = "Bye" }, new TestMessage { Data = "Cruel" }, new TestMessage { Data = "World" } }; foreach (TestMessage message in messages) { messagePublisher.PublishAsync(message); } Thread.Sleep(TimeSpan.FromSeconds(1)); Assert.That(receivedMessages1.Count, Is.EqualTo(7), "Incorrect number of messages received for first subscription"); Assert.That(receivedMessages2.Count, Is.EqualTo(7), "Incorrect number of messages received for second subscription"); for (int index = 0; index < messages.Count; index++) { TestMessage message = messages[index]; TestMessage received1 = receivedMessages1[index]; TestMessage received2 = receivedMessages2[index]; Assert.That(received1.Data == message.Data && received1.Timestamp == message.Timestamp, string.Format("Incorrect message1: {0}", received1)); Assert.That(received2.Data == message.Data && received2.Timestamp == message.Timestamp, string.Format("Incorrect message2: {0}", received2)); } }
/// <summary> /// Sends a single message to the queue. /// </summary> /// <param name="messagePublisher">The message publisher.</param> /// <param name="message">The message.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task.</returns> public static Task PublishAsync(this IMessagePublisher messagePublisher, Message message, CancellationToken cancellationToken = default) { _ = message ?? throw new ArgumentNullException(nameof(message)); return(messagePublisher.PublishAsync(new Message[] { message }, cancellationToken)); }
private async Task SendApprenticeshipUpdateCancelledEvent(Apprenticeship apprenticeship) { await _messagePublisher.PublishAsync(new ApprenticeshipUpdateCancelled(apprenticeship.EmployerAccountId, apprenticeship.ProviderId, apprenticeship.Id)); }
public async Task PublishAsync(IMessage message, CancellationToken token) => await _publisher.PublishAsync(message, token);
/// <summary> /// Serializes the messages to JSON and sends them to the queue. /// </summary> /// <param name="messagePublisher">The message publisher.</param> /// <param name="messages">The messages.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task.</returns> public static Task PublishAsJsonAsync <T>(this IMessagePublisher <T> messagePublisher, IEnumerable <T> messages, CancellationToken cancellationToken = default) { return(messagePublisher.PublishAsync(messages.Select(ConvertToMessage), cancellationToken)); }
public async Task <IHttpActionResult> ChangePlanAsync(string id, string planId, string stripeToken = null, string last4 = null, string couponId = null) { if (String.IsNullOrEmpty(id) || !CanAccessOrganization(id)) { return(NotFound()); } if (!Settings.Current.EnableBilling) { return(Ok(ChangePlanResult.FailWithMessage("Plans cannot be changed while billing is disabled."))); } var organization = await GetModelAsync(id, false); if (organization == null) { return(Ok(ChangePlanResult.FailWithMessage("Invalid OrganizationId."))); } var plan = BillingManager.GetBillingPlan(planId); if (plan == null) { return(Ok(ChangePlanResult.FailWithMessage("Invalid PlanId."))); } if (String.Equals(organization.PlanId, plan.Id) && String.Equals(BillingManager.FreePlan.Id, plan.Id)) { return(Ok(ChangePlanResult.SuccessWithMessage("Your plan was not changed as you were already on the free plan."))); } // Only see if they can downgrade a plan if the plans are different. if (!String.Equals(organization.PlanId, plan.Id)) { var result = await _billingManager.CanDownGradeAsync(organization, plan, CurrentUser); if (!result.Success) { return(Ok(result)); } } var customerService = new StripeCustomerService(Settings.Current.StripeApiKey); var subscriptionService = new StripeSubscriptionService(Settings.Current.StripeApiKey); try { // If they are on a paid plan and then downgrade to a free plan then cancel their stripe subscription. if (!String.Equals(organization.PlanId, BillingManager.FreePlan.Id) && String.Equals(plan.Id, BillingManager.FreePlan.Id)) { if (!String.IsNullOrEmpty(organization.StripeCustomerId)) { var subs = await subscriptionService.ListAsync(new StripeSubscriptionListOptions { CustomerId = organization.StripeCustomerId }); foreach (var sub in subs.Where(s => !s.CanceledAt.HasValue)) { await subscriptionService.CancelAsync(sub.Id); } } organization.BillingStatus = BillingStatus.Trialing; organization.RemoveSuspension(); } else if (String.IsNullOrEmpty(organization.StripeCustomerId)) { if (String.IsNullOrEmpty(stripeToken)) { return(Ok(ChangePlanResult.FailWithMessage("Billing information was not set."))); } organization.SubscribeDate = SystemClock.UtcNow; var createCustomer = new StripeCustomerCreateOptions { SourceToken = stripeToken, PlanId = planId, Description = organization.Name, Email = CurrentUser.EmailAddress }; if (!String.IsNullOrWhiteSpace(couponId)) { createCustomer.CouponId = couponId; } var customer = await customerService.CreateAsync(createCustomer); organization.BillingStatus = BillingStatus.Active; organization.RemoveSuspension(); organization.StripeCustomerId = customer.Id; if (customer.Sources.TotalCount > 0) { organization.CardLast4 = customer.Sources.Data.First().Card.Last4; } } else { var update = new StripeSubscriptionUpdateOptions { PlanId = planId }; var create = new StripeSubscriptionCreateOptions(); bool cardUpdated = false; if (!String.IsNullOrEmpty(stripeToken)) { update.Source = stripeToken; create.Source = stripeToken; cardUpdated = true; } var subscriptionList = await subscriptionService.ListAsync(new StripeSubscriptionListOptions { CustomerId = organization.StripeCustomerId }); var subscription = subscriptionList.FirstOrDefault(s => !s.CanceledAt.HasValue); if (subscription != null) { await subscriptionService.UpdateAsync(subscription.Id, update); } else { await subscriptionService.CreateAsync(organization.StripeCustomerId, planId, create); } await customerService.UpdateAsync(organization.StripeCustomerId, new StripeCustomerUpdateOptions { Email = CurrentUser.EmailAddress }); if (cardUpdated) { organization.CardLast4 = last4; } organization.BillingStatus = BillingStatus.Active; organization.RemoveSuspension(); } BillingManager.ApplyBillingPlan(organization, plan, CurrentUser); await _repository.SaveAsync(organization, o => o.Cache()); await _messagePublisher.PublishAsync(new PlanChanged { OrganizationId = organization.Id }); } catch (Exception e) { _logger.Error().Exception(e).Message("An error occurred while trying to update your billing plan: " + e.Message).Critical().Identity(CurrentUser.EmailAddress).Property("User", CurrentUser).SetActionContext(ActionContext).Write(); return(Ok(ChangePlanResult.FailWithMessage(e.Message))); } return(Ok(new ChangePlanResult { Success = true })); }
public static Task PublishAsync <T>(this IMessagePublisher publisher, T message, TimeSpan?delay = null) where T : class { return(publisher.PublishAsync(typeof(T), message, delay)); }
/// <inheritdoc /> public Task LaunchAsync() { IView mainView = _serviceProvider.GetRequiredService <MainView>(); return(_messagePublisher.PublishAsync(new AddViewMessage("Shell.ViewsHost", mainView, new Scope(_serviceProvider)))); }
public static Task PublishAsync(this IMessagePublisher publisher, Func <MqttMessageBuilder, MqttMessageBuilder> builder) { var message = builder(new MqttMessageBuilder()).Build(); return(publisher.PublishAsync(message)); }
private async Task OnCreateTodo(CreateTodo todo, CancellationToken ct) { var newTodo = await _todoRepo.AddAsync(todo.Title); await _publisher.PublishAsync(new TodoCreated(newTodo), ct); }
public virtual async Task PublishAsync(SampleMessage message) { await _publisher.PublishAsync(message); }
public static Task PublishEventAsync <TEvent>(this IMessagePublisher publisher, TEvent @event) where TEvent : class, IEvent => publisher.PublishAsync(@event);
public async Task PublishAsync(object message) { await _eventConsumer.Consume(message); await _messagePublisher.PublishAsync(message); }