public override async Task <CreateCouponsArgument> Run( CreateCouponsArgument arg, CommercePipelineExecutionContext context) { await this._getManagedListCommand.PerformTransaction(context.CommerceContext, async() => { var policy = context.CommerceContext.GetPolicy <LoyaltyPointsPolicy>(); LoyaltyPointsEntity loyaltyPointsEntity = await _findEntityCommand.Process(context.CommerceContext, typeof(LoyaltyPointsEntity), Constants.EntityId, shouldCreate: true) as LoyaltyPointsEntity; if (loyaltyPointsEntity == null) { await context.AbortWithError("Unable to access or create LoyaltyPointsEntity {0}", "LoyaltyPointsEntityNotReturned", Constants.EntityId); return; } // Prevent simultaneous updates, in case multiple minion instances. Since these might be on scaled servers, mutex lock uses database field. // Lock is read before count is checked, so that when first process finishes and releases row, counts will be replenished. // Notes: // 1. If this pipeline aborts, the lock should be rolled back. // 2. Assuming transactions are enabled, the second process should never see IsLocked=true, as the read won't return until the lock is released. However, // this syntax should work on a non-transactional environment, and makes the intent of the code clearer. if (loyaltyPointsEntity.IsLocked) { await context.AbortWithError("{0} is locked. If this condition persists, unset this value through the database.", "EntityLocked", Constants.EntityId); return; } var list = await EnsureList(context, Constants.AvailableCouponsList); if (list == null) { await context.AbortWithError("Unable to create list {0}", "UnableToCreateList", Constants.AvailableCouponsList); return; } long count = await _getListCountCommand.Process(context.CommerceContext, Constants.AvailableCouponsList); context.Logger.LogDebug($"{this.Name}: List {Constants.AvailableCouponsList} has {count} items."); if (count <= policy.ReprovisionTriggerCount) { loyaltyPointsEntity.IsLocked = true; await _persistEntityCommand.Process(context.CommerceContext, loyaltyPointsEntity); context.Logger.LogDebug($"{this.Name}: List {Constants.AvailableCouponsList} is at or under reprovision count of {policy.ReprovisionTriggerCount}."); loyaltyPointsEntity.SequenceNumber++; string suffix = loyaltyPointsEntity.SequenceNumber.ToString(); string promotionName = string.Format(Constants.GeneratedPromotion, suffix); Promotion promotion = await GeneratePromotion(context, promotionName); if (promotion == null) { await context.AbortWithError("Unable to generate promotion {0}.", "PromotionNotFound", promotionName); return; } await AddCoupons(context, promotion, suffix); if (context.IsNullOrHasErrors()) { return; } await AllocateCoupons(context, promotion, suffix); if (context.IsNullOrHasErrors()) { return; } ApprovePromotion(context, promotion); await CopyCouponsToList(context, loyaltyPointsEntity, list); if (context.IsNullOrHasErrors()) { return; } loyaltyPointsEntity.IsLocked = false; await _persistEntityCommand.Process(context.CommerceContext, list); await _persistEntityCommand.Process(context.CommerceContext, promotion); await _persistEntityCommand.Process(context.CommerceContext, loyaltyPointsEntity); } }); return(arg); }
public override async Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context) { Condition.Requires(entityView).IsNotNull($"{Name}: The argument cannot be null"); if (entityView.Name != "ServiceBus") { return(entityView); } var pluginPolicy = context.GetPolicy <ServiceBusOrderPlacedPolicy>(); var connectionPolicy = context.GetPolicy <ServiceBusConnectionPolicy>(); var count = await _getCountCommand.Process(context.CommerceContext, pluginPolicy.OrderPlacedListName); var sentOrdersCount = await _getCountCommand.Process(context.CommerceContext, pluginPolicy.OrderSentListName); entityView.UiHint = "Flat"; entityView.Icon = pluginPolicy.Icon; entityView.DisplayName = "ServiceBus Dashboard"; entityView.Properties.Add( new ViewProperty { Name = "ServiceBus Connection String", IsHidden = false, IsReadOnly = true, OriginalType = "Html", UiType = "Html", RawValue = connectionPolicy.EndPoint }); entityView.ChildViews.Add( new EntityView { ItemId = "localordersnotsent", Icon = pluginPolicy.Icon, DisplayName = "Local Orders pending send to ServiceBus", Properties = new List <ViewProperty> { new ViewProperty { Name = "ItemId", RawValue = "localordersnotsent", UiType = "EntityLink", IsHidden = true }, new ViewProperty { Name = "QueueName", RawValue = pluginPolicy.OrderPlacedListName, UiType = "EntityLink" }, new ViewProperty { Name = "Orders Count", RawValue = count, UiType = "EntityLink" } } }); entityView.ChildViews.Add( new EntityView { ItemId = "Total Orders sent to ServiceBus", Icon = pluginPolicy.Icon, DisplayName = "Total Orders sent to ServiceBus", Properties = new List <ViewProperty> { new ViewProperty { Name = "ItemId", RawValue = "localordersnotsent", UiType = "EntityLink", IsHidden = true }, new ViewProperty { Name = "QueueName", RawValue = pluginPolicy.OrderSentListName, UiType = "EntityLink" }, new ViewProperty { Name = "Orders Count", RawValue = sentOrdersCount, UiType = "EntityLink" } } }); //entityView.ChildViews.Add( // new EntityView // { // ItemId = "123", // Icon = pluginPolicy.Icon, // DisplayName = "ServiceBus Queue", // Properties = new List<ViewProperty> { // new ViewProperty {Name = "ItemId", RawValue = "abc123", UiType = "EntityLink", IsHidden = true }, // new ViewProperty {Name = "QueueName", RawValue = "Orders", UiType = "EntityLink" }, // new ViewProperty {Name = "Status", RawValue = "1", UiType = "EntityLink" }, // new ViewProperty {Name = "MaxSize", RawValue = "10000000", UiType = "EntityLink" }, // new ViewProperty {Name = "Active Message Count", RawValue = GetMetricsAsync(), UiType = "EntityLink" }, // } // }); return(entityView); }