From dbbb2ee33443bac9df2826bf54349c463520e197 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 21 May 2020 17:04:20 +0800 Subject: [PATCH 1/3] Update background document --- docs/en/Background-Jobs-Quartz.md | 54 +++++++++++++- docs/en/Background-Workers-Quartz.md | 84 ++++++++++++++++++++-- docs/zh-Hans/Background-Jobs-Quartz.md | 54 +++++++++++++- docs/zh-Hans/Background-Workers-Quartz.md | 86 +++++++++++++++++++++-- 4 files changed, 263 insertions(+), 15 deletions(-) diff --git a/docs/en/Background-Jobs-Quartz.md b/docs/en/Background-Jobs-Quartz.md index 8039192708..aa087ace0c 100644 --- a/docs/en/Background-Jobs-Quartz.md +++ b/docs/en/Background-Jobs-Quartz.md @@ -40,7 +40,7 @@ public class YourModule : AbpModule ## Configuration -Quartz is a very configurable library,and the ABP framework provides `AbpQuartzPreOptions` for this. You can use the `PreConfigure` method in your module class to pre-configure this option. ABP will use it when initializing the Quartz module. For example: +Quartz is a very configurable library,and the ABP framework provides `AbpQuartzOptions` for this. You can use the `PreConfigure` method in your module class to pre-configure this option. ABP will use it when initializing the Quartz module. For example: ````csharp [DependsOn( @@ -53,7 +53,7 @@ public class YourModule : AbpModule { var configuration = context.Services.GetConfiguration(); - PreConfigure(options => + PreConfigure(options => { options.Properties = new NameValueCollection { @@ -70,4 +70,52 @@ public class YourModule : AbpModule } ```` -Quartz stores job and scheduling information **in memory by default**. In the example, we use the pre-configuration of [options pattern](Options.md) to change it to the database. For more configuration of Quartz, please refer to the Quartz's [documentation](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html). \ No newline at end of file +Quartz stores job and scheduling information **in memory by default**. In the example, we use the pre-configuration of [options pattern](Options.md) to change it to the database. For more configuration of Quartz, please refer to the Quartz's [documentation](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html). + +## Exception handling + +### Default exception handling strategy + +When an exception occurs in the background job,ABP provide the **default handling strategy** retrying once every 3 seconds, up to 3 times. You can change the retry count and retry interval via `AbpBackgroundJobQuartzOptions` options: + +```csharp +[DependsOn( + //...other dependencies + typeof(AbpBackgroundJobsQuartzModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.RetryCount = 1; + options.RetryIntervalMillisecond = 1000; + }); + } +} +``` + +### Customize exception handling strategy + +You can customize the exception handling strategy via `AbpBackgroundJobQuartzOptions` options: + +```csharp +[DependsOn( + //...other dependencies + typeof(AbpBackgroundJobsQuartzModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.RetryStrategy = async (retryIndex, executionContext, exception) => + { + // customize exception handling + }; + }); + } +} +``` \ No newline at end of file diff --git a/docs/en/Background-Workers-Quartz.md b/docs/en/Background-Workers-Quartz.md index 0e9c640ee2..f8495b27a4 100644 --- a/docs/en/Background-Workers-Quartz.md +++ b/docs/en/Background-Workers-Quartz.md @@ -36,11 +36,11 @@ public class YourModule : AbpModule } ```` -### Configuration +## Configuration See [Configuration](Background-Jobs-Quartz#Configuration). -### Create a Background Worker +## Create a Background Worker A background work is a class that derives from the `QuartzBackgroundWorkerBase` base class. for example. A simple worker class is shown below: @@ -49,8 +49,8 @@ public class MyLogWorker : QuartzBackgroundWorkerBase { public MyLogWorker() { - JobDetail = JobBuilder.Create().Build(); - Trigger = TriggerBuilder.Create().StartNow().Build(); + JobDetail = JobBuilder.Create().WithIdentity(nameof(MyLogWorker)).Build(); + Trigger = TriggerBuilder.Create().WithIdentity(nameof(MyLogWorker)).StartNow().Build(); } public override Task Execute(IJobExecutionContext context) @@ -63,6 +63,82 @@ public class MyLogWorker : QuartzBackgroundWorkerBase We simply implemented the Execute method to write a log. The background worker is a **singleton by default**. If you want, you can also implement a [dependency interface](Dependency-Injection#DependencyInterfaces) to register it as another life cycle. +> Tips: Add identity to background workers is a best practice,because quartz distinguishes different jobs based on identity. + +## Add to BackgroundWorkerManager + +Default background workers are **automatically** added to the BackgroundWorkerManager when the application is **initialized**. You can set `AutoRegister` property value to `false`,if you want to add it manually: + +```` csharp +public class MyLogWorker : QuartzBackgroundWorkerBase +{ + public MyLogWorker() + { + AutoRegister = false; + JobDetail = JobBuilder.Create().WithIdentity(nameof(MyLogWorker)).Build(); + Trigger = TriggerBuilder.Create().WithIdentity(nameof(MyLogWorker)).StartNow().Build(); + } + + public override Task Execute(IJobExecutionContext context) + { + Logger.LogInformation("Executed MyLogWorker..!"); + return Task.CompletedTask; + } +} +```` + +If you want to globally disable auto add worker, you can global disable via `AbpBackgroundWorkerQuartzOptions` options: + +```csharp +[DependsOn( + //...other dependencies + typeof(AbpBackgroundWorkersQuartzModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsAutoRegisterEnabled = false; + }); + } +} +``` + +## Advanced topics + +### Customize ScheduleJob + +Assume you have a worker executes every 10 minutes,but because server is unavailable for 30 minutes, 3 executions are missed. You want to execute all missed times after the server is available. You should define your background worker like this: + +```csharp +public class MyLogWorker : QuartzBackgroundWorkerBase +{ + public MyLogWorker() + { + JobDetail = JobBuilder.Create().WithIdentity(nameof(MyLogWorker)).Build(); + Trigger = TriggerBuilder.Create().WithIdentity(nameof(MyLogWorker)).WithSimpleSchedule(s=>s.WithIntervalInMinutes(1).RepeatForever().WithMisfireHandlingInstructionIgnoreMisfires()).Build(); + + ScheduleJob = async scheduler => + { + if (!await scheduler.CheckExists(JobDetail.Key)) + { + await scheduler.ScheduleJob(JobDetail, Trigger); + } + }; + } + + public override Task Execute(IJobExecutionContext context) + { + Logger.LogInformation("Executed MyLogWorker..!"); + return Task.CompletedTask; + } +} +``` + +In the example we defined the worker execution interval to be 10 minutes and set `WithMisfireHandlingInstructionIgnoreMisfires`. we customized `ScheduleJob` and add worker to quartz only when the background worker does not exist. + ### More Please see Quartz's [documentation](https://www.quartz-scheduler.net/documentation/index.html) for more information. diff --git a/docs/zh-Hans/Background-Jobs-Quartz.md b/docs/zh-Hans/Background-Jobs-Quartz.md index 906d0b2d1f..61de4548f5 100644 --- a/docs/zh-Hans/Background-Jobs-Quartz.md +++ b/docs/zh-Hans/Background-Jobs-Quartz.md @@ -40,7 +40,7 @@ public class YourModule : AbpModule ## 配置 -Quartz是一个可配置的类库,对此ABP框架提供了 `AbpQuartzPreOptions`. 你可以在模块预配置此选项,ABP在初始化Quartz模块时将使用它. 例: +Quartz是一个可配置的类库,对此ABP框架提供了 `AbpQuartzOptions`. 你可以在模块预配置此选项,ABP在初始化Quartz模块时将使用它. 例: ````csharp [DependsOn( @@ -53,7 +53,7 @@ public class YourModule : AbpModule { var configuration = context.Services.GetConfiguration(); - PreConfigure(options => + PreConfigure(options => { options.Properties = new NameValueCollection { @@ -70,4 +70,52 @@ public class YourModule : AbpModule } ```` -Quartz**默认**将作业与调度信息存储在**内存**中,示例中我们使用[选项模式](Options.md)的预配置将其更改为存储到数据库中. 有关Quartz的更多配置请参阅[Quartz文档](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html). \ No newline at end of file +Quartz**默认**将作业与调度信息存储在**内存**中,示例中我们使用[选项模式](Options.md)的预配置将其更改为存储到数据库中. 有关Quartz的更多配置请参阅[Quartz文档](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html). + +## 异常处理 + +### 默认异常处理策略 + +当后台作业发生异常时ABP提供了**默认**异常处理策略,它会为你的作业重试3次,每次间隔3秒. 你可以通过 `AbpBackgroundJobQuartzOptions` 更改默认重试次数与间隔时间: + +```csharp +[DependsOn( + //...other dependencies + typeof(AbpBackgroundJobsQuartzModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.RetryCount = 1; + options.RetryIntervalMillisecond = 1000; + }); + } +} +``` + +### 自定义异常处理策略 + +你可以通过 `AbpBackgroundJobQuartzOptions` 选项自定义异常处理策略: + +```csharp +[DependsOn( + //...other dependencies + typeof(AbpBackgroundJobsQuartzModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.RetryStrategy = async (retryIndex, executionContext, exception) => + { + // customize exception handling + }; + }); + } +} +``` \ No newline at end of file diff --git a/docs/zh-Hans/Background-Workers-Quartz.md b/docs/zh-Hans/Background-Workers-Quartz.md index 4799633b07..196d0e1d07 100644 --- a/docs/zh-Hans/Background-Workers-Quartz.md +++ b/docs/zh-Hans/Background-Workers-Quartz.md @@ -36,11 +36,11 @@ public class YourModule : AbpModule } ```` -### 配置 +## 配置 参阅[配置](Background-Jobs-Quartz.md#配置). -### 创建后台工作者 +## 创建后台工作者 后台工作者是一个继承自 `QuartzBackgroundWorkerBase` 基类的类. 一个简单的工作者如下所示: @@ -49,8 +49,8 @@ public class MyLogWorker : QuartzBackgroundWorkerBase { public MyLogWorker() { - JobDetail = JobBuilder.Create().Build(); - Trigger = TriggerBuilder.Create().StartNow().Build(); + JobDetail = JobBuilder.Create().WithIdentity(nameof(MyLogWorker)).Build(); + Trigger = TriggerBuilder.Create().WithIdentity(nameof(MyLogWorker)).StartNow().Build(); } public override Task Execute(IJobExecutionContext context) @@ -63,6 +63,82 @@ public class MyLogWorker : QuartzBackgroundWorkerBase 示例中我们重写了 `Execute` 方法写入日志. 后台工作者默认是**单例**. 如果你需要,也可以实现[依赖接口](Dependency-Injection.md#依赖接口)将其注册为其他的生命周期. -### 更多 +> 提示: 为后台工作者添加标识是最佳实践,Quartz根据标识区分作业. 如果未指定标识会重复添加工作者到Quartz. + +## 添加到BackgroundWorkerManager + +默认后台工作者会在应用程序启动时**自动**添加到 `BackgroundWorkerManager`,如果你想要手动添加,可以将 `AutoRegister` 属性值设置为 `false`: + +```` csharp +public class MyLogWorker : QuartzBackgroundWorkerBase +{ + public MyLogWorker() + { + AutoRegister = false; + JobDetail = JobBuilder.Create().WithIdentity(nameof(MyLogWorker)).Build(); + Trigger = TriggerBuilder.Create().WithIdentity(nameof(MyLogWorker)).StartNow().Build(); + } + + public override Task Execute(IJobExecutionContext context) + { + Logger.LogInformation("Executed MyLogWorker..!"); + return Task.CompletedTask; + } +} +```` + +尽管你可以使用 `AutoRegister` 跳过自动添加,但如果你想要全局禁用这样会比较繁琐. 你可以通过 `AbpBackgroundWorkerQuartzOptions` 选项全局禁用: + +```csharp +[DependsOn( + //...other dependencies + typeof(AbpBackgroundWorkersQuartzModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsAutoRegisterEnabled = false; + }); + } +} +``` + +## 高级主题 + +### 自定义ScheduleJob + +例如你有一个每10分钟执行一次的工作者,但由于服务器不可用30分钟导致工作者错过了3次执行,你想要在服务器恢复正常后执行所有错过的执行. 你应该这样定义你的工作者: + +```csharp +public class MyLogWorker : QuartzBackgroundWorkerBase +{ + public MyLogWorker() + { + JobDetail = JobBuilder.Create().WithIdentity(nameof(MyLogWorker)).Build(); + Trigger = TriggerBuilder.Create().WithIdentity(nameof(MyLogWorker)).WithSimpleSchedule(s=>s.WithIntervalInMinutes(1).RepeatForever().WithMisfireHandlingInstructionIgnoreMisfires()).Build(); + + ScheduleJob = async scheduler => + { + if (!await scheduler.CheckExists(JobDetail.Key)) + { + await scheduler.ScheduleJob(JobDetail, Trigger); + } + }; + } + + public override Task Execute(IJobExecutionContext context) + { + Logger.LogInformation("Executed MyLogWorker..!"); + return Task.CompletedTask; + } +} +``` + +在示例中我们定义了工作者执行间隔为10分钟,并且设置 `WithMisfireHandlingInstructionIgnoreMisfires` ,另外自定义 `ScheduleJob` 仅当工作者不存在时向quartz添加调度作业. + +## 更多 参阅Quartz[文档](https://www.quartz-scheduler.net/documentation/index.html)了解更多信息. \ No newline at end of file From 43e20fe59b0bbbe2f0cb5ed14e07c639b7dbac6e Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Mon, 25 May 2020 20:04:52 +0300 Subject: [PATCH 2/3] fix broken link for iOS Simulator --- docs/en/Getting-Started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Getting-Started.md b/docs/en/Getting-Started.md index fa7f47f276..d4f9a6d5b7 100644 --- a/docs/en/Getting-Started.md +++ b/docs/en/Getting-Started.md @@ -398,7 +398,7 @@ Wait Expo CLI to start. Expo CLI opens the management interface on the `http://l In the above management interface, you can start the application with an Android emulator, an iOS simulator or a physical phone by the scan the QR code with the [Expo Client](https://expo.io/tools#client). -> See the [Android Studio Emulator](https://docs.expo.io/versions/v36.0.0/workflow/android-studio-emulator/), [iOS Simulator](https://docs.expo.io/versions/v36.0.0/workflow/ios-simulator/) documents on expo.io. +> See the [Android Studio Emulator](https://docs.expo.io/versions/v36.0.0/workflow/android-studio-emulator/), [iOS Simulator](https://docs.expo.io/workflow/ios-simulator/) documents on expo.io. ![React Native login screen on iPhone 11](images/rn-login-iphone.png) From 69291673e5c3ffd3d1f3451864c3290313f4d9dd Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Mon, 25 May 2020 20:28:59 +0300 Subject: [PATCH 3/3] fix broken android emulator link --- docs/en/Getting-Started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Getting-Started.md b/docs/en/Getting-Started.md index d4f9a6d5b7..4011fd287c 100644 --- a/docs/en/Getting-Started.md +++ b/docs/en/Getting-Started.md @@ -398,7 +398,7 @@ Wait Expo CLI to start. Expo CLI opens the management interface on the `http://l In the above management interface, you can start the application with an Android emulator, an iOS simulator or a physical phone by the scan the QR code with the [Expo Client](https://expo.io/tools#client). -> See the [Android Studio Emulator](https://docs.expo.io/versions/v36.0.0/workflow/android-studio-emulator/), [iOS Simulator](https://docs.expo.io/workflow/ios-simulator/) documents on expo.io. +> See the [Android Studio Emulator](https://docs.expo.io/workflow/android-simulator/), [iOS Simulator](https://docs.expo.io/workflow/ios-simulator/) documents on expo.io. ![React Native login screen on iPhone 11](images/rn-login-iphone.png)