Retry after exception in delphi - delphi

I have a question for you.
I have a piece of code as follows.
try
//some code that fails
except
// code to retry the code that fails
end
Now I want to retry the failing code after the exception. Is it possible to do that in Delphi?
So you have a kind of loop that retries after an exception for 3/4 times. and if it didn't work at the 4th time then give an error message.

I often use this construct:
FOR I:=1 TO Retries DO BEGIN
TRY
<Code>
BREAK
EXCEPT
<Report/Log failure, prepare for next iteration>
END
END
this way, it loops around "Retries" number of times, but if it succeeds at some point, it breaks out of the loop.
The EXCEPT part should prepare for the next iteration of the retry loop (like delete any files created by the failed code, etc.), perhaps guarded by an
IF I=Retries THEN
RAISE
ELSE BEGIN
<Report/Log failure, prepare for next iteration>
END

Related

Catch back trace information without exit

I'm trying to run a series of tests and collect some meta data on each test. If there is an error during one of the tests, I would like to save the back trace information but not to exit the script. For example:
-- Example program
for _, v in ipairs(tests) do
--check some results of function calls
if v == nil then
--error("function X failed") no exit
--save back trace to variable/file
-- continue with program
end
end
I'm not currently aware if it is possible in lua to tell the function error()
not to stop after creating the back trace. Any thoughts on how to do this?
debug.traceback ([thread,] [message [, level]]) (source) is what you're looking for. You can write a function that 1. gets a traceback 2. opens a file 3. writes the traceback to the file 4. closes the file.
In that case you'd have to use a level of 2, since 0 would be the debug.traceback function, 1 would be the function calling it (i.e. your function) and 2 the funcion calling that one. message could be your error code. Then you just override the error function locally in your script and you're done; calling error will just log the error and not exit the program.
EDIT: You can also override error globally, if you want, but that might lead to unexpected results if something goes terribly wrong somewhere else (code that you didn't write yourself) and the program continues nonetheless.
You'd be better off with a construct like this:
if os.getenv 'DEBUG' then
my_error = function()
-- what I explained above
end
else
my_error = error
end
and just use my_error in all the places where you'd usually use error.

Capybara Find Within Synchronize Not Waiting

The code below keeps looping, where I would expect find to wait for its default wait time of 2 seconds before throwing an exception and having the loop iterate.
user_general.synchronize(10) do
tab_me.primary_action("Plus").click
add_edit_item.find('.ready[data-id="pageAddEditItems"]')
end
In Capybara only the outermost synchronize loop is rerun on failures, you can see this in the source code for #synchronize which does the following
if session.synchronized
yield # if we are already in a synchronize loop just run the code
else
... # catch errors and retry until max wait time expires or success
end

Suppress an error message box appearing in Delphi for a specific error

At the moment I have a Delphi form running and upon losing connection to its Database/loss of network, it re-establishes and carries on.
The service is on a timer and each minute, it pops up with message box saying failure to connected to db on network [ip address]. This is at the start of the timer, a stored proc is ran.
I have all errors writing to a log file on the service local machine, is there a way I can suppress the message box appearing as I don't need it to appear all the time? by message box it is a windows exception box not a showMessageBox(). It automatically pops up when the exception hits but it will continuously hit whilst the machine boots up and re-establishes connection to the network.
The code I have is as follows
(*Call db Procedure*)
try
db.SQL.Clear;
db.SQL.Add('call dbProc();');
db.ExecSQL;
except
On E : Exception Do
begin
If E.ClassName = 'EIBInterBaseError' Then
begin
WriteToLog('Network Error : An error has occured whilst trying to communicate with the db outside the'
+ ' loop to catch up , please see user guide V.1.0.2.145',2);
reconnectdb;
end
else if E.ClassName = 'EADOError' then
begin
WriteToLog('Network Error : An error has occured whilst trying to communicate with the db outside the'
+ ' loop to catch up , please see user guide V.1.0.2.145',2);
reconnectDB;
end;
end;
end;
Based on your description (since you did not show any code), it sounds like each iteration of your loop is raising an exception that you are not catching, so it ends up in a default exception handler within the RTL that is then displaying the popup MessageBox. If this is the case, you need to catch the original exception using a try..except block around your code that is failing.

When to give up on getting results from an external web service?

I'm using a gem to get code results from Ideone.com. The gem submits code to Ideone and then checks for the results page. It checks timeout times and then gives up if there's no result. The problem is it might give up too early, but I also don't want it to wait too long if there's not going to be a result. Is there a way to know when one should give up hope?
This is the relevant code:
begin
sleep 3 if i > 0
res = JSON.load(
Net::HTTP.post_form(
URI.parse("http://ideone.com/ideone/Index/view/id/#{loc}/ajax/1"),
{}
).body
)
i += 1
end while res['status'] != '0' && i < timeout
if i == timeout
raise IdeoneError, "Timed out while waiting for code result."
end
Sounds like you want to adjust sleep timeout and number of attempts parameters. There is no absolute values suitable for each case, so you should pick some which are most appropriate for you application.
Unfortunatelly the gem code have both this parameters (3 seconds delay and 4 attempts) hardcoded so you don't have an elegant way to change them. So you can either fork the gem and change its code or try to monkey-patch the value of TIMEOUT constant with http://apidock.com/ruby/Module/const_set . However you won't be able to monkey-patch the delay between attempts value without rewriting method .run of the gem.
FYI. Net::HTTP has their own timeouts - how much time to wait for ideone.com connection and response. If they are exceeded Net::HTTP raises Timeout exception. The setters are
http://ruby-doc.org/stdlib-2.0/libdoc/net/http/rdoc/Net/HTTP.html#method-i-read_timeout-3D and #open_timeout=.

Skip sourcecode in background (kibitz) compiler

I have a problem with the background compiler in Delphi7: in my project there is a single line of code that causes the background compiler to stop with an error message so that no CodeCompletion is possible. The normal compiler and the syntax check have no problem with this code and the resulting application is correct.
My question is if there is any way to skip this codeline when the background compilation is performed (e.g. compiler directive).
Example code to reproduce the error:
procedure ProduceKibitzError;
var
v : Variant;
begin
v.End; // This line stops kibitz compiler
end;
This code is placed in a unit "Error.pas" which is used in the main unit.
If you try to call CodeCompletion in the main-unit, it stops with the message "Error.pas could not be compiled" (real message is in german).
Interestingly the error only occurs until the project is compiled or syntax check is performed for the first time.
After compilation the CodeCompletion is working and Delphi has to be restarted to reproduce the error.
Update:
Adding an empty Assembler block with an end label is a solution for the problem.
Here is the changed example code that doesn't stop the background compiler:
procedure ProduceKibitzError;
var
v : Variant;
begin
asm
##END:
end;
v.End;
end;
Many thanks,
Christian
The background compiler does not do procedure body analysis when parsing to get to the position of the cursor. Instead, it uses simple syntax matching (such as begin/end pairs). If simple syntax matching indicates that the final end in the unit has been met, then it exits early.
This is what's happening with your example. The first End token is not escaped by the late binding logic because it's not being parsed by the real expression compiler, and instead it's being read as the end of the procedure. The second end looks like the end of the unit, and the background compiler never sees any further.
Added: You might try adding an empty asm/end block to this routine. It prevents the kibitz compiler skipping procedure analysis. Graphics.pas has an asm/end block with an ##end label, and the compiler handles asm/end blocks specially because of it.
Looks like the background compilation doesn't know what to do with the late binding.
Do you know which COM type library is used to make the call on the object? It would benefit both the compilation and the application's performance if you could export and use the pascal-wrapper unit based on the type library. (See Import Type Library option in the main menu)
Try escaping the token with & ?
so
v.&end;

Resources