2 分钟插件超时未处理异常
2 Minute Plugin Time Out Unhandled Exception
我试图通过使用 Thread.Sleep(120000) 生成超时来模拟我的插件的 2 分钟超时,但是当出现该异常时,我的 try catch 似乎无法捕获它们,甚至跳过 finally 块。
我该如何正确捕捉它,以便我可以针对此错误创建案例记录?
我试过使用不同的 catch 异常都无济于事。我什至尝试分析插件,但由于错误,它也不会分析插件。
protected override void ExecuteCrmPlugin(LocalPluginContext localContext) {
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
ITracingService tracer = localContext.TracingService;
try {
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) {
Entity entity = (Entity)context.InputParameters["Target"];
if (context.MessageName.ToLower() != "create")
return;
if (entity.LogicalName.ToLower() == Contact.EntityLogicalName) {
tracer.Trace("Sleep for 2 min");
Thread.Sleep(120000);
}
}
}
catch (System.ServiceModel.FaultException<System.TimeoutException ex) {
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
catch (System.ServiceModel.FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault ex) {
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
catch (TimeoutException e) {
throw new InvalidPluginExecutionException("A timeout has occurred during the execution of the plugin.", e);
}
catch (FaultException ex) {
throw new InvalidPluginExecutionException("Err occurred.", ex);
}
catch (Exception ex) {
tracer.Trace(ex.ToString());
throw;
}
finally {
tracer.Trace("Finally");
}
}
在 Base Class 我也有相同的 catch 块。
错误是:
Unhandled exception:
Exception type: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]
Message: An unexpected error occurred from ISV code. (ErrorType = ClientError) Unexpected exception from plug-in (Execute): MyPlugin.Plugins.PreCreateContact: System.TimeoutException: Couldn’t complete execution of the MyPlugin.Plugins.PreCreateContact plug-in within the 2-minute limit.Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ActivityId>397e0f4c-2e16-43ea-9368-ea76607820a5</ActivityId>
<ErrorCode>-2147220956</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<HelpLink i:nil="true" />
<Message>An unexpected error occurred from ISV code. (ErrorType = ClientError) Unexpected exception from plug-in (Execute): MyPlugin.Plugins.PreCreateContact: System.TimeoutException: Couldn’t complete execution of the MyPlugin.Plugins.PreCreateContact plug-in within the 2-minute limit.</Message>
<Timestamp>2019-07-17T00:49:48.360749Z</Timestamp>
<ExceptionRetriable>false</ExceptionRetriable>
<ExceptionSource>PluginExecution</ExceptionSource>
<InnerFault i:nil="true" />
<OriginalException>System.TimeoutException: Couldn’t complete execution of the MyPlugin.Plugins.PreCreateContact plug-in within the 2-minute limit.
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain, String crashOnPluginExceptionMessage)
at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain, String crashOnPluginExceptionMessage)
at Microsoft.Crm.Sandbox.SandboxWorker.<>c__DisplayClass3_0.<Execute>b__0()</OriginalException>
<TraceText>
Entered MyPlugin.Plugins.PreCreateContact.Execute(), Correlation Id: 0c2b0dd3-d27c-46ea-a7e2-90c0729b326e, Initiating User: 61e01dfa-668a-e811-8107-123456
</TraceText>
</OrganizationServiceFault>
我想一旦插件达到 2 分钟超时,我们处理任何事情的能力就结束了。这是有道理的——如果系统允许我们在 2 分钟超时后 运行 一个 catch 块,那么 catch 块可以再 运行 一分钟,或五分钟。
我采取的一种方法允许插件或自定义工作流程处理可能需要比 2 分钟超时更长的时间的方法是使用 cancellation token 在超时之前正常关闭。您可以在 115 秒时抛出自己的超时异常并优雅地取消,而不是捕获平台的超时异常。
我什至将执行状态保存为 XML 存储在注释中,并重新触发插件直至无限循环限制为 7 次。除此之外,我还创建了四个流程,每个流程每小时重复一次,间隔 15 分钟——即在主流程之后的 15、30、45 和 60 分钟。 (一个过程可以每小时重复一次而不会触发无限循环异常)。这些进程捕获在 7 运行 秒后保留其状态的任何作业,并在另外 7 秒内重新触发它们。使用这种方法,我的工作流完成了耗时数小时的计算。
请注意,这可能被视为滥用异步处理系统。我承认这有点牵强,但用例需要完全在 Dynamics 内部处理大型计算。当然,"escape" 沙盒超时的标准方法是将处理转移到外部服务(例如 Azure API、Azure Functions、Flow、Logic Apps 等)
我试图通过使用 Thread.Sleep(120000) 生成超时来模拟我的插件的 2 分钟超时,但是当出现该异常时,我的 try catch 似乎无法捕获它们,甚至跳过 finally 块。
我该如何正确捕捉它,以便我可以针对此错误创建案例记录?
我试过使用不同的 catch 异常都无济于事。我什至尝试分析插件,但由于错误,它也不会分析插件。
protected override void ExecuteCrmPlugin(LocalPluginContext localContext) {
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
ITracingService tracer = localContext.TracingService;
try {
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) {
Entity entity = (Entity)context.InputParameters["Target"];
if (context.MessageName.ToLower() != "create")
return;
if (entity.LogicalName.ToLower() == Contact.EntityLogicalName) {
tracer.Trace("Sleep for 2 min");
Thread.Sleep(120000);
}
}
}
catch (System.ServiceModel.FaultException<System.TimeoutException ex) {
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
catch (System.ServiceModel.FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault ex) {
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
catch (TimeoutException e) {
throw new InvalidPluginExecutionException("A timeout has occurred during the execution of the plugin.", e);
}
catch (FaultException ex) {
throw new InvalidPluginExecutionException("Err occurred.", ex);
}
catch (Exception ex) {
tracer.Trace(ex.ToString());
throw;
}
finally {
tracer.Trace("Finally");
}
}
在 Base Class 我也有相同的 catch 块。
错误是:
Unhandled exception:
Exception type: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]
Message: An unexpected error occurred from ISV code. (ErrorType = ClientError) Unexpected exception from plug-in (Execute): MyPlugin.Plugins.PreCreateContact: System.TimeoutException: Couldn’t complete execution of the MyPlugin.Plugins.PreCreateContact plug-in within the 2-minute limit.Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ActivityId>397e0f4c-2e16-43ea-9368-ea76607820a5</ActivityId>
<ErrorCode>-2147220956</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<HelpLink i:nil="true" />
<Message>An unexpected error occurred from ISV code. (ErrorType = ClientError) Unexpected exception from plug-in (Execute): MyPlugin.Plugins.PreCreateContact: System.TimeoutException: Couldn’t complete execution of the MyPlugin.Plugins.PreCreateContact plug-in within the 2-minute limit.</Message>
<Timestamp>2019-07-17T00:49:48.360749Z</Timestamp>
<ExceptionRetriable>false</ExceptionRetriable>
<ExceptionSource>PluginExecution</ExceptionSource>
<InnerFault i:nil="true" />
<OriginalException>System.TimeoutException: Couldn’t complete execution of the MyPlugin.Plugins.PreCreateContact plug-in within the 2-minute limit.
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain, String crashOnPluginExceptionMessage)
at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain, String crashOnPluginExceptionMessage)
at Microsoft.Crm.Sandbox.SandboxWorker.<>c__DisplayClass3_0.<Execute>b__0()</OriginalException>
<TraceText>
Entered MyPlugin.Plugins.PreCreateContact.Execute(), Correlation Id: 0c2b0dd3-d27c-46ea-a7e2-90c0729b326e, Initiating User: 61e01dfa-668a-e811-8107-123456
</TraceText>
</OrganizationServiceFault>
我想一旦插件达到 2 分钟超时,我们处理任何事情的能力就结束了。这是有道理的——如果系统允许我们在 2 分钟超时后 运行 一个 catch 块,那么 catch 块可以再 运行 一分钟,或五分钟。
我采取的一种方法允许插件或自定义工作流程处理可能需要比 2 分钟超时更长的时间的方法是使用 cancellation token 在超时之前正常关闭。您可以在 115 秒时抛出自己的超时异常并优雅地取消,而不是捕获平台的超时异常。
我什至将执行状态保存为 XML 存储在注释中,并重新触发插件直至无限循环限制为 7 次。除此之外,我还创建了四个流程,每个流程每小时重复一次,间隔 15 分钟——即在主流程之后的 15、30、45 和 60 分钟。 (一个过程可以每小时重复一次而不会触发无限循环异常)。这些进程捕获在 7 运行 秒后保留其状态的任何作业,并在另外 7 秒内重新触发它们。使用这种方法,我的工作流完成了耗时数小时的计算。
请注意,这可能被视为滥用异步处理系统。我承认这有点牵强,但用例需要完全在 Dynamics 内部处理大型计算。当然,"escape" 沙盒超时的标准方法是将处理转移到外部服务(例如 Azure API、Azure Functions、Flow、Logic Apps 等)