& Lt; ABP document & gt; background jobs and workers

Source: Internet
Author: User

<ABP document> background jobs and workers

Document directory

 

Content of this section:

  • Introduction
  • Background job
    • About job persistence
    • Create a background job
    • Add a new job to the queue
    • Default background Job Manager
      • Background job Storage
    • Configuration
      • Disable job execution
    • Hangfire Integration
  • Background worker
    • Create a background worker
    • Register background workers
    • Background worker survival mode
  • Keep your application running

 

Introduction

ABP provides background jobs and workers to execute some tasks in the application in the background thread.

 

Background job

Background jobs are arranged in a queue and persistent and stable manner for some background tasks to be executed. You may need background jobs for several reasons, such:

  • You do not need to wait for tasks that run for a long time. For example, if you press the "Report" button to start a report task that runs for a long time, you add the task to the queue, after the task is completed, send the report result to you by email.
  • To create a retried and persistent task to ensure that a code is executed, for example, you can send an email in a background job, to overcome temporary failures and ensure that they will eventually be sent, you do not have to wait when you send an email.

About job persistence

View the background job Storage section for more information about job persistence.

 

Create a background job

You can create a background job by inheriting the BackgroundJob <TArgs> class or directly implementing the IBackgroundJob <TArgs> interface.

The following is a very simple background job:

public class TestJob : BackgroundJob<int>, ITransientDependency{    public override void Execute(int number)    {        Logger.Debug(number.ToString());    }}

A background job defines an Execute method and accepts an input parameter. The parameter type is to define the parameters of the generic class, as shown in the preceding example.

A background job must be registered with dependency injection. Implementing ITransientDependency is the easiest way.

Let's define a more realistic job: send an email in the backend queue:

public class SimpleSendEmailJob : BackgroundJob<SimpleSendEmailJobArgs>, ITransientDependency{    private readonly IRepository<User, long> _userRepository;    private readonly IEmailSender _emailSender;    public SimpleSendEmailJob(IRepository<User, long> userRepository, IEmailSender emailSender)    {        _userRepository = userRepository;        _emailSender = emailSender;    }    public override void Execute(SimpleSendEmailJobArgs args)    {        var senderUser = _userRepository.Get(args.SenderUserId);        var targetUser = _userRepository.Get(args.TargetUserId);        _emailSender.Send(senderUser.EmailAddress, targetUser.EmailAddress, args.Subject, args.Body);    }}

We inject the user warehouse (which can get the user email) and the mail sender (a mail sending service), and simply send the mail. SimpleSendEmailJobArgs is the parameter of the job. Its definition is as follows:

[Serializable]public class SimpleSendEmailJobArgs{    public long SenderUserId { get; set; }    public long TargetUserId { get; set; }    public string Subject { get; set; }    public string Body { get; set; }}

Parameters of a job should be Serializable because the job is to be serialized and stored in the database. Although the Default background Job Manager uses the JSOn serializer (it does not need to use the [Serializable] feature ), [Serializable] is better defined, because we may replace it with another job manager in the future and may use it. net built-in binary serializer.

Saving your parameters is simple (such as DTO). Do not include objects or other non-serialized objects, as shown in SimpleSendEmailJob. We can only store the Id of one object, it also obtains the entity from the internal warehouse of the job.

 

Add a new job to the queue

After defining a background job, we can inject and use IBackgroundJobManager to add a job to the queue. Let's take a look at the example of using the TestJob defined above:

public class MyService{    private readonly IBackgroundJobManager _backgroundJobManager;    public MyService(IBackgroundJobManager backgroundJobManager)    {        _backgroundJobManager = backgroundJobManager;    }    public void Test()    {        _backgroundJobManager.Enqueue<TestJob, int>(42);    }}

When a queue is added, we send the parameter 42. IBackgroundManager will be materialized and run it with the parameter 42 as TestJob.

Let's take a look at the example of using SimpleSendEmailJob defined above:

[AbpAuthorize]public class MyEmailAppService : ApplicationService, IMyEmailAppService{    private readonly IBackgroundJobManager _backgroundJobManager;    public MyEmailAppService(IBackgroundJobManager backgroundJobManager)    {        _backgroundJobManager = backgroundJobManager;    }    public async Task SendEmail(SendEmailInput input)    {            await _backgroundJobManager.EnqueueAsync<SimpleSendEmailJob, SimpleSendEmailJobArgs>(            new SimpleSendEmailJobArgs            {                Subject = input.Subject,                Body = input.Body,                SenderUserId = AbpSession.GetUserId(),                TargetUserId = input.TargetUserId            });    }}

Enqueue (or EnqueueAsync) has other parameters, such as priority and delay.

 

Default background Job Manager

By default, BackgroundJobManager implements IBackgroundJobManager, which can be replaced by other backend job providers (view the Hangfire document ). Some information about the default BackgroudJobManager is as follows:

  • It is a simple job queue that uses a FIFO (first-in-first-out) Single-threaded job. It uses IBackgroundJobStore to persist jobs (see the next section ).
  • It retries the job until the job runs successfully (only logs do not throw an exception) or times out. By default, the job times out for 2 days.
  • After the job runs successfully, it deletes the job from the storage (database). If the job times out, it is set to "abandoned" and then leaves the database.
  • It increases the waiting time between retrying a job. It retries for the first time, waits for 1 minute, retries for the second time, waits for 2 minutes, retries for the third time, waits for 4 minutes, and so on.
  • It polls the storage of jobs at a fixed interval, queries jobs in the order of priority (ascending), and then ranks jobs by number of attempts (programs.

 

Background job Storage

The default BackgroundJobManager requires a data storage to store and obtain jobs. If you do not implement IBackgroundJobStore, it uses InMemoryBackgroundJobStore, which does not store jobs in persistent databases, you can simply implement this interface to store jobs in a database or use the module-zero that has implemented this interface.

If you use a third-party Job Manager (such as Hangfire), you do not need to implement IBackgroundJobStore.

 

Configuration

You can use Configuration. BackgroundJobs to configure your background job system in the PreInitialize method of the module.

 

Disable job execution

You may want to disable background job execution for your application:

public class MyProjectWebModule : AbpModule{    public override void PreInitialize()    {        Configuration.BackgroundJobs.IsJobExecutionEnabled = false;    }    //...}

This is rarely needed, but consider that you are running multiple instances of an application and accessing the same database. In this case, each application will query jobs in the same database and execute them, this may cause multiple executions of the same job and some other problems. To prevent this situation, we have two options:

  • You can only allow one instance of the application to complete job execution.
  • You can disable all instances of an application to execute jobs and create an application (such as a windows Service) to execute background jobs.

 

Hangfire Integration

The background job manager is designed to be replaced by other background managers. You can view how the Hangfire Integration document is replaced by Hangfire.

 

Background worker

Different from background jobs, background workers simply depend on the threads where applications run in the background. Generally, they define to execute some tasks, such:

  • A background worker can regularly delete old logs.
  • A background worker can regularly detect inactive users and then send an email to them to re-use your application.

 

Create a background worker

To create a background worker, we should implement the IBackgroundWorker interface. We can also choose to inherit directly from the BackgroundWorkerBase or PeriodicBackgroundWorkerBase base class.

Suppose we want to set users who have not logged on for more than 30 days as "negative", the Code is as follows:

public class MakeInactiveUsersPassiveWorker : PeriodicBackgroundWorkerBase, ISingletonDependency{    private readonly IRepository<User, long> _userRepository;    public MakeInactiveUsersPassiveWorker(AbpTimer timer, IRepository<User, long> userRepository)        : base(timer)    {        _userRepository = userRepository;        Timer.Period = 5000; //5 seconds (good for tests, but normally will be more)    }    [UnitOfWork]    protected override void DoWork()    {        using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))        {            var oneMonthAgo = Clock.Now.Subtract(TimeSpan.FromDays(30));            var inactiveUsers = _userRepository.GetAllList(u =>                u.IsActive &&                ((u.LastLoginTime < oneMonthAgo && u.LastLoginTime != null) || (u.CreationTime < oneMonthAgo && u.LastLoginTime == null))                );            foreach (var inactiveUser in inactiveUsers)            {                inactiveUser.IsActive = false;                Logger.Info(inactiveUser + " made passive since he/she did not login in last 30 days.");            }            CurrentUnitOfWork.SaveChanges();        }    }}

 

This is a piece of real code, which works in module-zero of ABP.

  • If you inherit from PeriodicBackgroundWorkerBase (in this example), you need to implement the DoWork method to perform your regular work.
  • If you inherit from BackgroundWorkerBase or directly implement IBackgroundWorker, You need to rewrite/implement the Start, Stop, and WaitToStop methods. The Start and Stop methods should be non-blocking, the WaitToStop method needs to wait for the worker to complete its current work.

 

Register background workers

After creating a background worker, you need to add it to IBackgroundWorkerManager, which is very common in the PostInitialize method of your module:

public class MyProjectWebModule : AbpModule{    //...    public override void PostInitialize()    {        var workManager = IocManager.Resolve<IBackgroundWorkerManager>();        workManager.Add(IocManager.Resolve<MakeInactiveUsersPassiveWorker>());    }}

 

Although we usually add workers in PostInitialize, it is not necessary. You can inject IBackgroundWorkerManager anywhere and then add workers at runtime.

When your application is disabled, IBackgroundWorkerManager stops and releases all registered workers.

 

Background worker survival mode

Backend workers are created in the singleton mode, but this is not the case. If you need multiple instances of the same worker class, you can make it "temporary" and add multiple instances to IBackgroundWorkermanager. In this case, your worker may need parameters (assuming you have a separate LogCleaner class, but there are two LogCleaner worker instances used to monitor and delete different log Directories ).

 

Keep your application running

Only background jobs and workers can work when your application is running. If a Web application does not receive an access request for a long time, it is disabled by default, if your host background job runs in your web application (this is the default behavior), make sure that your web application is configured to run continuously. Otherwise, background jobs can only work when your application is in use.

Here, some technologies can do this. A very simple method is to regularly access your Web application from an external application so that you can always check whether your web application is running. The Hangfire document explains some other methods.

 

Kid1412 Appendix: http://www.aspnetboilerplate.com/Pages/Documents/Background-Jobs-And-Workers

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.