Erroring with PetrelLogger.NewAsyncProgress - ocean

I am using the PetrelLogger.NewAsyncProgress which seems to work well. However I can't figure out how to report an error with my task. Once I Dispose of the NewAsyncProgress, it reports 'Success' for my task.
I have tried setting the ProgressStatus = -1, but that didn't make a difference.
Example:
using (_asyncProgress = PetrelLogger.NewAsyncProgress("Doing Job", ProgressType.Default, (AsyncProgressCanceledCallback)AsyncProgressCanceled, this))
{
try
{
//Do Something
_asyncProgress.ProgressStatus = 100;
}
catch (Exception e)
{
//Error happened
_asyncProgress.ProgressStatus = -1;
}
}
So if an exception is thrown, the task manager result is Success 100%. Any ideas?

It's not possible in Ocean at the moment. However, we have such requirement recorded, so it can be implemented in one of future releases

Related

Merging Mono and Flux in Spring WebFlux

Let's say I have a method store(Flux<DataBuffer> bufferFlux) which receives some data as a flux of DataBuffers, calculates an identifier, creates an AsynchronousFileChannel and then uses DataBufferUtils the data to the channel.
I started like this. Please note, that the following code will not work. It should just illustrate how I create a FileChannel and how I would like to write the data, while releasing used buffers and closing the channel afterwards.
public Mono<Void> store(Flux<DataBuffer> bufferFlux) {
var channelMono = Mono.defer(() -> {
try {
log.info("opening file {}", filePath);
return Mono.just(AsynchronousFileChannel
.open(filePath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE));
} catch (IOException ex) {
log.error("error opening file", ex);
return Mono.error(ex);
}
});
// calculate identifier
// store buffers to AsynchronousFileChannel
return DataBufferUtils
.write(bufferFlux, fileChannel)
.doOnNext(DataBufferUtils.releaseConsumer())
.doFinally(f -> {
try {
fileChannel.close();
} catch (IOException ioException) {
log.error("error closing file channel", ioException);
}
})
.then();
}
The problem is, that I just started with reactive programming and have no clue how I could bring these two building blocks together, so that
the data is written to the channel
all buffers are gracefully released
the channel is closed after writing the data
the whole operation just signals complete or error (I guess this is what Mono<Void> is used for)
Can anyone help me choose the right operators or point me to a conceptual problem (perhaps there is a good reason why I cannot find a suitable operator)? :)
Thank you!

How do I throw an exception and log as info?

Need a bit quick help with Kotlin. Here is the pseudocode: When there is a “specialCase” error, throw the exception and Log this exception as “Info”. This is the if statement I have. Does this look like a good approach?
if (error.contains (specialCase))
{
throw specialCaseDoesNotExistException
}
LOGGER.info("WriteSpecialCaseasInfoandNOTError")
Either you log before throwing or you could combine it into a single statement using also (reference):
if (error.contains (specialCase)) {
LOGGER.info("WriteSpecialCaseasInfoandNOTError")
throw specialCaseDoesNotExistException
}
if (error.contains (specialCase)) {
throw specialCaseDoesNotExistException.also {
LOGGER.info("WriteSpecialCaseasInfoandNOTError")
}
}

WCF Service proxy - Both Close() and Abort functions getting called

I have the below code to call a WCF proxy:-
var client = new ServiceClientProxy();
try
{
var documents = client.GetDocuments();
client.Close();
if(documents.Length > 50)
{
throw new Exception("Too many Documents");
}
else if(documents.Length <10)
{
throw new Exception("Too many Documents");
}
else
{
return documents;
}
}
catch(exception ex)
{
client.Abort();
}
Here If the documents count that we get from service is more than 50 or less than 10, in that case we will be calling both Close() as well as the Abort functions on client.Is this expected way of calling WCF service proxy?
Anyone please suggest if there is some better way handling this.
Also is it a better approach to close the client connection immediately after the call or do we need to wait till we have completely used the response properties and close the connection at end?
Also is it a better approach to close the client connection
immediately after the call or do we need to wait till we have
completely used the response properties and close the connection at
end?
Depends on if you need to make subsequent calls to the service. If not then by all means close the connection.
Is this expected way of calling WCF service proxy? Anyone please
suggest if there is some better way handling this.
No. To handle a problem that is baked into WCF you could should actually be structured like this:
Documents documnts = null;
try
{
var client = new ServiceClientProxy();
documents = client.GetDocuments();
}
finally
{
try
{
if (client.State != CommunicationState.Closed)
client.Close();
}
catch
{
client.Abort();
};
};
if (documents.Length > 50)
{
throw new Exception("Too many Documents");
}
else if (documents.Length < 10)
{
throw new Exception("Too many Documents");
}
else
{
return documents;
}
If you want to truly understand the 'why' I would highly recommend reading this series of articles. They will clear up the Close / Abort portion of your problem.
http://blogs.msmvps.com/p3net/2014/02/02/a-smarter-wcf-service-client-part-1/
http://blogs.msmvps.com/p3net/2014/02/09/a-smarter-wcf-service-client-part-2/
http://blogs.msmvps.com/p3net/2014/02/23/a-smarter-wcf-service-client-part-3/
http://blogs.msmvps.com/p3net/2014/03/15/a-smarter-wcf-service-client-part-4/
Another other things I should point out with the code you've provided is exceptions should be exceptional.
Using exceptions for what I would considered to be business logic is usually not the right thing to do. Consider the approach where you return a structured result instead. Perhaps in your case it make sense though.
HTH

Exception handling in Controller in ASP.Net MVC 4 with ELMAH and ajax

I've seen a number of posts and articles but am not able to see the solution crisply.
I've installed Elmah.MVC via NuGet and have commented out this line from FilterConfig.cs:
//filters.Add(new HandleErrorAttribute());
So that Elmah would pick up the errors.
It works when I provide an invalid action name and I get a yellow page as well as an email.
I want to know about two other types of errors that my code may generate... how are we supposed to handle them:
1.E.g. if my repository or manager (business logic) layer throws an exception when trying to access database or send an email etc.
a. Is the correct way to NOT implement any kind of try catch in Controllers (or anywhere else for that matter) and let Elmah take care of exceptions?
b. If so, and if it shows a yellow error page, how can we show a view of our own liking?
2.If my view contains ajax calls, e.g. via jqgrid, and behind the scenes there are errors, I've noticed they also get picked up properly by Elmah. But how do I show some kind of an error message to the user as well?
Thanks
Here is what I did:
In controller, I placed try catch:
try
{
//model = getmodelfromdb();
return View("MyView", model);
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
return View("../Error/ShowException", ex);
}
For custom view for 404, I did this in global.asax:
protected void Application_OnError( )
{
var exception = Server.GetLastError( );
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
Helper.SetSessionValue(SessionKeys.EXCEPTION, exception);
Response.Redirect( "~/Error/ShowException");
}
For jqgrid, I did this in my controller:
[HttpPost]
public ActionResult ListRecords( int page , DateTime? fromdate , DateTime? todate)
{
try
{
var list = FetchListFromDB();
var result = new
{
total = Math.Ceiling(list.Count / (decimal)Helper.PAGE_SIZE),
page = page, //--- current page
records = list.Count, //--- total items
rows = list.List.Select(x => new
{
id = x.EntityID,
cell = new string[]
{
x.Property1,
x.Property2
}
}).ToArray()
};
return Json(result, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var result = new
{
errorMessage = "An unexpected error occurred while fetching data. An automatic email has been generated for the support team who will address this issue shortly. Details: " + ex.Message,
records = 0
};
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
return Json(result, JsonRequestBehavior.AllowGet);
}
And this in the View (in the jqgrid definition):
loadComplete:function(data)
{
if (data.errorMessage)
{
alert(data.errorMessage);
}
},
In a general ajax scenario:
success: function(data)
{
if (data.errorMessage)
{
alert(data.errorMessage);
}
else
{
//...
}
},
a. Is the correct way to NOT implement any kind of try catch in Controllers (or anywhere else for that matter) and let Elmah take care of exceptions?
I'd say that Elmah doesn't "take care" of exceptions, it records them. Ideally, you should try to handle the errors - by all means log them, but also add logic to deal with them so that they don't interrupt the user's workflow.
I'd wrap logic in try blocks, and in the catch use
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
to record anything that goes wrong. Immediately after that line, however, I'd then do something to try to recover from the exception - catch specific exception types, never just catch (Exception e), and deal with them after logging them. The idea is that you should be reviewing your logs, working out what's causing the exceptions, and improving your program so that it doesn't throw exceptions any more.
To show your own error pages, there's the HandleErrorAttribute, or if you don't want to use that there's also the controller's OnException() method, which is called when a controller action method quits with an exception rather than finishing normally. An ExceptionContext object is passed into that method, so you can use that to get the exception that was thrown and log it, do any cleanup that might be required etc.
I know i'm very late to the party but I stumbled upon this answer while searching something similar form Google.
I don't like using try catch blocks everywhere in my code, especially in web apps. I let Elmah catch everything and log it behind the scenes. Then in the web.config file you can redirect based on the error type...
<customErrors mode="RemoteOnly" defaultRedirect="~/Error" >
<error statusCode="500" redirect="~/Error"/>
<error statusCode="404" redirect="~/NotFound"/>
</customErrors>

How to tell the Session to throw the error query[NHibernate]?

I made a test class against the repository methods shown below:
public void AddFile<TFileType>(TFileType FileToAdd) where TFileType : File
{
try
{
_session.Save(FileToAdd);
_session.Flush();
}
catch (Exception e)
{
if (e.InnerException.Message.Contains("Violation of UNIQUE KEY"))
throw new ArgumentException("Unique Name must be unique");
else
throw e;
}
}
public void RemoveFile(File FileToRemove)
{
_session.Delete(FileToRemove);
_session.Flush();
}
And the test class:
try
{
Data.File crashFile = new Data.File();
crashFile.UniqueName = "NonUniqueFileNameTest";
crashFile.Extension = ".abc";
repo.AddFile(crashFile);
Assert.Fail();
}
catch (Exception e)
{
Assert.IsInstanceOfType(e, typeof(ArgumentException));
}
// Clean up the file
Data.File removeFile = repo.GetFiles().Where(f => f.UniqueName == "NonUniqueFileNameTest").FirstOrDefault();
repo.RemoveFile(removeFile);
The test fails. When I step in to trace the problem, I found out that when I do the _session.flush() right after _session.delete(), it throws the exception, and if I look at the sql it does, it is actually submitting a "INSERT INTO" statement, which is exactly the sql that cause UNIQUE CONSTRAINT error. I tried to encapsulate both in transaction but still same problem happens. Anyone know the reason?
Edit
The other stay the same, only added Evict as suggested
public void AddFile<TFileType>(TFileType FileToAdd) where TFileType : File
{
try
{
_session.Save(FileToAdd);
_session.Flush();
}
catch (Exception e)
{
_session.Evict(FileToAdd);
if (e.InnerException.Message.Contains("Violation of UNIQUE KEY"))
throw new ArgumentException("Unique Name must be unique");
else
throw e;
}
}
No difference to the result.
Call _session.Evict(FileToAdd) in the catch block. Although the save fails, FileToAdd is still a transient object in the session and NH will attempt to persist (insert) it the next time the session is flushed.
NHibernate Manual "Best practices" Chapter 22:
This is more of a necessary practice than a "best" practice. When
an exception occurs, roll back the ITransaction and close the ISession.
If you don't, NHibernate can't guarantee that in-memory state
accurately represents persistent state. As a special case of this,
do not use ISession.Load() to determine if an instance with the given
identifier exists on the database; use Get() or a query instead.