diff --git a/AccessQueuePlayground/Program.cs b/AccessQueuePlayground/Program.cs index f00ab40..349e337 100644 --- a/AccessQueuePlayground/Program.cs +++ b/AccessQueuePlayground/Program.cs @@ -19,7 +19,15 @@ builder.Host.UseSerilog((context, services, configuration) => // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); -builder.Services.AddSingleton(); +if (string.IsNullOrEmpty(builder.Configuration["AccessQueuePlayground:ServiceUrl"])) +{ + builder.Services.AddSingleton(); +} +else +{ + builder.Services.AddHttpClient(); + builder.Services.AddSingleton(); +} builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHostedService(); diff --git a/AccessQueuePlayground/Services/AccessQueueApiService.cs b/AccessQueuePlayground/Services/AccessQueueApiService.cs new file mode 100644 index 0000000..640c869 --- /dev/null +++ b/AccessQueuePlayground/Services/AccessQueueApiService.cs @@ -0,0 +1,59 @@ +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using AccessQueueService.Models; +using AccessQueueService.Services; + +namespace AccessQueuePlayground.Services +{ + public class AccessQueueApiService : IAccessService + { + private readonly HttpClient _httpClient; + private readonly string _serviceUrl; + + public AccessQueueStatus Status => throw new NotImplementedException(); + + public AccessQueueApiService(HttpClient httpClient, IConfiguration config) + { + _httpClient = httpClient; + _serviceUrl = config["AccessQueuePlayground:ServiceUrl"]?.TrimEnd('/') ?? "https://localhost:7291"; + } + + public async Task RequestAccess(string userId) + { + return await _httpClient.GetFromJsonAsync($"{_serviceUrl}/access/{userId}"); + } + + public async Task RevokeAccess(string userId) + { + var response = await _httpClient.DeleteAsync($"{_serviceUrl}/access/{userId}"); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(); + return result; + } + return false; + } + + public Task DeleteExpiredTickets() + { + throw new NotImplementedException(); + } + + public AccessQueueConfig GetConfiguration() + { + return _httpClient.GetFromJsonAsync($"{_serviceUrl}/config").Result; + } + + public void UpdateConfiguration(AccessQueueConfig config) + { + _ = _httpClient.PostAsJsonAsync($"{_serviceUrl}/config", config).Result; + } + + public void PatchConfiguration(AccessQueueConfig partialConfig) + { + throw new NotImplementedException(); + } + } +} diff --git a/AccessQueuePlayground/appsettings.json b/AccessQueuePlayground/appsettings.json index 9cfd1aa..65e1393 100644 --- a/AccessQueuePlayground/appsettings.json +++ b/AccessQueuePlayground/appsettings.json @@ -6,13 +6,14 @@ } }, "AccessQueue": { - "CapacityLimit": 3, // Maximum number of active users - "ActivitySeconds": 2, // Time since last access before a user is considered inactive - "ExpirationSeconds": 10, // 12 hours - Time before a user access is revoked - "RollingExpiration": true // Whether to extend expiration time on access + "CapacityLimit": 3, + "ActivitySeconds": 2, + "ExpirationSeconds": 10, + "RollingExpiration": true }, "AccessQueuePlayground": { - "RefreshRateMilliseconds": 200 // How often to re-request access and update the UI + "RefreshRateMilliseconds": 200, + "ServiceUrl": "https://localhost:7291/" }, "AllowedHosts": "*" } diff --git a/README.md b/README.md index c6b2e57..ddcd47d 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ Test results will be displayed in the terminal. You can also use Visual Studio's The `AccessQueuePlayground` project provides a simple web-based UI for interacting with the AccessQueueService API. This is useful for testing and demonstration purposes. -### Running the Playground +### Running 1. Build and run the playground project: ```powershell @@ -166,7 +166,7 @@ The `AccessQueuePlayground` project provides a simple web-based UI for interacti - HTTPS: https://localhost:7211 (See `AccessQueuePlayground/Properties/launchSettings.json` for details.) -### Using the Playground +### Using - Open the provided URL in your browser. - Use the UI to request and revoke access for different user IDs. @@ -174,5 +174,32 @@ The `AccessQueuePlayground` project provides a simple web-based UI for interacti This playground is intended only for local development and demonstration. +### Configuring + +The `AccessQueuePlayground` project can be configured via its `appsettings.json` file. The main options are: + +- **RefreshRateMilliseconds**: Determines how often (in milliseconds) the playground requests access for all active users and updates the UI. Lower values provide more real-time updates but may increase load on the service. +- **ServiceUrl**: The URL of the AccessQueueService API to use. If this is set, all API requests from the playground will be sent to the specified service URL (e.g., `https://localhost:7291/`). + - If `ServiceUrl` is **not provided**, the playground will use an internal instance of AccessQueueService, configured using the playground's own `appsettings.json` values under the `AccessQueue` section. This is useful for local development and testing without running the service separately. + +Example configuration in `AccessQueuePlayground/appsettings.json`: + +```json +{ + "AccessQueuePlayground": { + "RefreshRateMilliseconds": 200, + "ServiceUrl": "https://localhost:7291/" + }, + "AccessQueue": { + "CapacityLimit": 3, + "ActivitySeconds": 2, + "ExpirationSeconds": 10, + "RollingExpiration": true + } +} +``` + +> **Tip:** Adjust `RefreshRateMilliseconds` for your use case. For most demos, 100–500ms works well. If you are connecting to a remote or production AccessQueueService, consider increasing the refresh interval (e.g., 1000ms or higher) to account for network latency and reduce unnecessary load. + ## License See [LICENSE.txt](./LICENSE.txt) for license information. \ No newline at end of file