elsa-core/src/common/Elsa.Api.Common/Extensions/WebApplicationExtensions.cs

179 lines
9.1 KiB
C#
Raw Normal View History

using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elsa.Workflows;
using FastEndpoints;
2023-04-02 17:19:12 +00:00
using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.RateLimiting;
2023-04-02 17:19:12 +00:00
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
/// <summary>
/// Provides extension methods to add FastEndpoints configured for use with Elsa API endpoints.
/// </summary>
2023-04-02 17:19:12 +00:00
[PublicAPI]
public static class WebApplicationExtensions
{
private static readonly RequestDelegate NotFoundRequestDelegate = context =>
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
return Task.CompletedTask;
};
/// <summary>
/// Registers the FastEndpoints middleware configured for use with Elsa API endpoints.
/// </summary>
/// <param name="app"></param>
/// <param name="routePrefix">The route prefix to apply to Elsa API endpoints.</param>
/// <example>E.g. "elsa/api" will expose endpoints like this: "/elsa/api/workflow-definitions"</example>
Add Agents Module with Semantic Kernel Integration (#5937) * Remove `ServiceProfileConfig` and `SkillConfig` Refactored the codebase to eliminate `ServiceProfileConfig` and `SkillConfig` in favor of simplifying configurations. Updated related entities and settings to consistently use `ServiceConfig` and `AgentConfig`. Refined function execution to enhance overall system coherence and maintainability. * Refactor agent management and plugin system This update eliminates AgentManager and related classes, introducing new management interfaces and memory-based stores. The plugin system is refactored with better separation of concerns and the addition of provider interfaces. * Add new Agents features and services Introduced AgentsFeature for API endpoints, AgentManagementFeature for agent management, and AgentActivitiesFeature for activities. Updated service configurations and migrated files for cleaner and more maintainable code structure. * Rename execute endpoints to invoke Renamed the 'Execute' endpoints and related paths to 'Invoke' for better semantic clarity. Adjusted the namespace and updated the route configuration accordingly to reflect this change. * Add permissions configuration to Agents Invoke endpoint This commit adds a call to `ConfigurePermissions("agents:invoke")` in the Agents Invoke endpoint configuration. This change ensures that proper permissions are checked when this endpoint is accessed. * Rename Management to Persistence with EF Core support Renamed various files and classes from Management to Persistence. Introduced Entity Framework Core (EF Core) support for agents, including implementation of APIs for API key, service, and agent definitions. The changes also updated project configurations and added necessary database context and entity configurations. * Add EntityFrameworkCore project for Agents persistence Introduce a new Entity Framework Core provider to manage the persistence layer of the Agents module. The project includes references to the base persistence and common Entity Framework projects. * Remove redundant exception handlers and add new SQLite migration. Deleted unnecessary `DbExceptionTransformer` and `RethrowDbExceptionHandler` classes to streamline error handling. Introduced a new SQLite migration for the Agents module to create necessary database tables and indices. Also modified `Store` and `EntityStore` to utilize a service provider for exception handling. * Add Sqlite configuration extension and sample updates Introduce a new extension method for configuring EF Core to use Sqlite in the Elsa.Agents module. Updated the sample project to use a configurable Sqlite connection string and adjusted the appsettings.json accordingly. Also added necessary folder structure in the project file. * Add agent, service, and API key CRUD operations Introduced CRUD functionalities for agent, service, and API key entities. Added endpoint handlers, filtering capabilities, and memory/EF core stores to support these operations. Updated configuration mappings as well. * Add Agent API endpoints and DTOs Added CRUD endpoints for agents in Elsa.Agents.Api along with the required DTOs and Request models. These endpoints include create, read, update, delete, and list functionalities, facilitating the management of agent entities. * Add support for agent service providers and discovery Introduce interfaces and implementations for agent service providers and service discovery. Updated `KernelFactory` to integrate the new service discovery mechanism and restructured plugin discoverer naming for consistency. * Add agent management features Introduce agent management components, including pages for listing and handling agent workflows, dialogs for creating agents with Blazor components, and backend API endpoints for generating unique agent names. This enhances functionality for managing agent workflows within the application. * Refactor exception handling and simplify event handling logic Replaced DataProcessingDbExceptionHandler with DbExceptionTransformer for handling PostgreSQL exceptions. Streamlined event completion logic by renaming method and ensuring input retrieval before setting the result. * Add bulk delete endpoint for agents Introduced new API endpoint for bulk deleting agents. Implemented request and response models, and updated persistence layer to handle bulk operations. Also reorganized project structure for better modularity. * Refactor API Key models and endpoint classes Consolidate API Key request models into unified models and update endpoints to use these new models. Add new transformation methods to entity classes. Enhance configuration classes and streamline the dependency injection process. * Refactor and streamline bulk delete and service APIs Refactored the bulk delete endpoints for API keys, services, and agents, consolidating request and response models. Added new service input and model classes and updated the corresponding stores to support bulk deletions. Simplified the endpoint logic to use these new models and enhanced filtering capabilities. * Set default values for AgentInputModel properties Updated properties in `AgentInputModel` to use initialized default values instead of `default!`. This change ensures that string and object properties are instantiated properly, improving code stability and preventing potential null reference exceptions. * Add plugin listing endpoint and related models Introduced a new endpoint to list all registered plugins in the system. Added necessary models and methods for plugin description and retrieval, along with appropriate documentation comments. * Refactor agent management to use `IAgentManager`. Created new notifications for agent lifecycle events and introduced an `AgentManager` service for agent CRUD operations. Updated APIs and other components to use the new `IAgentManager` service instead of direct store access for a more cohesive architecture. * Update agent activity descriptor names Changed the activity descriptor names to use PascalCase for consistency and readability. Also added display names for input variables to improve user interfaces. * Add overloaded RefreshDescriptorsAsync for single activity provider Introduced a new overloaded method in IActivityRegistry and ActivityRegistry to refresh activity descriptors using a single IActivityProvider. Updated RefreshActivityRegistry to use the new method, ensuring more flexibility in descriptor refresh operations.
2024-09-01 07:03:14 +00:00
public static IApplicationBuilder UseWorkflowsApi(this IApplicationBuilder app, string routePrefix = "elsa/api")
{
return app.UseFastEndpoints(config => ConfigureWorkflowsApi(config, routePrefix));
Add Agents Module with Semantic Kernel Integration (#5937) * Remove `ServiceProfileConfig` and `SkillConfig` Refactored the codebase to eliminate `ServiceProfileConfig` and `SkillConfig` in favor of simplifying configurations. Updated related entities and settings to consistently use `ServiceConfig` and `AgentConfig`. Refined function execution to enhance overall system coherence and maintainability. * Refactor agent management and plugin system This update eliminates AgentManager and related classes, introducing new management interfaces and memory-based stores. The plugin system is refactored with better separation of concerns and the addition of provider interfaces. * Add new Agents features and services Introduced AgentsFeature for API endpoints, AgentManagementFeature for agent management, and AgentActivitiesFeature for activities. Updated service configurations and migrated files for cleaner and more maintainable code structure. * Rename execute endpoints to invoke Renamed the 'Execute' endpoints and related paths to 'Invoke' for better semantic clarity. Adjusted the namespace and updated the route configuration accordingly to reflect this change. * Add permissions configuration to Agents Invoke endpoint This commit adds a call to `ConfigurePermissions("agents:invoke")` in the Agents Invoke endpoint configuration. This change ensures that proper permissions are checked when this endpoint is accessed. * Rename Management to Persistence with EF Core support Renamed various files and classes from Management to Persistence. Introduced Entity Framework Core (EF Core) support for agents, including implementation of APIs for API key, service, and agent definitions. The changes also updated project configurations and added necessary database context and entity configurations. * Add EntityFrameworkCore project for Agents persistence Introduce a new Entity Framework Core provider to manage the persistence layer of the Agents module. The project includes references to the base persistence and common Entity Framework projects. * Remove redundant exception handlers and add new SQLite migration. Deleted unnecessary `DbExceptionTransformer` and `RethrowDbExceptionHandler` classes to streamline error handling. Introduced a new SQLite migration for the Agents module to create necessary database tables and indices. Also modified `Store` and `EntityStore` to utilize a service provider for exception handling. * Add Sqlite configuration extension and sample updates Introduce a new extension method for configuring EF Core to use Sqlite in the Elsa.Agents module. Updated the sample project to use a configurable Sqlite connection string and adjusted the appsettings.json accordingly. Also added necessary folder structure in the project file. * Add agent, service, and API key CRUD operations Introduced CRUD functionalities for agent, service, and API key entities. Added endpoint handlers, filtering capabilities, and memory/EF core stores to support these operations. Updated configuration mappings as well. * Add Agent API endpoints and DTOs Added CRUD endpoints for agents in Elsa.Agents.Api along with the required DTOs and Request models. These endpoints include create, read, update, delete, and list functionalities, facilitating the management of agent entities. * Add support for agent service providers and discovery Introduce interfaces and implementations for agent service providers and service discovery. Updated `KernelFactory` to integrate the new service discovery mechanism and restructured plugin discoverer naming for consistency. * Add agent management features Introduce agent management components, including pages for listing and handling agent workflows, dialogs for creating agents with Blazor components, and backend API endpoints for generating unique agent names. This enhances functionality for managing agent workflows within the application. * Refactor exception handling and simplify event handling logic Replaced DataProcessingDbExceptionHandler with DbExceptionTransformer for handling PostgreSQL exceptions. Streamlined event completion logic by renaming method and ensuring input retrieval before setting the result. * Add bulk delete endpoint for agents Introduced new API endpoint for bulk deleting agents. Implemented request and response models, and updated persistence layer to handle bulk operations. Also reorganized project structure for better modularity. * Refactor API Key models and endpoint classes Consolidate API Key request models into unified models and update endpoints to use these new models. Add new transformation methods to entity classes. Enhance configuration classes and streamline the dependency injection process. * Refactor and streamline bulk delete and service APIs Refactored the bulk delete endpoints for API keys, services, and agents, consolidating request and response models. Added new service input and model classes and updated the corresponding stores to support bulk deletions. Simplified the endpoint logic to use these new models and enhanced filtering capabilities. * Set default values for AgentInputModel properties Updated properties in `AgentInputModel` to use initialized default values instead of `default!`. This change ensures that string and object properties are instantiated properly, improving code stability and preventing potential null reference exceptions. * Add plugin listing endpoint and related models Introduced a new endpoint to list all registered plugins in the system. Added necessary models and methods for plugin description and retrieval, along with appropriate documentation comments. * Refactor agent management to use `IAgentManager`. Created new notifications for agent lifecycle events and introduced an `AgentManager` service for agent CRUD operations. Updated APIs and other components to use the new `IAgentManager` service instead of direct store access for a more cohesive architecture. * Update agent activity descriptor names Changed the activity descriptor names to use PascalCase for consistency and readability. Also added display names for input variables to improve user interfaces. * Add overloaded RefreshDescriptorsAsync for single activity provider Introduced a new overloaded method in IActivityRegistry and ActivityRegistry to refresh activity descriptors using a single IActivityProvider. Updated RefreshActivityRegistry to use the new method, ensuring more flexibility in descriptor refresh operations.
2024-09-01 07:03:14 +00:00
}
2023-04-02 17:19:12 +00:00
/// <summary>
/// Applies an ASP.NET Core rate limiting policy to requests targeting the Elsa API route prefix.
/// </summary>
/// <param name="app">The application builder.</param>
/// <param name="routePrefix">The route prefix used by Elsa API endpoints.</param>
/// <param name="policyName">The registered ASP.NET Core rate limiting policy name. Leave empty to skip rate limiting.</param>
public static IApplicationBuilder UseWorkflowsApiRateLimiting(this IApplicationBuilder app, string routePrefix = "elsa/api", string? policyName = null)
{
if (string.IsNullOrWhiteSpace(policyName))
return app;
var pathPrefix = NormalizeRoutePrefixPath(routePrefix);
return app.UseRateLimitingPolicyForPath(pathPrefix, policyName, "Elsa API rate limiting endpoint", requireMatchedEndpoint: true);
}
/// <summary>
/// Maps FastEndpoints endpoint routes configured for use with Elsa API endpoints.
2023-04-02 17:19:12 +00:00
/// </summary>
/// <param name="routes">The <see cref="IEndpointRouteBuilder"/> to register the endpoints with.</param>
/// <param name="routePrefix">The route prefix to apply to Elsa API endpoints.</param>
Add caching to workflow runtime and workflow management stores (#5174) * Add caching to workflow runtime and workflow management stores The update introduces caching to workflow runtime and workflow management stores to enhance performance. This is achieved by adding decorators for several stores, which cache records to reduce database fetches. Additionally, a signaler for change tokens allows for cache invalidation when changes occur. The MemoryCache feature has also been updated to include Scrutor for decoration and the caching duration can be configured through the new CachingOptions class. * Refactor WorkflowsMiddleware for HTTP Endpoint bookmarks and triggers The WorkflowsMiddleware has been extensively refactored to handle HTTP Endpoint bookmarks and triggers. This involves breaking down the InvokeAsync method by extracting parts of its functionality into separate helper methods such as FindTriggersAsync and FindBookmarksAsync. Moreover, Assist with authorization checks, workflow execution within request timeout, and handling of workflow faults has been improved to be more efficient and clearly segmented. * Update HTTP endpoint authorization to use Workflow context The authorization process in the AuthenticationBasedHttpEndpointAuthorizationHandler class has been updated to use the Workflow context instead of the WorkflowInstanceId string. The AuthorizeHttpEndpointContext model has been correspondingly changed to include a Workflow property, thereby strengthening the link between authorization and specific workflows. * Add FindAsync methods to trigger and bookmark stores The code adjustments add new FindAsync methods to the trigger and bookmark store contracts as well as all their concrete implementations (MongoDb, Memory and EFCore). These methods support fetching the first record matching a given filter. The adjustments also include minor syntax improvements and the addition of [UsedImplicitly] attributes where needed. * Refactor WorkflowsMiddleware for improved workflow handling The code was refactored to simplify the flow of handling workflows in the WorkflowsMiddleware class. Specifically, the methods to start and resume a workflow have been extracted to improve code readability. Further, handleErrorMiddlewares was also updated to better manage instances where no valid workflows or base paths are found. * Add caching functionality to WorkflowsMiddleware Added IMemoryCache usage in the WorkflowsMiddleware to cache lookup results for workflows and their associated triggers. This will reduce the number of database operations required when searching for workflows, thus improving performance. The cache is maintained for one minute before it is refreshed. * Implement dynamic cache duration for workflows The code has been updated to have a dynamic cache duration for the workflows instead of a hardcoded one minute. By using the CachingOptions service, the cache duration can now be set in the configuration making it more flexible and adaptable to different performance needs. * Add HttpWorkflowsCacheManager for caching HTTP workflows This commit includes the implementation of IHttpWorkflowsCacheManager for caching of HTTP workflows. New handlers have been added to invalidate cache on workflow updates. Additionally, WorkflowsMiddleware has been renamed to HttpWorkflowsMiddleware. * Refactor workflow trigger handling and caching The refactoring includes deletion of `IndexWorkflowTriggersHandler.cs` and creation of `IndexTriggers.cs` thus revising the workflow trigger indexing approach. Also, revamped the `ITriggerIndexer` interface which now handles deletion of triggers with specific workflow and filter. Furthermore, the caching mechanism in `HttpWorkflowsCacheManager.cs` is modified to handle eviction of workflow definitions and triggers separately boosting its efficiency. * Add summary to IndexedWorkflowTriggers A summary has been added to the 'IndexedWorkflowTriggers' class, providing a brief description. This description outlines that it represents a collection of indexed workflow triggers, promoting clearer understanding for future reference. * Refactor memory caching feature into separate module This commit separates the memory caching feature from the Elsa.Common module into a distinct Elsa.Caching module. This includes moving and renaming related files, such as the MemoryCacheFeature class and associated dependencies. The references in other modules and in the main solution file have been updated accordingly to include the new Elsa.Caching module. * Add distributed caching and update async methods Introduced a distributed caching feature with extensible change token signal publishing. Updated various cache-related methods to be asynchronous for improved performance and responsiveness. Also updated some workflow identity references for clarity. * Add distributed caching with MassTransit support This addition includes the implementation of a distributed caching system with MassTransit transport. The changes introduce necessary interfaces and services, new distributed caching feature along with the support for MassTransit as a transport option. Moreover, the instance management feature has been renamed to clustering feature for better clarity. * Refactor queue naming and scope of MassTransitChangeTokenSignalPublisher Queue name construction is adjusted in the RabbitMqServiceBusFeature and AzureServiceBusFeature modules for better organization and readability. MassTransitChangeTokenSignalPublisher is now a singleton service, ensuring the signal publisher can be shared across the application, increasing efficiency and performance. Also, introduced use of DistributedCacheFeature in MassTransitDistributedCacheFeature module for better modularization. * Add caching capabilities to workflow definition service This commit introduces caching to the workflow definition service, improving the performance for retrieving workflow definitions. 4 new classes have been created (`CachingWorkflowDefinitionService`, `EvictWorkflowDefinitionServiceCache`, `WorkflowDefinitionCacheManager`, and `IWorkflowDefinitionCacheManager`), and several existing classes have been updated to support caching. The caching also includes invalidation mechanisms, ensuring data consistency. * Refactor caching mechanism in workflow definition In the workflow definition module, the explicit caching functionality related to workflow definition versioning has been removed in favor of a more streamlined approach. Additionally, the manner in which services are registered has been altered. As a result, the caching now directly involves the overall workflow definition rather than individual versions, simplifying the caching logic and potentially improving the performance. * Update MassTransitBroker and enable RealTimeWorkflows and SignalRHubs The MassTransitBroker has been updated to Memory from RabbitMq. In addition, the RealTimeWorkflows and UseWorkflowsSignalRHubs features are now enabled in the code. This change will impact how the service communicates and processes real-time requests for workflow operations. * Reformat variable types in HttpFeature The reformatting involves a list of variable types in the HttpFeature module. Each type now appears on a new line for improved readability, making the code easier to maintain and review. * Update HTTP workflows cache invalidation handler XML comment * Remove unnecessary using directives Unnecessary using directives were deleted across several files in the Elsa.Http module. This simplifies the code and will possibly improve execution speed. Specific deletions include those for Encoding, Unicode, Extensions, Collections.Generic, Linq, Text, and Tasks namespaces. * Refactor HttpWorkflowsMiddleware constructor This commit simplifies the HttpWorkflowsMiddleware class constructor. It removes the intermediary variables `_next` and `_options` and directly uses the passed arguments in the constructor. Now, the `next` and `options` parameters are used directly throughout the middleware. * Simplify workflow retrieval in HttpWorkflowsMiddleware This refactoring replaces the use of FindWorkflowDefinitionAsync and MaterializeWorkflowAsync with a single method, FindWorkflowAsync. This simplifies the middleware code and likely improves performance by reducing the number of database queries or service calls required to retrieve a workflow. * Refactor workflow retrieval in HttpBookmarkProcessor Simplified the workflow retrieval process in HttpBookmarkProcessor.cs. Replaced FindWorkflowDefinitionAsync and MaterializeWorkflowAsync methods with a single FindWorkflowAsync call. This reduces the complexity and improves efficiency in retrieving workflow. * Optimize FindWorkflowAsync method in HttpWorkflowsCacheManager Removed redundant lines of code to simplify workflow search functionality. This change simplified the FindWorkflowAsync method by directly calling the FindWorkflowAsync function in the workflowDefinitionService, thus increasing code readability and efficiency. * Refactor Endpoint.cs for workflow retrieval The method for obtaining a workflow in the Endpoint.cs script has been refactored and streamlined. The 'GetWorkflowDefinition' method is replaced by the 'GetWorkflowAsync' method which directly retrieves the workflow, without the intermediate step of materializing the workflow definition. This shortens the code and simplifies the process. * Refactor InputFunctionsDefinitionProvider constructor The constructor for InputFunctionsDefinitionProvider has been simplified by removing unnecessary private fields. Services are now directly used in the method instead of being stored in fields. This improves readability and reduces complexity in the class structure. * Refactor WorkflowInstance with improved state handling Simplified the methods for handling workflow and workflow state in the WorkflowInstance class. The refactoring also included some code clean-ups and variable renaming. The new implementation provides better readability and maintainability of the code by reducing unnecessary lines and improving structuring of objects and responses. * Remove unused IBookmarkManager and update workflow functions IBookmarkManager from ProtoActorWorkflowRuntime.cs file is removed due to its redundant status. Additionally, the "FindAsync" method has been updated to use a cancellation token. Also, annotations were added to the "ExportWorkflowStateAsync" and "ImportWorkflowStateAsync" methods to flag calls to functions that require unreferenced code. * Remove unused ReSharper directive Unused ReSharper directive in the file IndexTriggers.cs was identified and therefore removed. This change makes the code cleaner and easier to read. * Update activity invocation in workflow runtime Updated the DefaultBackgroundActivityInvoker service in the Elsa.Workflows.Runtime module to annotate the ExecuteAsync method with "RequiresUnreferencedCode" attribute. This change is made considering the potential code trimming issue. Additionally, simplified the process of fetching workflow by directly using FindWorkflowAsync method instead of FindWorkflowDefinitionAsync and MaterializeWorkflowAsync methods. * Refactor code to simplify workflow definition loading The code for finding and materializing workflow definitions has been simplified. Instead of loading the definition and materializing it into a workflow in separate steps, a new method called FindWorkflowAsync has been introduced to perform both actions at once. This reduces redundancy and makes the code more readable. * Refactor WorkflowHostFactory to streamline workflow creation This commit simplifies the workflow creation process in WorkflowHostFactory. It removes redundant code and extraneous methods, specifically the overloaded CreateAsync method which used WorkflowDefinition. Now, it directly finds and uses the Workflow instance, thereby simplifying the code base and improving maintainability. * Refactor workflow retrieval in WorkflowInstance.cs Changed the way workflow instances are retrieved from the WorkflowDefinitionService. Instead of obtaining the workflow definition and then materializing the workflow from it, the workflow is directly retrieved using the FindWorkflowAsync function. This simplifies the code and avoids unnecessary null-checks. * Remove unnecessary whitespace in WorkflowInstance.cs An extraneous whitespace character was identified and removed in the WorkflowInstance.cs file. This change contributes towards maintaining clean and readable code in the Elsa.ProtoActor module. * Remove unnecessary comment in ProtoActorWorkflowRuntime The unnecessary comment ("Load the workflow definition.") in the method TryStartWorkflowAsync of the ProtoActorWorkflowRuntime.cs file was removed. This is part of an ongoing effort to keep the codebase clean and readable. * Update workflow management features and handlers Added explicit notification handlers for DeleteWorkflowInstances and RefreshActivityRegistry in WorkflowManagementFeature.cs. Also, renamed RefreshActivityRegistryHandler.cs to RefreshActivityRegistry.cs for better clarity. * Add multiple log record support to workflow execution log stores The major change of this commit is the addition of methods to add multiple log records in the WorkflowExecutionLogStore, across different storage modules such as EntityFramework, MongoDB, Dapper, Elasticsearch and Memory. This ensures consistency and uniform behavior across different storage types. Furthermore, some reformatting and tidying up of the code were undertaken to maintain readability and clarity. * Remove redundant workflow definition check The workflow definition existence check and related service retrieval were removed from HttpWorkflowsMiddleware.cs. It was determined that this check was unnecessary as the workflow definition's existence is guaranteed at this point in the process, reducing redundancy in the code. * Improve cancellation token usage in workflow execution This commit refines the usage of cancellation tokens during the execution of workflows in Elsa.Server and HttpWorkflowsMiddleware. Previously, a cancellation token pair was created before ExecuteWithinTimeoutAsync was called, which limited duration control solely to that method. Now, cancellation tokens are included within ExecuteWithinTimeoutAsync method. This allows the method to observe any cancellation initiated by outer scopes, enhancing control over the timeout of operations. * Add PersistStateAsync method to WorkflowHost A new PersistStateAsync method has been added to the WorkflowHost, which enables the host to directly persist its own state. The method has been integrated into the DefaultWorkflowRuntime and HttpWorkflowsMiddleware. This update eliminates the need to continuously get instances of IWorkflowInstanceManager to save state, which improves efficiency and code readability. * Refactor DefaultAlterationRunner service This update simplifies the DefaultAlterationRunner service, reducing the number of code lines and removing unnecessary references. The workflow materialization step has been merged with the find workflow step, and unused namespaces have been dropped. * Refine wording in IWorkflowHost interface documentation The documentation for the 'CanStartWorkflowAsync' method in the IWorkflowHost interface has been cleaned up. The superfluous "or not" verbiage has been removed, making it easier to understand the method's function. * Remove Redis from DistributedCachingTransport The Redis option was removed from the DistributedCachingTransport enumeration. This transport isn't currently implemented. * Remove 'useDistributedCaching' constant The 'useDistributedCaching' constant was removed from `Program.cs`, and conditional logic was updated to use `distributedCachingTransport != DistributedCachingTransport.None`. A new option 'None' was added to the `DistributedCachingTransport` enum to facilitate this change. * Update package tags in MassTransit project file The package tags in the Elsa.Caching.Distributed.MassTransit project file was updated to consolidate the tags, changing 'mass-transit' to 'masstransit'. This change better aligns with standard naming conventions and improves searchability. * Refactor distributed caching implementation This commit involves an extensive refactor of the distributed caching implementation. Distributed caching related code and resources were moved into an independent 'Elsa.Caching.Distributed' module. The interface 'IDistributedChangeTokenSignaler' was deleted and its functionality was replaced by 'IChangeTokenSignalInvoker'. * Refactor order of parameters in GetOrCreateAsync method The order of parameters in the GetOrCreateAsync method within the CachingWorkflowDefinitionStore class has been changed. This change ensures that the `key` parameter is now first, followed by the `factory` parameter. This improves code readability and aligns with standard coding practices. * Refactor cache retrieval in Workflow service Refactoring was done to streamline the way objects are retrieved from cache in the Workflow service. Duplicated code was condensed into a new `GetFromCacheAsync` method, which is now called in the existing methods, thus increasing maintainability and reducing the possibility of errors. * Update method descriptions and fix comments formatting Method descriptions in various contracts have been updated to more accurately reflect their function regarding record addition and updating in the persistence store. All double comment markers (/// ///) have also been corrected to the standard (///) across multiple classes. * Remove unused caching methods in ModuleExtensions The commit removes the unused methods, `UseMemoryCache` and `UseDistributedCache` from the `ModuleExtensions.cs` file. The removal is part of a wider cleanup and refactoring effort to streamline the codebase and improve legibility. * Remove redundant PrimaryKeyName in DapperWorkflowExecutionLogStore The "PrimaryKeyName" constant was removed in DapperWorkflowExecutionLogStore. This change simplifies the initialization of the '_store' property, reducing unnecessary redundancy and complexity. The refactored code maintains the same functionality but improves readability and maintainability. * Refactor SaveAsync methods in Elsa.Dapper Store The SaveAsync functions have been updated in the Store.cs file inside the Elsa.Dapper module. They now include cancellation token parameters and specify that they add or update records, providing clearer distinction and flexibility. * Refactor store initialization in Elsa.Dapper modules Removed the redundant usage of primary keys during the store initialization across Elsa.Dapper module. Simplified the SaveAsync methods by removing the parameter for primary key, making the code cleaner and more maintainable. This refactoring does not affect the module's functionality. * Refactor UserStore in Elsa.Dapper module The code was adjusted to improve readability within the Elsa.Dapper module's UserStore. Two lines that were previously combined have now been separated into distinct lines, making the code structure more clear. * Refactor constructor arguments in MongoDb module Simplified several classes in the MongoDb module by injecting dependencies directly through the constructor instead of assigning them to private readonly fields. This improves readability and removes unnecessary code lines. Also added JetBrains.Annotations where applicable. * Fix comment syntax in IWorkflowInstanceStore A syntax error in the comments for the method SaveManyAsync (in IWorkflowInstanceStore interface) has been corrected. This change ensures that the remarks section of the method is properly formatted and correctly displayed in documentation. * Remove ComputeBookmarkHash from IHttpWorkflowsCacheManager The ComputeBookmarkHash method was removed from IHttpWorkflowsCacheManager to declutter the interface. The functionality was moved and adapted in the HttpWorkflowsMiddleware class to maintain the original functionality. * Add logging to HttpWorkflowsMiddleware In this update, the HttpWorkflowsMiddleware class has been modified to include logging. Specifically, warning logs have been added to track workflow-related processes and to notify if mentioned bookmarks or workflow instances are not found. * Update consumer configuration in MassTransitFeature This commit modifies the consumer configuration in the MassTransitFeature. Instead of hardcoding the consumer type to DispatchCancelWorkflowsRequestConsumer, it now uses the dynamic consumer type retrieved from the context, making the feature more adaptable for different scenarios. * Change default MassTransitBroker to Memory The default value for the variable useMassTransitBroker in Elsa.Server.Web's Program.cs file has been modified. It has been changed from RabbitMq to Memory to change the message broker used by MassTransit in the application. * Remove Datadog.Trace package from Directory.Packages.props The Datadog.Trace package with version 2.49.0 has been removed from the Directory.Packages.props file. This change reflects the fact that this package is no longer required in our project.
2024-04-10 09:51:40 +00:00
/// <example>E.g. "elsa/api" will expose endpoints like this: "/elsa/api/workflow-definitions"</example>
2023-04-02 17:19:12 +00:00
public static IEndpointRouteBuilder MapWorkflowsApi(this IEndpointRouteBuilder routes, string routePrefix = "elsa/api") =>
routes.MapFastEndpoints(config => ConfigureWorkflowsApi(config, routePrefix));
/// <summary>
/// Applies an ASP.NET Core rate limiting policy to requests targeting the specified path prefix.
/// </summary>
/// <param name="app">The application builder.</param>
/// <param name="pathPrefix">The path prefix to protect.</param>
/// <param name="policyName">The registered ASP.NET Core rate limiting policy name.</param>
/// <param name="displayName">The endpoint display name used for rate limiting metadata.</param>
/// <remarks>
/// This method only attaches rate limiting metadata. In endpoint-routed pipelines, call this after routing has selected an endpoint
/// and before the host's single <c>app.UseRateLimiter()</c> middleware. ASP.NET Core validates the configured policy when the
/// rate limiter middleware handles matching requests.
/// </remarks>
public static IApplicationBuilder UseRateLimitingPolicyForPath(this IApplicationBuilder app, PathString pathPrefix, string policyName, string displayName) =>
app.UseRateLimitingPolicyForPath(pathPrefix, policyName, displayName, true);
/// <summary>
/// Applies an ASP.NET Core rate limiting policy to requests targeting the specified path prefix.
/// </summary>
/// <param name="app">The application builder.</param>
/// <param name="pathPrefix">The path prefix to protect.</param>
/// <param name="policyName">The registered ASP.NET Core rate limiting policy name.</param>
/// <param name="displayName">The endpoint display name used for rate limiting metadata.</param>
/// <param name="requireMatchedEndpoint">Whether to skip rate limiting when endpoint routing selected no endpoint.</param>
public static IApplicationBuilder UseRateLimitingPolicyForPath(this IApplicationBuilder app, PathString pathPrefix, string policyName, string displayName, bool requireMatchedEndpoint)
{
if (!pathPrefix.HasValue || string.IsNullOrWhiteSpace(policyName))
return app;
var rateLimitingMetadata = new EnableRateLimitingAttribute(policyName);
var fallbackEndpoint = CreateRateLimitingEndpoint(null, rateLimitingMetadata, displayName);
var endpointCache = new ConditionalWeakTable<Endpoint, Endpoint>();
return app.UseWhen(
context => context.Request.Path.StartsWithSegments(pathPrefix, StringComparison.OrdinalIgnoreCase),
branch =>
{
branch.Use(async (context, next) =>
{
var originalEndpoint = context.GetEndpoint();
if (requireMatchedEndpoint && originalEndpoint == null)
{
await next(context);
return;
}
var rateLimitingEndpoint = originalEndpoint == null
? fallbackEndpoint
: endpointCache.GetValue(originalEndpoint, endpoint => CreateRateLimitingEndpoint(endpoint, rateLimitingMetadata, displayName));
context.SetEndpoint(rateLimitingEndpoint);
try
{
await next(context);
}
finally
{
if (ReferenceEquals(context.GetEndpoint(), rateLimitingEndpoint))
context.SetEndpoint(originalEndpoint);
}
});
});
}
private static PathString NormalizeRoutePrefixPath(string routePrefix)
{
var value = routePrefix.Trim().Trim('/');
return string.IsNullOrEmpty(value) ? PathString.Empty : new PathString("/" + value);
}
private static void ConfigureWorkflowsApi(Config config, string routePrefix)
{
config.Endpoints.RoutePrefix = routePrefix;
config.Serializer.RequestDeserializer = DeserializeRequestAsync;
config.Serializer.ResponseSerializer = SerializeRequestAsync;
config.Binding.ValueParserFor<DateTimeOffset>(s =>
new(DateTimeOffset.TryParse(s.ToString(), CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result), result));
}
private static Endpoint CreateRateLimitingEndpoint(Endpoint? originalEndpoint, EnableRateLimitingAttribute rateLimitingMetadata, string displayName)
{
var metadata = originalEndpoint == null
? new EndpointMetadataCollection(rateLimitingMetadata)
: new EndpointMetadataCollection(originalEndpoint.Metadata.Where(x => x is not EnableRateLimitingAttribute and not DisableRateLimitingAttribute).Concat([rateLimitingMetadata]));
if (originalEndpoint is RouteEndpoint routeEndpoint)
return new RouteEndpoint(routeEndpoint.RequestDelegate ?? NotFoundRequestDelegate, routeEndpoint.RoutePattern, routeEndpoint.Order, metadata, routeEndpoint.DisplayName ?? displayName);
return new Endpoint(originalEndpoint?.RequestDelegate ?? NotFoundRequestDelegate, metadata, originalEndpoint?.DisplayName ?? displayName);
}
private static ValueTask<object?> DeserializeRequestAsync(HttpRequest httpRequest, Type modelType, JsonSerializerContext? serializerContext, CancellationToken cancellationToken)
{
var serializer = httpRequest.HttpContext.RequestServices.GetRequiredService<IApiSerializer>();
var options = serializer.GetOptions();
return serializerContext == null
? JsonSerializer.DeserializeAsync(httpRequest.Body, modelType, options, cancellationToken)
: JsonSerializer.DeserializeAsync(httpRequest.Body, modelType, serializerContext, cancellationToken);
}
private static Task SerializeRequestAsync(HttpResponse httpResponse, object? dto, string contentType, JsonSerializerContext? serializerContext, CancellationToken cancellationToken)
{
var serializer = httpResponse.HttpContext.RequestServices.GetRequiredService<IApiSerializer>();
var options = serializer.GetOptions();
httpResponse.ContentType = contentType;
return serializerContext == null
? JsonSerializer.SerializeAsync(httpResponse.Body, dto, dto?.GetType() ?? typeof(object), options, cancellationToken)
: JsonSerializer.SerializeAsync(httpResponse.Body, dto, dto?.GetType() ?? typeof(object), serializerContext, cancellationToken);
}
}