diff --git a/README.md b/README.md
index 107ddcb..e48455d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,96 @@
-# DfE.CoreLibs
+DfE Core Libraries
+==================
+
+This repository consists of a .NET solution containing multiple class libraries, with each library published as a standalone NuGet package. The libraries follow the naming convention: `DfE.CoreLibs.{library_name}`.
+
+Adding a New Library to the Repository
+--------------------------------------
+
+To add a new library to this repository and automatically publish it as a NuGet package, follow these steps:
+
+1. **Create a new library** in the `src` folder in the root of the solution.
+2. **Copy the two YAML workflow files** used for other libraries (e.g., from `Caching`) into your new library directory, and modify them as needed to match your new library.
+
+### File 1: `build-test-{library_name}.yml`
+
+For example, if your new library is called "FileService," name the file `build-test-FileService.yml`.
+
+#### Example Content (Replace with your library name):
+
+```yaml
+ name: Build DfE.CoreLibs.FileService
+
+ on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'src/DfE.CoreLibs.FileService/**'
+
+ jobs:
+ build-and-test:
+ uses: ./.github/workflows/build-test-template.yml
+ with:
+ project_name: DfE.CoreLibs.FileService
+ project_path: src/DfE.CoreLibs.FileService
+ sonar_project_key: DFE-Digital_corelibs-fileservice
+ secrets:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+```
+
+
+Make sure to:
+
+* Replace `DfE.CoreLibs.FileService` with your new library name.
+* Ensure the path to the new library is correct.
+
+### File 2: `pack-{library_name}.yml`
+
+For example, name the file `pack-FileService.yml` for your new library.
+
+#### Example Content (Replace with your library name):
+
+```yaml
+ name: Pack DfE.CoreLibs.FileService
+
+ on:
+ workflow_run:
+ workflows: ["Build DfE.CoreLibs.FileService"]
+ types:
+ - completed
+
+ jobs:
+ build-and-package:
+ uses: ./.github/workflows/nuget-package-template.yml
+ with:
+ project_name: DfE.CoreLibs.FileService
+ project_path: src/DfE.CoreLibs.FileService
+ nuget_package_name: DfE.CoreLibs.FileService
+```
+
+
+Workflows Explanation
+---------------------
+
+* **Build and Test Workflow** (`build-test-{library_name}.yml`): This workflow is responsible for building and testing your library.
+* **Pack Workflow** (`pack-{library_name}.yml`): This workflow handles versioning and packaging of your library, but it only runs after the build and test workflow successfully completes.
+
+Versioning and Auto-Publishing
+------------------------------
+
+* **Initial Versioning:** The first time your library is published, the version will start at `1.0.0`.
+* **Automatic Increment:** With subsequent changes, the patch version will increment automatically (e.g., `1.0.1`, `1.0.2`, and so on).
+* **Custom Version Bumps:** To bump the **minor** or **major** version of your library, follow these steps:
+ 1. Make the necessary changes in your library.
+ 2. Commit your changes with a message like the following:
+
+ (#update {Project_Name} package version to {version_number})
+
+ Example:
+
+ (#update DfE.CoreLibs.FileService package version to 1.1.0)
+
+
+The packaging workflow will then automatically set the version to `1.1.0` and increment the patch part (`1.1.x`) with each further change.
\ No newline at end of file
diff --git a/src/DfE.CoreLibs.BackgroundService/DfE.CoreLibs.BackgroundService.csproj b/src/DfE.CoreLibs.BackgroundService/DfE.CoreLibs.BackgroundService.csproj
index 5ecfff2..32a7244 100644
--- a/src/DfE.CoreLibs.BackgroundService/DfE.CoreLibs.BackgroundService.csproj
+++ b/src/DfE.CoreLibs.BackgroundService/DfE.CoreLibs.BackgroundService.csproj
@@ -4,6 +4,10 @@
net8.0
enable
enable
+ readme.md
+
DfE.CoreLibs.BackgroundService
+ This package provides a robust framework for implementing long-running background tasks in .NET applications. It simplifies the development of background services by offering reusable components that streamline task scheduling, execution, and error handling. Ideal for any project requiring background processing, it ensures reliability and scalability across different environments.
+ DFE-Digital
@@ -14,4 +18,10 @@
+
+
+ Always
+
+
+
diff --git a/src/DfE.CoreLibs.BackgroundService/readme.md b/src/DfE.CoreLibs.BackgroundService/readme.md
new file mode 100644
index 0000000..51deac9
--- /dev/null
+++ b/src/DfE.CoreLibs.BackgroundService/readme.md
@@ -0,0 +1,85 @@
+# DfE.CoreLibs.BackgroundService
+
+This library provides a robust framework for implementing long-running background tasks in .NET applications. It simplifies the development of background services by offering reusable components that streamline task scheduling, execution, and error handling. Ideal for any project requiring background processing, it ensures reliability and scalability across different environments.
+
+## Installation
+
+To install the DfE.CoreLibs.BackgroundService Library, use the following command in your .NET project:
+
+```sh
+dotnet add package DfE.CoreLibs.BackgroundService
+```
+
+## Usage
+
+
+**Usage in a Command Handler**
+
+1. **Service Registration:** You use a background service factory to enqueue tasks. Register the factory in your `Program.cs`:
+
+ ```csharp
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddBackgroundService();
+ }
+ ```
+
+
+2. **Implementation in the Handler:** You enqueue tasks using `IBackgroundServiceFactory` directly inside a command handler, optionally you can pass in an event to be raised when the task is completed, as shown in your code:
+
+ ```csharp
+ public class CreateReportCommandHandler : IRequestHandler
+ {
+ private readonly IBackgroundServiceFactory _backgroundServiceFactory;
+
+ public CreateReportCommandHandler(IBackgroundServiceFactory backgroundServiceFactory)
+ {
+ _backgroundServiceFactory = backgroundServiceFactory;
+ }
+
+ public Task Handle(CreateReportCommand request, CancellationToken cancellationToken)
+ {
+ var taskName = "Create_Report_Task1";
+
+ _backgroundServiceFactory.EnqueueTask(
+ async () => await (new CreateReportExampleTask()).RunAsync(taskName),
+ result => new CreateReportExampleTaskCompletedEvent(taskName, result)
+ );
+
+ return Task.FromResult(true);
+ }
+ }
+ ```
+
+3. **Events:** The background service triggers events when a task is completed. For example:
+
+ ```csharp
+ public class CreateReportExampleTaskCompletedEvent : IBackgroundServiceEvent
+ {
+ public string TaskName { get; }
+ public string Message { get; }
+
+ public CreateReportExampleTaskCompletedEvent(string taskName, string message)
+ {
+ TaskName = taskName;
+ Message = message;
+ }
+ }
+ ```
+
+4. **Event Handlers:** These events are processed by event handlers. Here's an example of how you handle task completion events:
+
+ ```csharp
+ public class SimpleTaskCompletedEventHandler : IBackgroundServiceEventHandler
+ {
+ public Task Handle(CreateReportExampleTaskCompletedEvent notification, CancellationToken cancellationToken)
+ {
+ Console.WriteLine($"Event received for Task: {notification.TaskName}, Message: {notification.Message}");
+ return Task.CompletedTask;
+ }
+ }
+ ```
+
+This setup allows you to enqueue tasks in the background, fire events when tasks complete, and handle those events using a custom event handler architecture.
+
+* * *
\ No newline at end of file
diff --git a/src/DfE.CoreLibs.Caching/DfE.CoreLibs.Caching.csproj b/src/DfE.CoreLibs.Caching/DfE.CoreLibs.Caching.csproj
index e4ae1de..9e97bc9 100644
--- a/src/DfE.CoreLibs.Caching/DfE.CoreLibs.Caching.csproj
+++ b/src/DfE.CoreLibs.Caching/DfE.CoreLibs.Caching.csproj
@@ -4,6 +4,10 @@
net8.0
enable
enable
+ readme.md
+ DfE.CoreLibs.Caching
+ This caching library offers a unified, efficient caching solution for .NET projects. It provides a simple, reusable abstraction over different caching mechanisms, enabling developers to easily implement in-memory and distributed caching strategies, improving the performance and scalability of their applications.
+ DFE-Digital
@@ -15,4 +19,10 @@
+
+
+ Always
+
+
+
diff --git a/src/DfE.CoreLibs.Caching/readme.md b/src/DfE.CoreLibs.Caching/readme.md
new file mode 100644
index 0000000..facbc15
--- /dev/null
+++ b/src/DfE.CoreLibs.Caching/readme.md
@@ -0,0 +1,79 @@
+# DfE.CoreLibs.Caching
+
+This caching library offers a unified, efficient caching solution for .NET projects. It provides a simple, reusable abstraction over different caching mechanisms, enabling developers to easily implement in-memory and distributed caching strategies, improving the performance and scalability of their applications.
+
+## Installation
+
+To install the DfE.CoreLibs.Caching Library, use the following command in your .NET project:
+
+```sh
+dotnet add package DfE.CoreLibs.Caching
+```
+
+## Usage
+
+
+**Usage in Handlers**
+
+1. **Service Registration:** You use `ICacheService` in your handlers to store and retrieve data from memory to avoid unnecessary processing and database queries. Here's how you register the caching service:
+
+
+ ```csharp
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddServiceCaching(config);
+ }
+ ```
+
+
+2. **Usage in Handlers:** Here's an example of how caching is used in one of your query handlers:
+
+ ```csharp
+ public class GetPrincipalBySchoolQueryHandler(
+ ISchoolRepository schoolRepository,
+ IMapper mapper,
+ ICacheService cacheService)
+ : IRequestHandler
+ {
+ public async Task Handle(GetPrincipalBySchoolQuery request, CancellationToken cancellationToken)
+ {
+ var cacheKey = $"Principal_{CacheKeyHelper.GenerateHashedCacheKey(request.SchoolName)}";
+
+ var methodName = nameof(GetPrincipalBySchoolQueryHandler);
+
+ return await cacheService.GetOrAddAsync(cacheKey, async () =>
+ {
+ var principal= await schoolRepository
+ .GetPrincipalBySchoolAsync(request.SchoolName, cancellationToken);
+
+ var result = mapper.Map(principal);
+
+ return result;
+ }, methodName);
+ }
+ }
+ ```
+
+In this case, the query handler checks if the principals are cached by generating a unique cache key. If the data is not cached, it retrieves the data from the repository, caches it, and returns it.
+
+### Cache Duration Based on Method Name
+
+The caching service dynamically determines the cache duration based on the method name. This is particularly useful when you want to apply different caching durations to different query handlers.
+In this example, the cache duration for `GetPrincipalBySchoolQueryHandler` is retrieved from the configuration using the method name. If no specific duration is defined for the method, it will fall back to the default cache duration.
+
+#### Example of Cache Settings in appsettings.json
+
+Here is the configuration for cache durations in the `appsettings.json` file:
+
+ ```csharp
+ "CacheSettings": {
+ "DefaultDurationInSeconds": 60,
+ "Durations": {
+ "GetPrincipalBySchoolQueryHandler": 86400
+ }
+ }
+ ```
+
+This setup ensures that the `GetPrincipalBySchoolQueryHandler` cache duration is set to 24 hours (86400 seconds), while other handlers will use the default duration of 60 seconds if no specific duration is configured.
+
+* * *
\ No newline at end of file
diff --git a/src/DfE.CoreLibs.Testing/DfE.CoreLibs.Testing.csproj b/src/DfE.CoreLibs.Testing/DfE.CoreLibs.Testing.csproj
index 5ecbed9..b55e958 100644
--- a/src/DfE.CoreLibs.Testing/DfE.CoreLibs.Testing.csproj
+++ b/src/DfE.CoreLibs.Testing/DfE.CoreLibs.Testing.csproj
@@ -4,6 +4,10 @@
net8.0
enable
enable
+ readme.md
+ DfE.CoreLibs.Testing
+ Designed to enhance test automation, this library provides essential utilities and frameworks for unit and integration testing in .NET. It includes tools for mocking, assertions, and common test scenarios, helping developers write cleaner, more efficient tests that improve the overall quality and stability of their applications.
+ DFE-Digital
@@ -26,4 +30,10 @@
+
+
+ Always
+
+
+
diff --git a/src/DfE.CoreLibs.Testing/readme.md b/src/DfE.CoreLibs.Testing/readme.md
new file mode 100644
index 0000000..ddf80ec
--- /dev/null
+++ b/src/DfE.CoreLibs.Testing/readme.md
@@ -0,0 +1,87 @@
+# DfE.CoreLibs.Testing
+
+Designed to enhance test automation, this library provides essential utilities and frameworks for unit and integration testing in .NET. It includes tools for mocking, assertions, and common test scenarios, helping developers write cleaner, more efficient tests that improve the overall quality and stability of their applications.
+
+## Installation
+
+To install the DfE.CoreLibs.Testing Library, use the following command in your .NET project:
+
+```sh
+dotnet add package DfE.CoreLibs.Testing
+```
+
+## Usage
+
+### Usage of Customization Attributes
+
+In your tests, you can use `CustomAutoData` to easily inject customizations like `AutoMapperCustomization`, this Customization scans your assembly for profiles and registers them automatically.
+
+```csharp
+ [Theory]
+ [CustomAutoData(
+ typeof(PrincipalCustomization),
+ typeof(SchoolCustomization),
+ typeof(AutoMapperCustomization))]
+ public async Task Handle_ShouldReturnMemberOfParliament_WhenSchoolExists(
+ [Frozen] ISchoolRepository mockSchoolRepository,
+ [Frozen] ICacheService mockCacheService,
+ GetPrincipalBySchoolQueryHandler handler,
+ GetPrincipalBySchoolQuery query,
+ Domain.Entities.Schools.School school,
+ IFixture fixture)
+ {
+ // Arrange
+ var expectedMp = fixture.Customize(new PrincipalCustomization()
+ {
+ FirstName = school.NameDetails.NameListAs!.Split(",")[1].Trim(),
+ LastName = school.NameDetails.NameListAs.Split(",")[0].Trim(),
+ SchoolName = school.SchoolName,
+ }).Create();
+
+ // Act
+ var result = await handler.Handle(query, default);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(expectedMp.FirstName, result.FirstName);
+ Assert.Equal(expectedMp.LastName, result.LastName);
+ }
+```
+
+
+### CustomWebApplicationDbContextFactory
+
+You can create custom factory customizations and use them like the following example, which demonstrates testing with a custom web application factory:
+
+```csharp
+ [Theory]
+ [CustomAutoData(typeof(CustomWebApplicationDbContextFactoryCustomization))]
+ public async Task GetPrincipalBySchoolAsync_ShouldReturnPrincipal_WhenSchoolExists(
+ CustomWebApplicationDbContextFactory factory,
+ ISchoolsClient schoolsClient)
+ {
+ factory.TestClaims = [new Claim(ClaimTypes.Role, "API.Read")];
+
+ // Arrange
+ var dbContext = factory.GetDbContext();
+
+ await dbContext.Schools
+ .Where(x => x.SchoolName == "Test School 1")
+ .ExecuteUpdateAsync(x => x.SetProperty(p => p.SchoolName, "NewSchoolName"));
+
+ var schoolName = Uri.EscapeDataString("NewSchoolName");
+
+ // Act
+ var result = await schoolsClient.GetPrincipalBySchoolAsync(schoolName);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("NewSchoolName", result.SchoolName);
+ }
+```
+
+This demonstrates how you can test your queries and database context interactions using a custom web application factory and test claims.
+
+For detailed examples, please refer to the [GitHub DDD-CA-Template repository](https://github.com/DFE-Digital/rsd-ddd-clean-architecture).
+
+* * *
\ No newline at end of file