From 6c9aebb24a8c023df2888d693abb1bf1878c81be Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Mon, 8 Aug 2022 16:02:46 +0800 Subject: [PATCH] Use actor timer to persist inventory for flash sales --- ...Shop.Plugins.Inventories.DaprActors.csproj | 1 - ...EShopPluginsInventoriesDaprActorsModule.cs | 2 - .../Inventories/DaprActors/InventoryActor.cs | 53 +++++++++---------- ...p.Plugins.Inventories.OrleansGrains.csproj | 1 - ...opPluginsInventoriesOrleansGrainsModule.cs | 2 - .../OrleansGrains/InventoryGrain.cs | 45 +++++++--------- 6 files changed, 45 insertions(+), 59 deletions(-) diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj index 386df1c6..4b5cd92d 100644 --- a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj @@ -12,7 +12,6 @@ - diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsModule.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsModule.cs index 65b224a5..0b59cb9b 100644 --- a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsModule.cs +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsModule.cs @@ -1,10 +1,8 @@ using Volo.Abp.Modularity; -using Volo.Abp.Timing; namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; [DependsOn( - typeof(AbpTimingModule), typeof(EShopPluginsInventoriesDaprActorsAbstractionsModule) )] public class EShopPluginsInventoriesDaprActorsModule : AbpModule diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryActor.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryActor.cs index 0d9938b0..b78c33f8 100644 --- a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryActor.cs +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryActor.cs @@ -2,7 +2,7 @@ using System; using System.Threading.Tasks; using Dapr; using Dapr.Actors.Runtime; -using Volo.Abp.Timing; +using JetBrains.Annotations; namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; @@ -10,13 +10,13 @@ public class InventoryActor : Actor, IInventoryActor { public static string InventoryStateName { get; set; } = "i"; - protected DateTime? TimeToPersistInventory { get; set; } + protected bool FlashSalesInventoryUpdated { get; set; } - protected IClock Clock { get; } + [CanBeNull] + protected ActorTimer FlashSalesPersistInventoryTimer { get; set; } - public InventoryActor(ActorHost host, IClock clock) : base(host) + public InventoryActor(ActorHost host) : base(host) { - Clock = clock; } protected override async Task OnActivateAsync() @@ -24,64 +24,61 @@ public class InventoryActor : Actor, IInventoryActor await StateManager.TryAddStateAsync(InventoryStateName, new InventoryStateModel()); } - public virtual async Task GetInventoryStateAsync() - { - var state = await InternalGetInventoryStateAsync(); - - await TrySetInventoryStateAsync(state); - - return state; - } + public virtual Task GetInventoryStateAsync() => + StateManager.GetStateAsync(InventoryStateName); public virtual async Task IncreaseInventoryAsync(int quantity, bool decreaseSold, bool isFlashSale) { - var state = await InternalGetInventoryStateAsync(); + var state = await GetInventoryStateAsync(); InternalIncreaseInventory(state, quantity, decreaseSold); - if (!isFlashSale || state.Inventory == 0) + if (!isFlashSale) { await SetInventoryStateAsync(state); } else { - TimeToPersistInventory ??= Clock.Now + TimeSpan.FromSeconds(30); + FlashSalesInventoryUpdated = true; - await TrySetInventoryStateAsync(state); + await TryRegisterFlashSalesPersistInventoryTimerAsync(); } } public virtual async Task ReduceInventoryAsync(int quantity, bool increaseSold, bool isFlashSale) { - var state = await InternalGetInventoryStateAsync(); + var state = await GetInventoryStateAsync(); InternalReduceInventory(state, quantity, increaseSold); - if (!isFlashSale || state.Inventory == 0) + if (!isFlashSale) { await SetInventoryStateAsync(state); } else { - TimeToPersistInventory ??= Clock.Now + TimeSpan.FromSeconds(30); + FlashSalesInventoryUpdated = true; - await TrySetInventoryStateAsync(state); + await TryRegisterFlashSalesPersistInventoryTimerAsync(); } } - protected virtual Task InternalGetInventoryStateAsync() => - StateManager.GetStateAsync(InventoryStateName); + protected virtual async Task TryRegisterFlashSalesPersistInventoryTimerAsync() + { + FlashSalesPersistInventoryTimer ??= await RegisterTimerAsync(null, nameof(PeriodicSetInventoryStateAsync), + null, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3)); + } - protected virtual async Task TrySetInventoryStateAsync(InventoryStateModel stateModel) + protected virtual async Task PeriodicSetInventoryStateAsync() { - if (!TimeToPersistInventory.HasValue || TimeToPersistInventory.Value < Clock.Now) + if (!FlashSalesInventoryUpdated) { - return false; + return; } - await SetInventoryStateAsync(stateModel); + await SetInventoryStateAsync(await GetInventoryStateAsync()); - return true; + FlashSalesInventoryUpdated = false; } protected virtual async Task SetInventoryStateAsync(InventoryStateModel state) diff --git a/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp.EShop.Plugins.Inventories.OrleansGrains.csproj b/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp.EShop.Plugins.Inventories.OrleansGrains.csproj index 2346d462..6e831f2a 100644 --- a/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp.EShop.Plugins.Inventories.OrleansGrains.csproj +++ b/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp.EShop.Plugins.Inventories.OrleansGrains.csproj @@ -12,7 +12,6 @@ - all diff --git a/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/EShopPluginsInventoriesOrleansGrainsModule.cs b/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/EShopPluginsInventoriesOrleansGrainsModule.cs index 40b6f09d..087bb7b9 100644 --- a/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/EShopPluginsInventoriesOrleansGrainsModule.cs +++ b/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/EShopPluginsInventoriesOrleansGrainsModule.cs @@ -1,10 +1,8 @@ using Volo.Abp.Modularity; -using Volo.Abp.Timing; namespace EasyAbp.EShop.Plugins.Inventories.OrleansGrains; [DependsOn( - typeof(AbpTimingModule), typeof(EShopPluginsInventoriesOrleansGrainsAbstractionsModule) )] public class EShopPluginsInventoriesOrleansGrainsModule : AbpModule diff --git a/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/InventoryGrain.cs b/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/InventoryGrain.cs index 06213b69..b17aadbc 100644 --- a/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/InventoryGrain.cs +++ b/plugins/Inventories/OrleansGrains/src/EasyAbp.EShop.Plugins.Inventories.OrleansGrains/EasyAbp/EShop/Plugins/Inventories/OrleansGrains/InventoryGrain.cs @@ -1,9 +1,9 @@ using System; using System.Threading.Tasks; +using JetBrains.Annotations; using Orleans; using Orleans.Providers; using Orleans.Runtime; -using Volo.Abp.Timing; namespace EasyAbp.EShop.Plugins.Inventories.OrleansGrains; @@ -12,23 +12,12 @@ public class InventoryGrain : Grain, IInventoryGrain { public const string StorageProviderName = "EShopInventoryStorage"; - protected DateTime? TimeToPersistInventory { get; set; } + protected bool FlashSalesInventoryUpdated { get; set; } - protected IClock Clock { get; } + [CanBeNull] + protected IDisposable FlashSalesPersistInventoryTimer { get; set; } - public InventoryGrain(IClock clock) - { - Clock = clock; - } - - public virtual async Task GetInventoryStateAsync() - { - var state = State; - - await TryWriteStateAsync(); - - return state; - } + public virtual Task GetInventoryStateAsync() => Task.FromResult(State); public virtual async Task IncreaseInventoryAsync(int quantity, bool decreaseSold, bool isFlashSale) { @@ -40,9 +29,9 @@ public class InventoryGrain : Grain, IInventoryGrain } else { - TimeToPersistInventory ??= Clock.Now + TimeSpan.FromSeconds(30); + FlashSalesInventoryUpdated = true; - await TryWriteStateAsync(); + TryRegisterFlashSalesPersistInventoryTimer(); } } @@ -56,22 +45,28 @@ public class InventoryGrain : Grain, IInventoryGrain } else { - TimeToPersistInventory ??= Clock.Now + TimeSpan.FromSeconds(30); + FlashSalesInventoryUpdated = true; - await TryWriteStateAsync(); + TryRegisterFlashSalesPersistInventoryTimer(); } } - - public async Task TryWriteStateAsync() + + protected virtual void TryRegisterFlashSalesPersistInventoryTimer() + { + FlashSalesPersistInventoryTimer ??= RegisterTimer(PeriodicWriteInventoryStateAsync, + new object(), TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3)); + } + + protected virtual async Task PeriodicWriteInventoryStateAsync(object obj) { - if (!TimeToPersistInventory.HasValue || TimeToPersistInventory.Value < Clock.Now) + if (!FlashSalesInventoryUpdated) { - return false; + return; } await WriteStateAsync(); - return true; + FlashSalesInventoryUpdated = false; } protected virtual void InternalIncreaseInventory(int quantity, bool decreaseSold)