Consequential Operations Guidelines

What is the best way to perform multiple tasks together, and if one task fails, should the following tasks not be performed? I know if these were database operations, then I had to use transactions, but I'm talking about different types of operations, such as:

All tasks must pass:

SendEmail ArchiveReportsInDatabase CreateAFile

In the above scenario, all tasks must pass, or the entire batch operation must be rolled back.

+3
source share
10 answers

Exceptions are generally good for this kind of thing. Pseudo-Java / JavaScript / C ++ code:

try {
    if (!SendEmail()) {
        throw "Could not send e-mail";
    }

    if (!ArchiveReportsInDatabase()) {
        throw "Could not archive reports in database";
    }

    if (!CreateAFile()) {
        throw "Could not create file";
    }

    ...

} catch (Exception) {
    LogError(Exception);
    ...
}

It is better if your methods themselves throw exceptions:

try {
    SendEmail();
    ArchiveReportsInDatabase();
    CreateAFile();
    ...

} catch (Exception) {
    LogError(Exception);
    ...
}

, , ; . .

, , , ..

0

- AFAIK, . 2- , , .

, , 2PC . , RDBMS .

, ... :

class Compensator {
   Action Action { get; set; }
   Action Compensate { get; set; }
}

Queue<Compensator> actions = new Queue<Compensator>(new Compensator[] { 
   new Compensator(SendEmail, UndoSendEmail),
   new Compensator(ArchiveReportsInDatabase, UndoArchiveReportsInDatabase),
   new Compensator(CreateAFile, UndoCreateAFile)
});

Queue<Compensator> doneActions = new Queue<Compensator>();
while (var c = actions.Dequeue() != null) {
   try {
      c.Action();
      doneActions.Add(c);
   } catch {
      try {
        doneActions.Each(d => d.Compensate());
      } catch (EXception ex) {
        throw new OhCrapException("Couldn't rollback", doneActions, ex);
      }
      throw;
   }
}

, - .

System.Transactions, .

+4

#

return SendEmail() && & ArchiveResportsInDatabase() && & CreateAFile();

+2

:

try {
    task1();
    task2();
    task3();
    ...
    taskN();
}
catch (TaskFailureException e) {
    dealWith(e);
}
+1

:

- . , " X". ", , X" ", ". , , , , . "" , .

, :

try:
    SendEmail()
    try:
        ArchiveReportsInDatabase()
        try:
             CreateAFile()
        except:
            UndoArchiveReportsInDatabase()
            raise
    except:
        UndoSendEmail()
        raise
except:
    // handle failure

( , , , .)

+1

, :

  • .
  • .
  • , - .
0

, / . .NET Framework, . Concurrency Microsoft Robotics Studio, () : , , , .. , .

0

. Unix, && .

SendEmail () {
  # ...
}
ArchiveReportsInDatabase () {
  # ...
}
CreateAFile () {
  # ...
}

SendEmail && ArchiveReportsInDatabase && CreateAFile
0

, - (Java # do), :

return SendEmail() && ArchiveResportsInDatabase() && CreateAFile();

true, true , false.

0

, . , , nServiceBus MSMQ.

Basically, every step happens by sending a message to the queue. When nServiceBus finds messages waiting to be queued, it calls your Handle method appropriate for this type of message. Thus, each individual step is independent of failure and can be repeated. If one step fails, the message ends in the error queue, so you can easily repeat it later.

The proposed proposed clean codes are not so reliable, because if there is a failure in a step, you will not be able to repeat only one step in the future, and you will have to implement a rollback code, which is not even possible in some cases.

0
source

Source: https://habr.com/ru/post/1697876/


All Articles