Jump to content
roPopa

Is there any "standard protocol" for recovery from a failure in non atomic operations?

Recommended Posts

I have the following logical problem developing an app.
I need to do several key operations that need to be executed only once.
Lets say I need to print something on a fiscal printer.
I have several records stored on the database.
I send one command to the printer and the result is ok (was printed successfully).
I save on that specific line the fact that was printed ok, so if the program is somehow stopped, on resume that line is already printed and will be skipped from sent to printer.
However if I cannot write in the database the answer (the program crash) on resume the line will be printed again.
This operation is obvious not an atomic operation.

So I need one protocol to ensure this functionality.
Is there any?
Many thanks

Share this post


Link to post

You could use a database transaction. Begin the transaction before printing and commit the transaction after printing. Roll the transaction back if printing failed.

If a program crash occurs while printing or before the program crashes, the transaction will automatically rolled back.

  • Like 1

Share this post


Link to post
1 hour ago, roPopa said:

I have the following logical problem developing an app.
I need to do several key operations that need to be executed only once.
Lets say I need to print something on a fiscal printer.
I have several records stored on the database.
I send one command to the printer and the result is ok (was printed successfully).
I save on that specific line the fact that was printed ok, so if the program is somehow stopped, on resume that line is already printed and will be skipped from sent to printer.
However if I cannot write in the database the answer (the program crash) on resume the line will be printed again.
This operation is obvious not an atomic operation.

So I need one protocol to ensure this functionality.
Is there any?
Many thanks

A kind of transaction log saved to local storage (a file) may serve your purpose. You can write entries to a file using a write  followed by a flush operation (or a full open - write - close cycle) . While not very fast it will ensure the entry is either written completely or not all (if the PC suffers a power failure, for example).

Your operation would then follow this scheme:

  • Write the intent to print, with the ID of the item to print, to the log
  • print the item
  • write the success of the operation to the log
  • save it to the database
  • write an end of transactio to the log or delete the log

On (re)start the program can then look for a transaction log and analyse it to see how far it got on the last run.

 

Edited by PeterBelow

Share this post


Link to post

In my opinion, in these situation you sometimes have to ask the user. Even when data is sent to printer, it does not mean it was really printed OK (out of paper, damaged printout...).

Edited by Vandrovnik

Share this post


Link to post

I'm afraid there's no 100% reliable solution. There always could be points where atomicity could be broken (print succeeded - app crashed - oops)

Share this post


Link to post

Maybe a state variable and a work queue?  You would add to the work queue the item that needs to be processed and its current state.  Somewhere in your application (maybe a separate thread or on idle) loop through the queue and investigate each state to see if its eligible to move to the next state or be removed from the queue.  If you persist this queue (database or file) you can then on program crash and reload determine if there is a state which would need to be restarted or not.  

Share this post


Link to post

For a good solution you must work both ends.
The application, the device and the connection between them can crash, this is why is very important to be able to query the device!

 

From your application:
1. Write down some identification ( file, table record, etc)
2. Send the data
3. Store the answer ( delete the file, update record status etc)

 

From the fiscal printer, in case of a crash you need to query the ID you sent:

a. If file exists or record is in open state then read the ID and query the device for that ID status
b. If data was not sent, the device will return with an error, in this case pick up from step 2

c. if data was sent, the device should answer properly, in this case start from step 3

 

If you can't query the device, you will get a half baked solution to your problem.
 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×