diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/POST.md b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/POST.md new file mode 100644 index 0000000000..a68bc106a5 --- /dev/null +++ b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/POST.md @@ -0,0 +1,236 @@ +# Moving Background Job Execution To A Separate Application + +In this article, I will show you how to move the background job execution to a separate application. + +Here are some benefits of doing this: + +* If your background jobs consume high system resources (CPU, RAM or Disk), then you can deploy that background application to a dedicated server so it won't affect your application's performance. +* You can scale your background job application independently from your web application. For example, you can deploy multiple instances of your background job application to a Kubernetes cluster and scale it easily. + +Here are some disadvantages of doing this: + +* You need to deploy and maintain at least two applications instead of one. +* You need to implement a mechanism to share the common code between your applications. For example, you can create a shared project and add it to your applications as a project reference. + +## Source code + +You can find the source code of the application at [abpframework/abp-samples](https://github.com/abpframework/abp-samples/tree/master/SeparateBackgroundJob). + +You can check the PR to see the changes step by step: [abpframework/abp-samples#250](https://github.com/abpframework/abp-samples/pull/250) + +## Creating the Web Application + +First, we need to create a new web application using the ABP CLI: + +```bash +abp new SeparateBackgroundJob -t app +``` + +* Create a shared project named `SeparateBackgroundJob.Common.Shared` to share the `BackgroundJob` and `BackgroundJobArgs` classes between the web and job executor applications. +* Install the `Volo.Abp.BackgroundJobs.Abstractions` package to the `SeparateBackgroundJob.Common.Shared` project. + +Add the `SeparateBackgroundJobCommonSharedModule` class to the `SeparateBackgroundJob.Common.Shared` project: + +```csharp +[DependsOn(typeof(AbpBackgroundJobsAbstractionsModule))] +public class SeparateBackgroundJobCommonSharedModule : AbpModule +{ +} +``` + +Add the `MyReportJob` and `MyReportJobArgs` classes to the `SeparateBackgroundJob.Common.Shared` project: + +```csharp +public class MyReportJob : AsyncBackgroundJob, ITransientDependency +{ + public override Task ExecuteAsync(MyReportJobArgs args) + { + Logger.LogInformation("Executing MyReportJob with args: {0}", args.Content); + return Task.CompletedTask; + } +} + +public class MyReportJobArgs +{ + public string? Content { get; set; } +} +``` + +Add the `SeparateBackgroundJob.Common.Shared` project reference to the `SeparateBackgroundJob.Domain` project and add `SeparateBackgroundJobCommonSharedModule` to the `DependsOn` attribute of the `SeparateBackgroundJobDomainModule` class: + +```csharp +[DependsOn( + typeof(SeparateBackgroundJobDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule), + typeof(SeparateBackgroundJobCommonSharedModule) //Add this line +)] +public class SeparateBackgroundJobDomainModule : AbpModule +``` + +Open the `Index.cshtml` and replace the content with the following code: + +```csharp +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using SeparateBackgroundJob.Localization +@using Volo.Abp.Users +@model SeparateBackgroundJob.Web.Pages.IndexModel +@inject IHtmlLocalizer L +@inject ICurrentUser CurrentUser + +@section styles { + +} + +@section scripts { + +} + +
+ + + + Add NEW BACKGROUND JOB + + + +
+
+
+ +
+
+
+ +
+
+
+
+
+``` + +Open the `Index.cshtml.cs` and replace the content with the following code: + +```csharp +public class IndexModel : SeparateBackgroundJobPageModel +{ + private readonly IBackgroundJobManager _backgroundJobManager; + + [BindProperty(SupportsGet = true)] + public string? ReportContent { get; set; } + + public IndexModel(IBackgroundJobManager backgroundJobManager) + { + _backgroundJobManager = backgroundJobManager; + } + + public void OnGet() + { + + } + + public async Task OnPostAsync() + { + await _backgroundJobManager.EnqueueAsync(new MyReportJobArgs + { + Content = ReportContent + }); + + Alerts.Success("Job is queued!"); + } +} +``` + +Run the application and navigate to the home page. You should see the following page: + +![1](images/1.png) + +When you enter some text and click the **Add** button, the job will be queued and executed in the web application: + +## Creating the Console Application + +Now we split the background job execution to a separate console application. + +Open the `SeparateBackgroundJobWebModule` class to disable the background job execution in the web application: + +```csharp +public class SeparateBackgroundJobWebModule : AbpModule +{ + .... + + public override void ConfigureServices(ServiceConfigurationContext context) + { + ... + + //Disable background job execution in the web application + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + } + + ... +} +``` + +* Create a new console application using the ABP CLI: + +```bash +abp new BackgroundJobExecutor -t console +``` + +* Add the `BackgroundJobExecutor` project to the solution of the web application. +* Add the `SeparateBackgroundJob.Common.Shared` project reference to the `BackgroundJobExecutor` project. +* Install the `Volo.Abp.BackgroundJobs.EntityFrameworkCore` and `Volo.Abp.EntityFrameworkCore.SqlServer` packages to the `BackgroundJobExecutor` project. + +Update the `BackgroundJobExecutorModule` class as follows: + +```csharp +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqlServerModule), + typeof(SeparateBackgroundJobCommonSharedModule) +)] +public class BackgroundJobExecutorModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.UseSqlServer(); + }); + } + + .... +} +``` + +Open the `appsettings.json` file to configure the [connection string](https://docs.abp.io/en/abp/latest/Connection-Strings#configure-the-connection-strings): + +```json +{ + "ConnectionStrings": { + "AbpBackgroundJobs": "Server=(LocalDb)\\MSSQLLocalDB;Database=SeparateBackgroundJob;Trusted_Connection=True" + } +} +``` + +> You must use the same connection string for the web application, `AbpBackgroundJobs` is the default connection string name for the background job module. + +The solution structure should look like this: + +![solution](images/solution.png) + +Now, run the web and console application. When you enter some text and click the **Add** button, the job will be queued and executed in the console application: + +![2](images/2.png) diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/1.png b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/1.png new file mode 100644 index 0000000000..37089353eb Binary files /dev/null and b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/1.png differ diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/2.png b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/2.png new file mode 100644 index 0000000000..0e56eee637 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/2.png differ diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/solution.png b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/solution.png new file mode 100644 index 0000000000..ab7abe9a89 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/solution.png differ