rescue how to raise further or forget an exception - exception

How do I raise an exception further in eiffel? I have 3 cases
I want to retry
a_feature
local
l_retries_count: INTEGER
do
some_potential_failing_feature
rescue
if l_retries_count <= 3 then
l_retries_count := l_retries_count + 1
retry
end
end
I want to do close db connection and ignore exception
a_feature
do
some_potential_failing_feature
rescue
db_connection.close
end
I want to do close db connection and send an email to an admin and ignore
a_feature
do
some_potential_failing_feature
rescue
db_connection.close
send_email_to_admin
end
I want to close db_connection and raise the exception further, I'll put all the cases I can think about into the above code
a_feature
local
l_retries_count: INTEGER
do
some_potential_failing_feature
rescue
if l_retries_count <= 3 then
l_retries_count := l_retries_count + 1
log_error ("Error, retrying for " + l_retries_count.out + "th time")
retry
else
db_connection.close
send_email_to_admin
-- raise the_created_exception_from_some_potential_failing_feature -- how do I do that?
end
end

You can try one of the following:
{EXCEPTION_MANAGER}.last_exception.original.raise
{EXCEPTION_MANAGER}.last_exception.cause.raise
{EXCEPTION_MANAGER}.last_exception.raise
The first one goes through the chain of exceptions ignoring those triggered as a result of failed routines. It might be the one you are looking for.
The next two retrieve either the cause of the current exception or the current exception itself, though it might be not the one you are looking for because it depends on the context of the exception and the nested calls.

Related

Active Record mySQL Timeout ERROR -- : worker=0 PID:(xxxxx) timeout (61s > 60s), killing

I have a async action on my controller that can perform a heavy SQL query depending on user input.
#results = ActiveRecord::Base
.connection
.select_all(query_string)
.map do |record|
Hashie::Mash.new(record)
end
When it happens, the only response I get from the server is
E, [2020-02-05T16:14:04.133233 #59909] ERROR -- : worker=0 PID:60952 timeout (61s > 60s), killing
E, [2020-02-05T16:14:04.159372 #59909] ERROR -- : reaped #<Process::Status: pid 60952 SIGKILL (signal 9)> worker=0
Is there any way I can capture this timeout on the backend, to give the user the correct feedback?
Tried using Timeout::timeout(x) but with no success.
You could add another, shorter timeout yourself and handle the situation before the worker gets killed. Something like this might be a good start:
require 'timeout'
begin
# 5 seconds before the MySQL timeout would kick in
Timeout.timeout(55) do
# have only the slow query in this block
#database_results = ActiveRecord::Base.connection.select_all(query_string)
end
rescue Timeout::Error
# Handle the timeout. Proper error handling depends on your application.
# In a controller you might just want to return an error page, in a
# background worker you might want to record the error in your database.
end
# time to translate the data should not count towards the timeout
#results = #database_results.map { |r| Hashie::Mash.new(r) }

How to throw a specific Exception in Julia

I am doing test driven development in Julia.
The test expects a certain exception to be thrown.
How do I throw the expected exception?
I'm looping through a string and counting the occurrence of specific letters.
Any letter than 'A','C','G',or'T' should result in an exception
Running Julia version 1.2.0.
I have tried these alternatives:
throw(DomainError())
throw(DomainError)
throw("DomainError")
I expected those to work based on this resource:
https://scls.gitbooks.io/ljthw/content/_chapters/11-ex8.html
Here is a link to the problem I am trying to solve:
https://exercism.io/my/solutions/781af1c1f9e2448cac57c0707aced90f
(Heads up: That link may be unique to my login)
My code:
function count_nucleotides(strand::AbstractString)
Counts = Dict()
Counts['A'] = 0
Counts['C'] = 0
Counts['G'] = 0
Counts['T'] = 0
for ch in strand
# println(ch)
if ch=='A'
Counts['A'] += 1
# Counts['A'] = Counts['A'] + 1
elseif ch=='C'
Counts['C'] += 1
elseif ch=='G'
Counts['G'] += 1
elseif ch=='T'
Counts['T'] += 1
else
throw(DomainError())
end
end
return Counts
end
The test:
#testset "strand with invalid nucleotides" begin
#test_throws DomainError count_nucleotides("AGXXACT")
end
My error report, see the lines with: Expected and Thrown.
strand with invalid nucleotides: Test Failed at /Users/username/Exercism/julia/nucleotide-count/runtests.jl:18
Expression: count_nucleotides("AGXXACT")
Expected: DomainError
Thrown: MethodError
Stacktrace:
[1] top-level scope at /Users/shane/Exercism/julia/nucleotide-count/runtests.jl:18
[2] top-level scope at /Users/juliainstall/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.2/Test/src/Test.jl:1113
[3] top-level scope at /Users/username/Exercism/julia/nucleotide-count/runtests.jl:18
Test Summary: | Fail Total
strand with invalid nucleotides | 1 1
ERROR: LoadError: Some tests did not pass: 0 passed, 1 failed, 0 errored, 0 broken.
The MethodError comes from the call to DomainError -- there are no zero-argument constructor for this exception type. From the docs:
help?> DomainError
DomainError(val)
DomainError(val, msg)
The argument val to a function or constructor is outside the valid domain.
So there are one constructor which takes the value that was out of the domain, and one that, in addition, takes an extra message string. You could e.g. do
throw(DomainError(ch))
or
throw(DomainError(ch, "this character is bad"))

Parallel mysql I/O in Ruby

Good day to you. I'm writing a cron job that hopefully will split a huge MySQL table to several threads and do some work on them. This is the minimal sample of what I have at the moment:
require 'mysql'
require 'parallel'
#db = Mysql.real_connect("localhost", "root", "", "database")
#threads = 10
Parallel.map(1..#threads, :in_processes => 8) do |i|
begin
#db.query("SELECT url FROM pages LIMIT 1 OFFSET #{i}")
rescue Mysql::Error => e
#db.reconnect()
puts "Error code: #{e.errno}"
puts "Error message: #{e.error}"
puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
end
end
#db.close
The threads don't need to return anything, they get their job share and they do it. Only they don't. Either connection to MySQL is lost during the query, or connection doesn't exist (MySQL server has gone away?!), or no _dump_data is defined for class Mysql::Result and then Parallel::DeadWorker.
How to do that right?
map method expects a result; I don't need a result, so I switched to each:
Parallel.each(1..#threads, :in_processes => 8) do |i|
Also this solves a problem with MySQL: I just needed to start the connection inside the parallel process. When using each loop, it's possible. Of course, connection should be closed inside the process also.

T-SQL is error handling totally turned off in a "BEGIN CATCH" block?

I just want to confirm what I'm seeing. Below is a small proof of concept Stored Proc I wrote that illustrates an issue I was having in a much bigger one.
ALTER PROCEDURE TestErrorHandling
#Param1 varchar(1) = ''
AS
BEGIN
/*
Unit test:
DECLARE #returnStatus nvarchar(15);
Exec #returnStatus = TestErrorHandling
print #returnStatus
*/
BEGIN TRY
print 'Start'
IF #Param1 = '' raiserror( '#Param1 is missing', 18, 1 );
print 'Should not see this'
END TRY
BEGIN CATCH
print error_message()
print error_state()
print error_number()
INSERT INTO [FlightOrderUploadFailedLog]
(EvtTyp)
VALUES ('max size of EvtType is only varchar(15) so this should cause truncation')
print 'after insert '
print error_message()
print error_state()
print error_number()
return -- added in second version (after original post)
END CATCH
END
GO
Output:
Start
#Param1 is missing
1
50000
Msg 8152, Level 16, State 4, Procedure TestErrorHandling, Line 30
String or binary data would be truncated.
The statement has been terminated.
after insert
#Param1 is missing
1
50000
-8
The surprising thing to me is that the program doesn't blow up on the "string or binary data would be truncated". In other words, the code after that still runs. Also, the error_message is not changed by a SQL error inside the catch block.
So the question is - what is the best practice for handling unexpected errors in the "BEGIN CATCH" section? Should I have another nested TRY/CATCH?
NOTE: This was my original question, but I thought to put this question there would get it off topic and confuse the issue. After this one gets answered, I'll go back and update that one: T-SQL Clear Errors
Part 2 - added later:
DECLARE #returnStatus nvarchar(15);
Exec #returnStatus = TestErrorHandling
print #returnStatus
This returns a -8. Where the heck does -8 come from?
I'm also experiementing with adding a "return" vs a "return 0". When BizTalk calls the stored proc, I want him to think it completed successfully, so as not to do the 3 retries every 5 minutes.
Added: I think this is mostly the answer I'm looking for:
SQL try-catch statement not handling error (SQL Server 2008)
But it does not discuss the best practice question I asked in this question.
UPDATE: Here is program to demo Allan's response:
ALTER PROCEDURE TestErrorHandling2
#Param1 varchar(1) = ''
AS
BEGIN
/*
Unit test:
DECLARE #returnStatus nvarchar(15);
Exec #returnStatus = TestErrorHandling2
print #returnStatus
This is proof of concept on error handling.
See question: https://stackoverflow.com/questions/20245900/t-sql-is-error-handling-totally-turned-off-in-a-begin-catch-block
Testing to see if Truncation error stops or not.
*/
print 'Start'
INSERT INTO [FlightOrderUploadFailedLog]
(EvtTyp)
VALUES ('max size of EvtType is only varchar(15) so this should cause truncation')
print 'after insert #1'
print 'Message=' + IsNull(error_message(),'null')
print 'State=' + IsNull(convert(varchar(4),error_state()),'null')
print 'ErrorNumber=' + IsNull(convert(varchar(8),error_number()),'null')
BEGIN TRY
print 'Start - Begin Try'
INSERT INTO [FlightOrderUploadFailedLog]
(EvtTyp)
VALUES ('max size of EvtType is only varchar(15) so this should cause truncation')
print 'after insert #2 '
print 'Message=' + IsNull(error_message(),'null')
print 'State=' + IsNull(convert(varchar(4),error_state()),'null')
print 'ErrorNumber=' + IsNull(convert(varchar(8),error_number()),'null')
print 'The End'
END TRY
BEGIN CATCH
print 'Catch'
print 'Message=' + error_message()
print 'State=' + convert(varchar(4),error_state())
print 'ErrorNumber=' + convert(varchar(8),error_number())
return -- error has been theoretically handled by writing it to a database
END CATCH
END
GO
Result:
Start
Msg 8152, Level 16, State 4, Procedure TestErrorHandling2, Line 21
String or binary data would be truncated.
The statement has been terminated.
after insert #1
Message=null
State=null
ErrorNumber=null
Start - Begin Try
(0 row(s) affected)
Catch
Message=String or binary data would be truncated.
State=4
ErrorNumber=8152
-6
Well, let me try for what I can.
"Best practice" - I hate that phrase because 9 times out of 10 it's purely subjective because somebody somewhere read something.
So my subjective answer is that seeing as you can nest try/catch and put a try/catch within the catch block - then I'd consider it good error handling to put a try/catch within the catch - IF what you have can throw an error and is severe enough that you wish to handle it yourself.
So IMO - best practice is yes, nest try/catch for better error handling.
Secondly - the reason your "catch" doesn't blow up is that the truncating error is not a batch terminating error. It's error level isn't high enough, so subsequent statements will be executed.
Simply try it out with a print statement:
PRINT 'something'
--do your insert here
PRINT 'somethingelse'
Then you'll see you should get both print statements.
You can even suppress truncate errors if you wanted to by changing ANSI_WARNINGS to OFF. Not that I would recommend, but well ... :)
If you had a try/catch within your catch, that should catch your truncate error because the severity is enough to trigger catch.

Attribute mysteriously getting set to id of 1

I have an object that is apparently randomly getting set to an id of 1 and the source of where this is happening is unknown in the codebase. Could be on an update attributes for a user for which school is associated.
How can I raise an error or otherwise log when this happens so I can track it down and resolve it?
Below is a first attempt but doesn't seem to take into account update_attributes
belongs_to :foo_school, :foreign_key => 'school_id'
def foo_school=(foo_school)
begin
raise "Found" if foo_school == FooSchool.find(1)
rescue Exception => e
# Track it down through the stack trace
Rails.logger.error e
ensure
write_attribute(:foo_school, foo_school)
end
end
An observer can do this for you. What you do with this observer is up to you.
$ rails g observer Oddity
Add this in config/application.rb (search for "observer" in that file, there's an example by default).
config.active_record.observers = :oddity_observer
class OddityObserver < ActiveRecord::Observer
observe :foo
def after_update(record)
raise "Boom" if record.id == 1
end
end