From c945abc935a2b68fe40ad1ac758f9a95b10f4b7e Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Fri, 10 Jun 2022 22:28:19 +0800 Subject: [PATCH 1/9] Dapr Actors inventory provider plugin --- Directory.Build.props | 1 + EShop.sln | 33 ++++++ EShop.sln.DotSettings | 1 + ...Inventories.DaprActors.Abstractions.csproj | 18 +++ ...InventoriesDaprActorsAbstractionsModule.cs | 11 ++ .../Inventories/DaprActors/IInventoryActor.cs | 13 +++ .../DaprActors/InventoryStateModel.cs | 8 ++ .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++++ ...Shop.Plugins.Inventories.DaprActors.csproj | 18 +++ ...EShopPluginsInventoriesDaprActorsModule.cs | 15 +++ .../Inventories/DaprActors/InventoryActor.cs | 76 ++++++++++++ .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++++ ...Products.DaprActorsInventory.Domain.csproj | 15 +++ .../DaprActorsProductInventoryProvider.cs | 110 ++++++++++++++++++ ...ProductsDaprActorsInventoryDomainModule.cs | 28 +++++ .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++++ 19 files changed, 446 insertions(+) create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.csproj create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAbstractionsModule.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/IInventoryActor.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryStateModel.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xml create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xsd create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsModule.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryActor.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xml create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xsd create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp.EShop.Products.DaprActorsInventory.Domain.csproj create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/EShopProductsDaprActorsInventoryDomainModule.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xml create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xsd diff --git a/Directory.Build.props b/Directory.Build.props index 83a0f05a..99c2facf 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,6 +5,7 @@ 2.5.3 2.0.11 0.8.2 + 1.7.0 \ No newline at end of file diff --git a/EShop.sln b/EShop.sln index f003f77d..3542d607 100644 --- a/EShop.sln +++ b/EShop.sln @@ -341,6 +341,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Plugins.Coupo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Orders.Plugins.Coupons", "plugins\Coupons\src\EasyAbp.EShop.Orders.Plugins.Coupons\EasyAbp.EShop.Orders.Plugins.Coupons.csproj", "{3C385657-8365-470F-9F4F-30F31F9FCA42}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Inventories", "Inventories", "{9AC27747-E175-487F-92C9-434DEE543273}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DaprActors", "DaprActors", "{6E6FE4B9-4117-4F57-B219-EE47E4046096}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Products.DaprActorsInventory.Domain", "plugins\Inventories\DaprActors\src\EasyAbp.EShop.Products.DaprActorsInventory.Domain\EasyAbp.EShop.Products.DaprActorsInventory.Domain.csproj", "{6CD1A8B5-8AB7-4A31-8333-024A7FB602D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions", "plugins\Inventories\DaprActors\src\EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions\EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.csproj", "{CF4DE32D-9629-4C48-9BE8-5B83A1C27291}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Plugins.Inventories.DaprActors", "plugins\Inventories\DaprActors\src\EasyAbp.EShop.Plugins.Inventories.DaprActors\EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj", "{B6F3ACD5-463E-4455-A094-057A82941A94}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F468A386-5660-4888-981A-6ECF15182D32}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{485204B1-7603-4EA0-B3A4-73CB89B0D5BC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -895,6 +909,18 @@ Global {3C385657-8365-470F-9F4F-30F31F9FCA42}.Debug|Any CPU.Build.0 = Debug|Any CPU {3C385657-8365-470F-9F4F-30F31F9FCA42}.Release|Any CPU.ActiveCfg = Release|Any CPU {3C385657-8365-470F-9F4F-30F31F9FCA42}.Release|Any CPU.Build.0 = Release|Any CPU + {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1}.Release|Any CPU.Build.0 = Release|Any CPU + {CF4DE32D-9629-4C48-9BE8-5B83A1C27291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF4DE32D-9629-4C48-9BE8-5B83A1C27291}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF4DE32D-9629-4C48-9BE8-5B83A1C27291}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF4DE32D-9629-4C48-9BE8-5B83A1C27291}.Release|Any CPU.Build.0 = Release|Any CPU + {B6F3ACD5-463E-4455-A094-057A82941A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6F3ACD5-463E-4455-A094-057A82941A94}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6F3ACD5-463E-4455-A094-057A82941A94}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6F3ACD5-463E-4455-A094-057A82941A94}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1065,6 +1091,13 @@ Global {86CAD303-A0E5-42C9-89A5-61D9AAA4AD8F} = {4001814E-A67B-490D-9E13-2FB9A34B0A0B} {B076C103-DF0B-464B-A9CB-4BE5CAFEE067} = {4001814E-A67B-490D-9E13-2FB9A34B0A0B} {3C385657-8365-470F-9F4F-30F31F9FCA42} = {72F34527-9295-4F29-923E-4B075A4F31A2} + {9AC27747-E175-487F-92C9-434DEE543273} = {94CC5A11-DA0F-413C-96CA-01DB0FC426E0} + {6E6FE4B9-4117-4F57-B219-EE47E4046096} = {9AC27747-E175-487F-92C9-434DEE543273} + {F468A386-5660-4888-981A-6ECF15182D32} = {6E6FE4B9-4117-4F57-B219-EE47E4046096} + {B6F3ACD5-463E-4455-A094-057A82941A94} = {F468A386-5660-4888-981A-6ECF15182D32} + {CF4DE32D-9629-4C48-9BE8-5B83A1C27291} = {F468A386-5660-4888-981A-6ECF15182D32} + {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1} = {F468A386-5660-4888-981A-6ECF15182D32} + {485204B1-7603-4EA0-B3A4-73CB89B0D5BC} = {6E6FE4B9-4117-4F57-B219-EE47E4046096} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} diff --git a/EShop.sln.DotSettings b/EShop.sln.DotSettings index a1a9e93c..7b7d4176 100644 --- a/EShop.sln.DotSettings +++ b/EShop.sln.DotSettings @@ -21,4 +21,5 @@ False SQL True + True True \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.csproj b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.csproj new file mode 100644 index 00000000..f5d2ebb7 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.csproj @@ -0,0 +1,18 @@ + + + + + + net6.0 + + + + + + + + + + + + diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAbstractionsModule.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAbstractionsModule.cs new file mode 100644 index 00000000..37b93cf2 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAbstractionsModule.cs @@ -0,0 +1,11 @@ +using EasyAbp.EShop.Products; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; + +[DependsOn( + typeof(EShopProductsDomainSharedModule) +)] +public class EShopPluginsInventoriesDaprActorsAbstractionsModule : AbpModule +{ +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/IInventoryActor.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/IInventoryActor.cs new file mode 100644 index 00000000..714904b5 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/IInventoryActor.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Dapr.Actors; + +namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; + +public interface IInventoryActor : IActor +{ + Task GetInventoryStateAsync(); + + Task IncreaseInventoryAsync(int quantity, bool decreaseSold); + + Task ReduceInventoryAsync(int quantity, bool increaseSold); +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryStateModel.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryStateModel.cs new file mode 100644 index 00000000..96f0ef28 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryStateModel.cs @@ -0,0 +1,8 @@ +namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; + +public class InventoryStateModel +{ + public int Inventory { get; set; } + + public long Sold { get; set; } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xml b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xml new file mode 100644 index 00000000..1715698c --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xsd b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xsd new file mode 100644 index 00000000..ffa6fc4b --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file 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 new file mode 100644 index 00000000..cc8c0afd --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp.EShop.Plugins.Inventories.DaprActors.csproj @@ -0,0 +1,18 @@ + + + + + + net6.0 + + + + + + + + + + + + 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 new file mode 100644 index 00000000..a1d4f2c2 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsModule.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; + +[DependsOn( + typeof(EShopPluginsInventoriesDaprActorsAbstractionsModule) +)] +public class EShopPluginsInventoriesDaprActorsModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddActors(options => { options.Actors.RegisterActor(); }); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..a53e7c53 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/EasyAbp/EShop/Plugins/Inventories/DaprActors/InventoryActor.cs @@ -0,0 +1,76 @@ +using System.Threading.Tasks; +using Dapr; +using Dapr.Actors.Runtime; + +namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; + +public class InventoryActor : Actor, IInventoryActor +{ + public InventoryActor(ActorHost host) : base(host) + { + } + + protected override async Task OnActivateAsync() + { + await StateManager.TryAddStateAsync(Id.GetId(), new InventoryStateModel()); + } + + public virtual async Task GetInventoryStateAsync() + { + return await StateManager.GetStateAsync(Id.GetId()); + } + + public virtual async Task IncreaseInventoryAsync(int quantity, bool decreaseSold) + { + var state = await GetInventoryStateAsync(); + + InternalIncreaseInventory(state, quantity, decreaseSold); + } + + public async Task ReduceInventoryAsync(int quantity, bool increaseSold) + { + var state = await GetInventoryStateAsync(); + + InternalReduceInventory(state, quantity, increaseSold); + } + + protected virtual void InternalIncreaseInventory(InventoryStateModel stateModel, int quantity, bool decreaseSold) + { + if (quantity < 0) + { + throw new DaprException("Quantity should not be less than 0."); + } + + if (decreaseSold && stateModel.Sold - quantity < 0) + { + throw new DaprException("Target Sold cannot be less than 0."); + } + + stateModel.Inventory = checked(stateModel.Inventory + quantity); + + if (decreaseSold) + { + stateModel.Sold -= quantity; + } + } + + protected virtual void InternalReduceInventory(InventoryStateModel stateModel, int quantity, bool increaseSold) + { + if (quantity < 0) + { + throw new DaprException("Quantity should not be less than 0."); + } + + if (quantity > stateModel.Inventory) + { + throw new DaprException("Insufficient inventory."); + } + + if (increaseSold) + { + stateModel.Sold = checked(stateModel.Sold + quantity); + } + + stateModel.Inventory -= quantity; + } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xml b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xml new file mode 100644 index 00000000..1715698c --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xsd b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xsd new file mode 100644 index 00000000..ffa6fc4b --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp.EShop.Products.DaprActorsInventory.Domain.csproj b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp.EShop.Products.DaprActorsInventory.Domain.csproj new file mode 100644 index 00000000..93c911a8 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp.EShop.Products.DaprActorsInventory.Domain.csproj @@ -0,0 +1,15 @@ + + + + + + net6.0 + + + + + + + + + diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs new file mode 100644 index 00000000..cdb0e46d --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Dapr.Actors; +using Dapr.Actors.Client; +using EasyAbp.EShop.Plugins.Inventories.DaprActors; +using EasyAbp.EShop.Products.ProductInventories; +using Microsoft.Extensions.Logging; +using Volo.Abp.DependencyInjection; + +namespace EasyAbp.EShop.Products.DaprActorsInventory; + +public class DaprActorsProductInventoryProvider : IProductInventoryProvider, ITransientDependency +{ + public static string DaprActorsProductInventoryProviderName { get; set; } = "DaprActors"; + public static string DaprActorsProductInventoryProviderDisplayName { get; set; } = "DaprActors"; + public static string DaprActorsProductInventoryProviderDescription { get; set; } = "DaprActors"; + + public string InventoryProviderName { get; } = DaprActorsProductInventoryProviderName; + + public static string ActorType { get; set; } = "InventoryActor"; + + private readonly ILogger _logger; + + public DaprActorsProductInventoryProvider(ILogger logger) + { + _logger = logger; + } + + public virtual async Task GetInventoryDataAsync(InventoryQueryModel model) + { + var actor = GetActor(model); + + var stateModel = await actor.GetInventoryStateAsync(); + + return new InventoryDataModel + { + Inventory = stateModel.Inventory, + Sold = stateModel.Sold + }; + } + + public virtual async Task> GetSkuIdInventoryDataMappingAsync( + IList models) + { + var result = new Dictionary(); + + foreach (var model in models) + { + result.Add(model.ProductSkuId, await GetInventoryDataAsync(model)); + } + + return result; + } + + public virtual async Task TryIncreaseInventoryAsync(InventoryQueryModel model, int quantity, + bool decreaseSold) + { + var actor = GetActor(model); + + try + { + await actor.IncreaseInventoryAsync(quantity, decreaseSold); + } + catch (Exception e) + { + _logger.LogError("Actor threw: {Message}", e.Message); + + return false; + } + + return true; + } + + public virtual async Task TryReduceInventoryAsync(InventoryQueryModel model, int quantity, bool increaseSold) + { + var actor = GetActor(model); + + var stateModel = await actor.GetInventoryStateAsync(); + + if (stateModel.Inventory < quantity) + { + return false; + } + + try + { + await actor.ReduceInventoryAsync(quantity, increaseSold); + } + catch (Exception e) + { + _logger.LogError("Actor threw: {Message}", e.Message); + + return false; + } + + return true; + } + + protected virtual IInventoryActor GetActor(InventoryQueryModel model) + { + return ActorProxy.Create(GetActorId(model), ActorType); + } + + protected virtual ActorId GetActorId(InventoryQueryModel model) + { + return new ActorId( + $"eshop_inventory_{(model.TenantId.HasValue ? model.TenantId.Value : "host")}_{model.ProductSkuId}"); + } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/EShopProductsDaprActorsInventoryDomainModule.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/EShopProductsDaprActorsInventoryDomainModule.cs new file mode 100644 index 00000000..3c9dc09a --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/EShopProductsDaprActorsInventoryDomainModule.cs @@ -0,0 +1,28 @@ +using EasyAbp.EShop.Plugins.Inventories.DaprActors; +using EasyAbp.EShop.Products.Options; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Products.DaprActorsInventory; + +[DependsOn( + typeof(EShopProductsDomainModule), + typeof(EShopPluginsInventoriesDaprActorsAbstractionsModule) +)] +public class EShopProductsDaprActorsInventoryDomainModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.InventoryProviders.Configure( + DaprActorsProductInventoryProvider.DaprActorsProductInventoryProviderName, provider => + { + provider.DisplayName = + DaprActorsProductInventoryProvider.DaprActorsProductInventoryProviderDisplayName; + provider.Description = DaprActorsProductInventoryProvider + .DaprActorsProductInventoryProviderDescription; + provider.ProviderType = typeof(DaprActorsProductInventoryProvider); + }); + }); + } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xml b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xml new file mode 100644 index 00000000..1715698c --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xsd b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xsd new file mode 100644 index 00000000..ffa6fc4b --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file From 987e0e2277317493add38d8eb632630b628bc924 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Fri, 10 Jun 2022 23:24:21 +0800 Subject: [PATCH 2/9] Use a static state name --- .../EShop/Plugins/Inventories/DaprActors/InventoryActor.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 a53e7c53..eb8e7345 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 @@ -6,18 +6,20 @@ namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; public class InventoryActor : Actor, IInventoryActor { + public static string InventoryStateName { get; set; } = "i"; + public InventoryActor(ActorHost host) : base(host) { } protected override async Task OnActivateAsync() { - await StateManager.TryAddStateAsync(Id.GetId(), new InventoryStateModel()); + await StateManager.TryAddStateAsync(InventoryStateName, new InventoryStateModel()); } public virtual async Task GetInventoryStateAsync() { - return await StateManager.GetStateAsync(Id.GetId()); + return await StateManager.GetStateAsync(InventoryStateName); } public virtual async Task IncreaseInventoryAsync(int quantity, bool decreaseSold) From bb6f421e4cf49497068ab7633b08b3b2fff17bcd Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Sat, 11 Jun 2022 16:00:07 +0800 Subject: [PATCH 3/9] Introduce IInventoryActorProvider --- .../DaprActorsProductInventoryProvider.cs | 17 ++++++++++------- .../IInventoryActorProvider.cs | 11 +++++++++++ .../InventoryActorProvider.cs | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/IInventoryActorProvider.cs create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/InventoryActorProvider.cs diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs index cdb0e46d..5c2561c4 100644 --- a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/DaprActorsProductInventoryProvider.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Dapr.Actors; -using Dapr.Actors.Client; using EasyAbp.EShop.Plugins.Inventories.DaprActors; using EasyAbp.EShop.Products.ProductInventories; using Microsoft.Extensions.Logging; @@ -21,15 +20,19 @@ public class DaprActorsProductInventoryProvider : IProductInventoryProvider, ITr public static string ActorType { get; set; } = "InventoryActor"; private readonly ILogger _logger; + protected IInventoryActorProvider InventoryActorProvider { get; } - public DaprActorsProductInventoryProvider(ILogger logger) + public DaprActorsProductInventoryProvider( + IInventoryActorProvider inventoryActorProvider, + ILogger logger) { + InventoryActorProvider = inventoryActorProvider; _logger = logger; } public virtual async Task GetInventoryDataAsync(InventoryQueryModel model) { - var actor = GetActor(model); + var actor = await GetActorAsync(model); var stateModel = await actor.GetInventoryStateAsync(); @@ -56,7 +59,7 @@ public class DaprActorsProductInventoryProvider : IProductInventoryProvider, ITr public virtual async Task TryIncreaseInventoryAsync(InventoryQueryModel model, int quantity, bool decreaseSold) { - var actor = GetActor(model); + var actor = await GetActorAsync(model); try { @@ -74,7 +77,7 @@ public class DaprActorsProductInventoryProvider : IProductInventoryProvider, ITr public virtual async Task TryReduceInventoryAsync(InventoryQueryModel model, int quantity, bool increaseSold) { - var actor = GetActor(model); + var actor = await GetActorAsync(model); var stateModel = await actor.GetInventoryStateAsync(); @@ -97,9 +100,9 @@ public class DaprActorsProductInventoryProvider : IProductInventoryProvider, ITr return true; } - protected virtual IInventoryActor GetActor(InventoryQueryModel model) + protected virtual async Task GetActorAsync(InventoryQueryModel model) { - return ActorProxy.Create(GetActorId(model), ActorType); + return await InventoryActorProvider.GetAsync(GetActorId(model), ActorType); } protected virtual ActorId GetActorId(InventoryQueryModel model) diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/IInventoryActorProvider.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/IInventoryActorProvider.cs new file mode 100644 index 00000000..8c0791fd --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/IInventoryActorProvider.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Dapr.Actors; +using EasyAbp.EShop.Plugins.Inventories.DaprActors; +using JetBrains.Annotations; + +namespace EasyAbp.EShop.Products.DaprActorsInventory; + +public interface IInventoryActorProvider +{ + Task GetAsync(ActorId actorId, [NotNull] string actorType); +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/InventoryActorProvider.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/InventoryActorProvider.cs new file mode 100644 index 00000000..11d016ae --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Products.DaprActorsInventory.Domain/EasyAbp/EShop/Products/DaprActorsInventory/InventoryActorProvider.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Dapr.Actors; +using Dapr.Actors.Client; +using EasyAbp.EShop.Plugins.Inventories.DaprActors; +using Volo.Abp.DependencyInjection; + +namespace EasyAbp.EShop.Products.DaprActorsInventory; + +public class InventoryActorProvider : IInventoryActorProvider, ITransientDependency +{ + public virtual Task GetAsync(ActorId actorId, string actorType) + { + return Task.FromResult(ActorProxy.Create(actorId, actorType)); + } +} \ No newline at end of file From e84fe3b2bb8651cc692074899fcf90186ea3c02e Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Sat, 11 Jun 2022 16:00:38 +0800 Subject: [PATCH 4/9] Unit tests for DaprActorsProductInventoryProvider --- EShop.sln | 7 +++ ...DaprActorsProductInventoryProviderTests.cs | 48 +++++++++++++++ ...uctsDaprActorsInventoryDomainTestModule.cs | 16 +++++ ...ts.DaprActorsInventory.Domain.Tests.csproj | 24 ++++++++ .../FakeInventoryActor.cs | 43 +++++++++++++ .../ProductsDaprActorsInventoryTestBase.cs | 61 +++++++++++++++++++ .../TestInventoryActorProvider.cs | 26 ++++++++ 7 files changed, 225 insertions(+) create mode 100644 plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/DaprActorsProductInventoryProviderTests.cs create mode 100644 plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EShopProductsDaprActorsInventoryDomainTestModule.cs create mode 100644 plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests.csproj create mode 100644 plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/FakeInventoryActor.cs create mode 100644 plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/ProductsDaprActorsInventoryTestBase.cs create mode 100644 plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/TestInventoryActorProvider.cs diff --git a/EShop.sln b/EShop.sln index 3542d607..569a8985 100644 --- a/EShop.sln +++ b/EShop.sln @@ -355,6 +355,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F468A386-566 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{485204B1-7603-4EA0-B3A4-73CB89B0D5BC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests", "plugins\Inventories\DaprActors\test\EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests\EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests.csproj", "{733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -921,6 +923,10 @@ Global {B6F3ACD5-463E-4455-A094-057A82941A94}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6F3ACD5-463E-4455-A094-057A82941A94}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6F3ACD5-463E-4455-A094-057A82941A94}.Release|Any CPU.Build.0 = Release|Any CPU + {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1098,6 +1104,7 @@ Global {CF4DE32D-9629-4C48-9BE8-5B83A1C27291} = {F468A386-5660-4888-981A-6ECF15182D32} {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1} = {F468A386-5660-4888-981A-6ECF15182D32} {485204B1-7603-4EA0-B3A4-73CB89B0D5BC} = {6E6FE4B9-4117-4F57-B219-EE47E4046096} + {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB} = {485204B1-7603-4EA0-B3A4-73CB89B0D5BC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} diff --git a/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/DaprActorsProductInventoryProviderTests.cs b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/DaprActorsProductInventoryProviderTests.cs new file mode 100644 index 00000000..ce701107 --- /dev/null +++ b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/DaprActorsProductInventoryProviderTests.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Products.ProductInventories; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace EasyAbp.EShop.Products.DaprActorsInventory.Domain; + +public class DaprActorsProductInventoryProviderTests : ProductsDaprActorsInventoryTestBase +{ + [Fact] + public async Task Should_Get_Inventory() + { + var inventoryProvider = ServiceProvider.GetRequiredService(); + + var inventoryDataModel = await inventoryProvider.GetInventoryDataAsync(new InventoryQueryModel()); + + inventoryDataModel.ShouldNotBeNull(); + inventoryDataModel.Inventory.ShouldBe(100); + inventoryDataModel.Sold.ShouldBe(0); + } + + [Fact] + public async Task Should_Change_Inventory() + { + var inventoryProvider = ServiceProvider.GetRequiredService(); + + var result = await inventoryProvider.TryReduceInventoryAsync(new InventoryQueryModel(), 2, true); + + result.ShouldBeTrue(); + + var inventoryDataModel = await inventoryProvider.GetInventoryDataAsync(new InventoryQueryModel()); + + inventoryDataModel.ShouldNotBeNull(); + inventoryDataModel.Inventory.ShouldBe(98); + inventoryDataModel.Sold.ShouldBe(2); + + result = await inventoryProvider.TryIncreaseInventoryAsync(new InventoryQueryModel(), 1, true); + + result.ShouldBeTrue(); + + inventoryDataModel = await inventoryProvider.GetInventoryDataAsync(new InventoryQueryModel()); + + inventoryDataModel.ShouldNotBeNull(); + inventoryDataModel.Inventory.ShouldBe(99); + inventoryDataModel.Sold.ShouldBe(1); + } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EShopProductsDaprActorsInventoryDomainTestModule.cs b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EShopProductsDaprActorsInventoryDomainTestModule.cs new file mode 100644 index 00000000..8b3c22fb --- /dev/null +++ b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EShopProductsDaprActorsInventoryDomainTestModule.cs @@ -0,0 +1,16 @@ +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Products.DaprActorsInventory.Domain; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(EShopProductsDaprActorsInventoryDomainModule) +)] +public class EShopProductsDaprActorsInventoryDomainTestModule : AbpModule +{ +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests.csproj b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests.csproj new file mode 100644 index 00000000..5fc3de69 --- /dev/null +++ b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + EasyAbp.EShop.Products.DaprActorsInventory.Domain + + + + + + + + + + + + + + + + + + + diff --git a/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/FakeInventoryActor.cs b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/FakeInventoryActor.cs new file mode 100644 index 00000000..58ae0129 --- /dev/null +++ b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/FakeInventoryActor.cs @@ -0,0 +1,43 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.Inventories.DaprActors; +using Volo.Abp.DependencyInjection; + +namespace EasyAbp.EShop.Products.DaprActorsInventory.Domain; + +public class FakeInventoryActor : IInventoryActor, ITransientDependency +{ + private InventoryStateModel StateModel { get; } = new() + { + Inventory = 100, + Sold = 0 + }; + + public Task GetInventoryStateAsync() + { + return Task.FromResult(StateModel); + } + + public Task IncreaseInventoryAsync(int quantity, bool decreaseSold) + { + StateModel.Inventory += quantity; + + if (decreaseSold) + { + StateModel.Sold -= quantity; + } + + return Task.CompletedTask; + } + + public Task ReduceInventoryAsync(int quantity, bool increaseSold) + { + StateModel.Inventory -= quantity; + + if (increaseSold) + { + StateModel.Sold += quantity; + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/ProductsDaprActorsInventoryTestBase.cs b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/ProductsDaprActorsInventoryTestBase.cs new file mode 100644 index 00000000..55c5d3fc --- /dev/null +++ b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/ProductsDaprActorsInventoryTestBase.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Testing; +using Volo.Abp.Uow; + +namespace EasyAbp.EShop.Products.DaprActorsInventory.Domain +{ + /* All test classes are derived from this class, directly or indirectly. */ + public abstract class + ProductsDaprActorsInventoryTestBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, + Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } + } +} \ No newline at end of file diff --git a/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/TestInventoryActorProvider.cs b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/TestInventoryActorProvider.cs new file mode 100644 index 00000000..db26bdad --- /dev/null +++ b/plugins/Inventories/DaprActors/test/EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests/TestInventoryActorProvider.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using Dapr.Actors; +using EasyAbp.EShop.Plugins.Inventories.DaprActors; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; + +namespace EasyAbp.EShop.Products.DaprActorsInventory.Domain; + +[Dependency(ReplaceServices = true)] +public class TestInventoryActorProvider : IInventoryActorProvider, ITransientDependency +{ + private IInventoryActor Actor { get; set; } + + private readonly IServiceProvider _serviceProvider; + + public TestInventoryActorProvider(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public Task GetAsync(ActorId actorId, string actorType) + { + return Task.FromResult(Actor ??= _serviceProvider.GetRequiredService()); + } +} \ No newline at end of file From 1242f1f14fedf2051295cc066d8244aa79d914f8 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Sat, 11 Jun 2022 17:38:31 +0800 Subject: [PATCH 5/9] Introduce EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore --- EShop.sln | 7 +++++ ...s.Inventories.DaprActors.AspNetCore.csproj | 19 ++++++++++++ ...nsInventoriesDaprActorsAspNetCoreModule.cs | 29 +++++++++++++++++++ ...Shop.Plugins.Inventories.DaprActors.csproj | 2 +- ...EShopPluginsInventoriesDaprActorsModule.cs | 5 ---- 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore.csproj create mode 100644 plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAspNetCoreModule.cs diff --git a/EShop.sln b/EShop.sln index 569a8985..cd7f5691 100644 --- a/EShop.sln +++ b/EShop.sln @@ -357,6 +357,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{485204B1-7 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests", "plugins\Inventories\DaprActors\test\EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests\EasyAbp.EShop.Products.DaprActorsInventory.Domain.Tests.csproj", "{733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore", "plugins\Inventories\DaprActors\src\EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore\EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore.csproj", "{3F0EA314-CCF4-4BB2-A8C1-79FAE4442884}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -927,6 +929,10 @@ Global {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Debug|Any CPU.Build.0 = Debug|Any CPU {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Release|Any CPU.ActiveCfg = Release|Any CPU {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB}.Release|Any CPU.Build.0 = Release|Any CPU + {3F0EA314-CCF4-4BB2-A8C1-79FAE4442884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F0EA314-CCF4-4BB2-A8C1-79FAE4442884}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F0EA314-CCF4-4BB2-A8C1-79FAE4442884}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F0EA314-CCF4-4BB2-A8C1-79FAE4442884}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1105,6 +1111,7 @@ Global {6CD1A8B5-8AB7-4A31-8333-024A7FB602D1} = {F468A386-5660-4888-981A-6ECF15182D32} {485204B1-7603-4EA0-B3A4-73CB89B0D5BC} = {6E6FE4B9-4117-4F57-B219-EE47E4046096} {733C51A3-19C8-45C4-8B22-3FD40CAF4EFB} = {485204B1-7603-4EA0-B3A4-73CB89B0D5BC} + {3F0EA314-CCF4-4BB2-A8C1-79FAE4442884} = {F468A386-5660-4888-981A-6ECF15182D32} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore.csproj b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore.csproj new file mode 100644 index 00000000..9a6f080b --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore.csproj @@ -0,0 +1,19 @@ + + + + + + net6.0 + + + + + + + + + + + + + diff --git a/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAspNetCoreModule.cs b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAspNetCoreModule.cs new file mode 100644 index 00000000..84d1eca1 --- /dev/null +++ b/plugins/Inventories/DaprActors/src/EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore/EasyAbp/EShop/Plugins/Inventories/DaprActors/EShopPluginsInventoriesDaprActorsAspNetCoreModule.cs @@ -0,0 +1,29 @@ +using EasyAbp.EShop.Products; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; + +[DependsOn( + typeof(AbpAspNetCoreModule), + typeof(EShopProductsDomainSharedModule) +)] +public class EShopPluginsInventoriesDaprActorsAspNetCoreModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddActors(options => { options.Actors.RegisterActor(); }); + + Configure(options => + { + options.EndpointConfigureActions.Add(ctx => + { + // Register actors handlers that interface with the Dapr runtime. + ctx.Endpoints.MapActorsHandlers(); + }); + }); + } +} \ No newline at end of file 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 cc8c0afd..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,7 @@ - + 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 a1d4f2c2..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,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; @@ -8,8 +7,4 @@ namespace EasyAbp.EShop.Plugins.Inventories.DaprActors; )] public class EShopPluginsInventoriesDaprActorsModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddActors(options => { options.Actors.RegisterActor(); }); - } } \ No newline at end of file From eb5c5276889711d23cf5c82df1b592d1cbba1511 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Sat, 11 Jun 2022 17:38:50 +0800 Subject: [PATCH 6/9] Update README.md --- docs/README.md | 4 +- .../plugins/inventories/dapr-actors/README.md | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 docs/plugins/inventories/dapr-actors/README.md diff --git a/docs/README.md b/docs/README.md index f9e3ba8a..c3651a7c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -48,7 +48,7 @@ We have launched an online demo for this module: [https://eshop.samples.easyabp. * Define a Product Group (optional) * Product group is used to classify different types of products, so we can customize different behavior for them, for example, products of the "GiftCard" product group could automatically send the card number and password to the customer's mailbox. - * EShop provides a [default product group](https://github.com/EasyAbp/EShop/blob/master/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/EShopProductsDomainModule.cs#L29-L36). + * EShop provides a [default product group](https://github.com/EasyAbp/EShop/blob/master/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/EShopProductsDomainModule.cs#L33-L37). * Refer to the configuration of the default product group and define a new product group. * Create a Product @@ -102,6 +102,8 @@ We can customize some features to use EShop in complex application scenarios. * Plugin modules * Baskets * Coupons + * Inventories + * [DaprActors](/plugins/inventories/dapr-actors) ## Roadmap diff --git a/docs/plugins/inventories/dapr-actors/README.md b/docs/plugins/inventories/dapr-actors/README.md new file mode 100644 index 00000000..3fa9e58b --- /dev/null +++ b/docs/plugins/inventories/dapr-actors/README.md @@ -0,0 +1,38 @@ +# EShop.Plugins.Inventories.DaprActors + +[![ABP version](https://img.shields.io/badge/dynamic/xml?style=flat-square&color=yellow&label=abp&query=%2F%2FProject%2FPropertyGroup%2FAbpVersion&url=https%3A%2F%2Fraw.githubusercontent.com%2FEasyAbp%2FEShop%2Fmaster%2FDirectory.Build.props)](https://abp.io) +[![NuGet](https://img.shields.io/nuget/v/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.svg?style=flat-square)](https://www.nuget.org/packages/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions) +[![NuGet Download](https://img.shields.io/nuget/dt/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions.svg?style=flat-square)](https://www.nuget.org/packages/EasyAbp.EShop.Plugins.Inventories.DaprActors.Abstractions) +[![Discord online](https://badgen.net/discord/online-members/S6QaezrCRq?label=Discord)](https://discord.gg/S6QaezrCRq) +[![GitHub stars](https://img.shields.io/github/stars/EasyAbp/EShop?style=social)](https://www.github.com/EasyAbp/EShop) + +EShop product-inventory implementation of [Dapr Actors](https://docs.dapr.io/developing-applications/building-blocks/actors/actors-overview). + +## Installation + +1. Install the following NuGet packages. ([see how](https://github.com/EasyAbp/EasyAbpGuide/blob/master/docs/How-To.md#add-nuget-packages)) + + * EasyAbp.EShop.Products.DaprActorsInventory.Domain _(install at EasyAbp.EShop.Products.Domain location)_ + * EasyAbp.EShop.Plugins.Inventories.DaprActors.AspNetCore _(install at a host project to run Actors)_ + +2. Add `DependsOn(typeof(EShopXxxModule))` attribute to configure the module dependencies. ([see how](https://github.com/EasyAbp/EasyAbpGuide/blob/master/docs/How-To.md#add-module-dependencies)) + +## Usage + +1. Configure the DaprActors inventory provider as default. + ```csharp + Configure(options => + { + // Configure as the default inventory provider + options.DefaultInventoryProviderName = "DaprActors"; + + // Configure as the default inventory provider for MyProductGroup + options.Groups.Configure(group => + { + group.DefaultInventoryProviderName = "DaprActors"; + }); + }); + ``` + > Better to use `DaprActorsProductInventoryProvider.DaprActorsProductInventoryProviderName` instead of `"DaprActors"` as the provider name. + +2. Create a product and set `InventoryProviderName` to `DaprActors`. Then the product is specified to use the Dapr Actors inventory provider. \ No newline at end of file From 83e0561f315e3c5217cd1fe45b6ce00702ceb60e Mon Sep 17 00:00:00 2001 From: Super Date: Sat, 11 Jun 2022 21:21:16 +0800 Subject: [PATCH 7/9] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index c3651a7c..8133570b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -103,7 +103,7 @@ We can customize some features to use EShop in complex application scenarios. * Baskets * Coupons * Inventories - * [DaprActors](/plugins/inventories/dapr-actors) + * [DaprActors](/docs/plugins/inventories/dapr-actors) ## Roadmap From 37a7204132719ebd4ec7e3df3984fbbc699b8594 Mon Sep 17 00:00:00 2001 From: Super Date: Sat, 11 Jun 2022 21:26:54 +0800 Subject: [PATCH 8/9] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 8133570b..81da5c14 100644 --- a/docs/README.md +++ b/docs/README.md @@ -103,7 +103,7 @@ We can customize some features to use EShop in complex application scenarios. * Baskets * Coupons * Inventories - * [DaprActors](/docs/plugins/inventories/dapr-actors) + * [DaprActors](https://github.com/EasyAbp/EShop/tree/dev/plugins/Inventories/DaprActors) ## Roadmap From ca4903eef2d93e873aa49ffb56e1fab75060b292 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Sat, 11 Jun 2022 21:33:20 +0800 Subject: [PATCH 9/9] Add symlink --- plugins/Inventories/DaprActors/README.md | 1 + 1 file changed, 1 insertion(+) create mode 120000 plugins/Inventories/DaprActors/README.md diff --git a/plugins/Inventories/DaprActors/README.md b/plugins/Inventories/DaprActors/README.md new file mode 120000 index 00000000..6aba629a --- /dev/null +++ b/plugins/Inventories/DaprActors/README.md @@ -0,0 +1 @@ +../../../docs/plugins/inventories/dapr-actors/README.md \ No newline at end of file