From 1cfa6a86189f6cefa6e1c1b2bba1beec5b48c146 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 30 Apr 2024 07:50:01 -0500 Subject: [PATCH] DistributedLocker --- .../Browsing/IWebBrowser.cs | 2 +- .../Browsing/Models/ElementActionArgs.cs | 25 ++++++---- .../Repositories/BotSharpDatabaseSettings.cs | 1 + .../BotSharp.Core/BotSharp.Core.csproj | 1 + .../BotSharp.Core/BotSharpCoreExtensions.cs | 2 + .../Infrastructures/DistributedLocker.cs | 50 +++++++++++++++++++ .../Repository/DataContextHelper.cs | 1 - .../PlaywrightWebDriver.GetAttributeValue.cs | 10 ++-- .../SeleniumWebDriver.GetAttributeValue.cs | 10 ++-- 9 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs index 850833cd..80dd6925 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs @@ -25,5 +25,5 @@ public interface IWebBrowser Task CloseBrowser(string contextId); Task CloseCurrentPage(string contextId); Task SendHttpRequest(string contextId, HttpRequestParams actionParams); - Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location, BrowserActionResult result); + Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementActionArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementActionArgs.cs index 48eb6a26..8b644b31 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementActionArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementActionArgs.cs @@ -4,24 +4,29 @@ namespace BotSharp.Abstraction.Browsing.Models; public class ElementActionArgs { - private BroswerActionEnum _action; - public BroswerActionEnum Action => _action; + public BroswerActionEnum Action { get; set; } - private string? _content; - public string? Content => _content; + public string? Content { get; set; } - private ElementPosition? _position; - public ElementPosition? Position => _position; + public ElementPosition? Position { get; set; } + + /// + /// Required for deserialization + /// + public ElementActionArgs() + { + + } public ElementActionArgs(BroswerActionEnum action, ElementPosition? position = null) { - _action = action; - _position = position; + Action = action; + Position = position; } public ElementActionArgs(BroswerActionEnum action, string content) { - _action = action; - _content = content; + Action = action; + Content = content; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/BotSharpDatabaseSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/BotSharpDatabaseSettings.cs index 458aa83e..ff077296 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/BotSharpDatabaseSettings.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/BotSharpDatabaseSettings.cs @@ -7,6 +7,7 @@ public class BotSharpDatabaseSettings : DatabaseBasicSettings public string BotSharpMongoDb { get; set; } public string TablePrefix { get; set; } public DbConnectionSetting BotSharp { get; set; } + public string Redis { get; set; } } public class DatabaseBasicSettings diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index 1650b719..6029a5c7 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -152,6 +152,7 @@ + diff --git a/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs index 2b56281c..51f3eb1d 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs +++ b/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs @@ -14,9 +14,11 @@ public static class BotSharpCoreExtensions { services.AddScoped(); services.AddScoped(); + services.AddSingleton(); RegisterPlugins(services, config); ConfigureBotSharpOptions(services, configOptions); + return services; } diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs new file mode 100644 index 00000000..82b655c7 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs @@ -0,0 +1,50 @@ +using RedLockNet; +using RedLockNet.SERedis; +using RedLockNet.SERedis.Configuration; +using StackExchange.Redis; + +namespace BotSharp.Core.Infrastructures; + +public class DistributedLocker +{ + private readonly BotSharpDatabaseSettings _settings; + private readonly RedLockFactory _lockFactory; + + public DistributedLocker(/*BotSharpDatabaseSettings settings*/) + { + // _settings = settings; + + var multiplexers = new List(); + foreach (var x in "".Split(';')) + { + var option = new ConfigurationOptions + { + AbortOnConnectFail = false, + EndPoints = { x } + }; + var _connMuliplexer = ConnectionMultiplexer.Connect(option); + multiplexers.Add(_connMuliplexer); + } + + _lockFactory = RedLockFactory.Create(multiplexers); + } + + public async Task Lock(string resource, Func action) + { + var expiry = TimeSpan.FromSeconds(60); + var wait = TimeSpan.FromSeconds(30); + var retry = TimeSpan.FromSeconds(3); + + await using (var redLock = await _lockFactory.CreateLockAsync(resource, expiry, wait, retry)) + { + if (redLock.IsAcquired) + { + await action(); + } + else + { + Console.WriteLine($"Acquire locak failed due to {resource} after {wait}s timeout."); + } + } + } +} diff --git a/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs b/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs index 28b447c5..edcbced8 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Repositories; using Microsoft.Data.SqlClient; using MySqlConnector; using System.Data.Common; diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs index cf172d31..035bcf3b 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs @@ -2,10 +2,10 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver; public partial class PlaywrightWebDriver { - public async Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location, BrowserActionResult result) + public async Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location) { var page = _instance.GetPage(message.ContextId); - ILocator locator = page.Locator(result.Selector); + ILocator locator = page.Locator(location.Selector); var value = string.Empty; if (!string.IsNullOrEmpty(location?.AttributeName)) @@ -13,6 +13,10 @@ public partial class PlaywrightWebDriver value = await locator.GetAttributeAsync(location.AttributeName); } - return value ?? string.Empty; + return new BrowserActionResult + { + IsSuccess = true, + Body = value ?? string.Empty + }; } } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs index ee5d47e7..0402b2db 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs @@ -2,10 +2,10 @@ namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; public partial class SeleniumWebDriver { - public async Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location, BrowserActionResult result) + public async Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location) { var driver = await _instance.InitInstance(message.ContextId); - var locator = driver.FindElement(By.CssSelector(result.Selector)); + var locator = driver.FindElement(By.CssSelector(location.Selector)); var value = string.Empty; if (!string.IsNullOrEmpty(location?.AttributeName)) @@ -13,6 +13,10 @@ public partial class SeleniumWebDriver value = locator.GetAttribute(location.AttributeName); } - return value ?? string.Empty; + return new BrowserActionResult + { + IsSuccess = true, + Body = value ?? string.Empty + }; } }