假设有一个WebForms应用程序,其中有一个名为CreateAll()的主要方法。我可以一步一步地描述方法任务的过程:
1)数据库存储(更新/创建数据库项3至4次)
2)启动新线程
3) Result1 =调用soap服务,通过使用超时阈值检查状态,在x minutes.The继续运行之后(状态现在已确定,并不意味着失败)
4)数据库存储(更新/创建数据库项3至4次)
5) result2 =调用soap服务(以火灾和遗忘的方式)
6)更新配置文件(实际上是从result1获取的)
7)通过使用回调请求,它检查前面部分的每个checks、result2的状态和UI显示一个进度bar.If,进程完成了(100%),这意味着成功。
我认为所有这些任务都可以按照它们的type.Basically进行分组,几种类型的操作是:
我希望在现有实现中添加回滚/重试机制,并使用面向任务的体系结构和重构现有的遗留代码。
我发现,类似于Memento设计模式或C#中的命令模式可以帮助实现这一目的,我还发现msdn 重试模式描述很有趣。我真的不知道,我希望有人带我找到最安全和最好的决定.
您能建议我最好的方法来保持现有的实现和流程,但将其包装在一个通用的抽象重试/回滚/任务列表实现中吗?
最后的实现必须能够在每种情况下重新尝试(无论在一般的createAll过程中,无论是什么任务或一般故障,例如超时等等),还有一个回滚决策列表,其中应用程序必须能够回滚所有已完成的任务。
我想要一些例子,如何打破这个耦合的代码。
PseudoCode可能会有帮助:
class something
{
static result CreateAll(object1 obj1, object2 obj2 ...)
{
//Save to database obj1
//...
//Update to database obj1
//
//NEW THREAD
//Start a new thread with obj1, obj2 ...CreateAll
//...
}
void CreateAllAsync()
{
//Type1 Save to database obj1
//...
//Type1 Update to database obj2
//Type2 Call Web Service to create obj1 on the service (not async)
while (state != null && now < times)
{
if (status == "OK")
break;
else
//Wait for X seconds
}
//Check status continue or general failure
//Type1 Update to database obj2 and obj1
//Type2 Call Web Service to create obj2 on the service (fire and forget)
//Type3 Update Configuration File
//Type1 Update to database obj2 and obj1
//..
return;
}
//Then the UI takes the responsibility to check the status of result2发布于 2016-05-23 14:55:12
查看使用波莉进行重试的场景,这些场景似乎与伪代码很好地一致。在这个答案的末尾是文档中的一个示例。您可以执行各种重试方案、重试和等待等。例如,您可以多次重试一个完整的事务,或者多次重试一组幂等操作,然后在重试策略最后失败时写入补偿逻辑。
memento模式更适合于在字处理器(Ctrl和Ctrl)中找到的撤销-重做逻辑。
其他有用的模式是一个简单的队列,一个持久的队列,甚至一个服务总线,以使您最终一致,而不必让用户等待一切顺利完成。
// Retry three times, calling an action on each retry
// with the current exception and retry count
Policy
.Handle<DivideByZeroException>()
.Retry(3, (exception, retryCount) =>
{
// do something
});基于伪代码的示例如下所示:
static bool CreateAll(object1 obj1, object2 obj2)
{
// Policy to retry 3 times, waiting 5 seconds between retries.
var policy =
Policy
.Handle<SqlException>()
.WaitAndRetry(3, count =>
{
return TimeSpan.FromSeconds(5);
});
policy.Execute(() => UpdateDatabase1(obj1));
policy.Execute(() => UpdateDatabase2(obj2));
}发布于 2016-05-29 21:06:55
您可以选择命令模式,其中每个命令都包含所有必要的信息,如连接字符串、服务url、重试计数etc.On,可以考虑使用rx、数据流块来完成管道操作。
高层视图

更新:意图是分离关注。重试逻辑仅限于一个类,它是现有命令的包装器。您可以进行更多的分析,并提出适当的命令、调用程序和接收对象,并添加回滚功能。
public abstract class BaseCommand
{
public abstract RxObservables Execute();
}
public class DBCommand : BaseCommand
{
public override RxObservables Execute()
{
return new RxObservables();
}
}
public class WebServiceCommand : BaseCommand
{
public override RxObservables Execute()
{
return new RxObservables();
}
}
public class ReTryCommand : BaseCommand // Decorator to existing db/web command
{
private readonly BaseCommand _baseCommand;
public RetryCommand(BaseCommand baseCommand)
{
_baseCommand = baseCommand
}
public override RxObservables Execute()
{
try
{
//retry using Polly or Custom
return _baseCommand.Execute();
}
catch (Exception)
{
throw;
}
}
}
public class TaskDispatcher
{
private readonly BaseCommand _baseCommand;
public TaskDispatcher(BaseCommand baseCommand)
{
_baseCommand = baseCommand;
}
public RxObservables ExecuteTask()
{
return _baseCommand.Execute();
}
}
public class Orchestrator
{
public void Orchestrate()
{
var taskDispatcherForDb = new TaskDispatcher(new ReTryCommand(new DBCommand));
var taskDispatcherForWeb = new TaskDispatcher(new ReTryCommand(new WebCommand));
var dbResultStream = taskDispatcherForDb.ExecuteTask();
var WebResultStream = taskDispatcherForDb.ExecuteTask();
}
}发布于 2016-05-31 08:25:00
对我来说,这听起来像是“分布式事务”,因为您有不同的资源(数据库、服务通信、文件i/o),并且希望能够处理可能涉及所有资源的事务。
在C#中,您可以使用Microsoft分布式事务协调器解决这个问题。对于每个资源,您都需要一个资源管理器。对于数据库,如sql server和文件i/o,据我所知,它已经可用。对于其他人来说,你可以发展自己的。
例如,要执行这些事务,可以使用TransactionScope类,如下所示:
using (TransactionScope ts = new TransactionScope())
{
//all db code here
// if an error occurs jump out of the using block and it will dispose and rollback
ts.Complete();
}(取自这里的例子)
要开发您自己的资源管理器,您必须实现IEnlistmentNotification,这可能是一个相当复杂的任务。这里是一个简短的示例。
https://stackoverflow.com/questions/37393828
复制相似问题