Simple logging scala - scala

I implemented a simple
trait Logging {
...
object log {
def info(msg: String)
...
}
//saves stuff
def logOut(path) = {}
setting up a full log4j takes a ton of time with all the properties file required
Logging seems to be working fine except for the fact that I need to make a logOut at the end of my main() to print or save those logs somewhere, which is inconvenient and ugly
So the questions are :
Is there a way to force Logging to do something at the end of the program?
Is there another good way to approach the problem?

You can add Shutdown hook at the end of your program. But keep in mind that it will only be executed in case of graceful shutdown. Killing the process will not invoke this hook.
sys.addShutdownHook { println("Bye-bye") }

Related

How to stop all actors and wait for them to terminate?

I am implementing unit tests for my Akka project. To avoid InvalidActorNameExceptions and the like, I want all actors that were created within one unit test to be stopped before the next unit test is being run. So, for each actor created within a unit test, I call _system.stop(someActorRef) at the end of it. However, it takes some time for an actor to actually be stopped, and unfortunately, the next unit test usually starts running before the actors that were created within the previous one are actually gone. And since there is neither a Future that is being returned by the stop method, nor an awaitStop method available, I really don't know how to solve this. Currently I call Thread.sleep(1000) at the end of each unit test and hope all actors are dead by then, but, obviously, I cannot stay this way. :D
I'd appreciate any hint!
You could try this at the end of your test:
val probe = TestProbe()
probe.watch(someActorRef)
system.stop(someActorRef)
probe.expectMsgType[Terminated]
//another way
//probe.expectMsgPF() {
// case Terminated(someActorRef) =>
//}

Scalatest figuring out if test passed or failed after the fact [duplicate]

In scalatest using FunSpec I have some code that fires in the afterEach. I would like to execute some code to get a screenshot only when the test fails. Just about everything I have looked at tries to solve this by putting asserts in try blocks which seems awful. Is there anything like onTestFailure in TestNG or a context I can get like RSpec to determine if the test failed? Looking at the scala doc I see a implementation that takes a configMap, but that is empty when I run the test. Any help would be appreciated.
pretty sure I figured it out. coming from a TestNG background it seemed weird to have to mess with fixtures to accomplish it. I suspect others with a background like mine may also look in all the wrong places as well, so going to leave this here to help others:
override def withFixture(test: NoArgTest) = { // after
val outcome = super.withFixture(test)
outcome match {
case Failed(ex) =>
// log ex (the exception) and a screenshot
}
outcome
}

Why does `TestFSMRef.receive must throw[Exception]` fail intermittently

Hi fellow coders and admired gurus,
I have an actor that implements FSM that is required to throw an IOException on certain messages while in a specific state (Busy) to be restarted by its Supervisor.
excerpt:
case class ExceptionResonse(errorCode: Int)
when(Busy) {
case ExceptionResponse(errorCode) =>
throw new IOException(s"Request failed with error code $errorCode")
}
I am trying to test that behavior by using a TestActorRef and calling receive directly on that expecting receive to throw an IOException.
case class WhenInStateBusy() extends TestKit(ActorSystem()) with After {
val myTestFSMRef = TestFSMRef(MyFSM.props)
...
def prepare: Result = {
// prepares tested actor by going through an initialization sequence
// including 'expectMsgPfs' for several messages sent from the tested FSM
// most of my test cases depend on the correctness of that initialization sequence
// finishing with state busy
myTestFSMRef.setState(Busy)
awaitCond(
myTestFSMRef.stateName == Busy,
maxDelay,
interval,
s"Actor must be in State 'Busy' to proceed, but is ${myTestFSMRef.stateName}"
)
success
}
def testCase = this {
prepare and {
myTestFSMRef.receive(ExceptionResponse(testedCode)) must throwAn[IOException]
}
}
}
Note: The initialization sequence makes sure, the tested FSM is fully initialized and has setup its internal mutable state. State Busy can only be left when the actor receives a certain kind of message that in my test setup has to be provided by the test case, so I am pretty sure the FSM is in the right state.
Now, on my Jenkins server (Ubuntu 14.10) this test case fails in about 1 out of 20 attempts (-> No exception is thrown). However, on my development machine (Mac Os X 10.10.4) I am not able to reproduce the bug. So debugger does not help me.
The tests are run sequentially and after each example the test system is shut down.
Java version 1.7.0_71
Scala version 2.11.4
Akka version 2.3.6
Specs2 version 2.3.13
Can anyone explain why sometimes calling myTestActorRef.receive(ExceptionResponse(testedCode)) does not result in an Exception?
This is a tricky question indeed: my prime suspect is that the Actor is not yet initialized. Why is this? When implementing system.actorOf (which is used by TestFSMRef.apply()) it became clear that there can only be one entity that is responsible for actually starting an Actor, and that is its parent. I tried many different things and all of them were flawed in some way.
But how does that make this test fail?
The basic answer is that with the code you show it is not guaranteed that at the time you execute setState the FSM has already been initialized. Especially on (low-powered) Jenkins boxes it may be that the guardian actor does not get scheduled to run for a measurable amount of time. If that is the case then the startWith statement in your FSM will override the setState because it runs afterwards.
The solution to this would be to send another message to the FSM and expect back the proper response before calling setState.

scala+jdbc+case class+actors design confusion

I am writing an exporter that will take results from the database and take every individual records and write it to a comma separated file. Different queries will have different worker created for it since they need to write separate csv files. To start off, I have decoupled the tasks into two different actors. Actor1 is a JdbcWorker which queries the database provided a query parameter and Actor2 is a CSVWriter which receives case class representing the result from the query that needs to be appended to the CSV. My first question is, even though I like the separation of concerns provided by these two workers but is it good design to decouple the jdbc query from the CSV writer?
So, I have written actor1 as follows:
class DataQueryWorker(csvExporterWorker: ActorRef) extends Actor with ActorLogging{
private implicit def ModelConverter(rs: ResultSet): QueryModel = {
QueryModel(
id = rs.getString(0),
name = rs.getString(1),
age = rs.getString(2),
gender = rs.getString(3))
}
private def sendModelToCsvWorker(model: QueryModel): Unit = {
csvExporterWorker ! model
}
private def startExport[T](queryString: String)(resultFunc: T => Unit)(implicit ModelConverter: ResultSet => T): Unit = {
try {
val connection = DriverManager.getConnection(DbConfig.connectionString,
DbConfig.user,
DbConfig.password)
val statement = connection.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY)
statement.setFetchSize(Integer.MIN_VALUE)
val rs = statement.executeQuery(queryString)
while (rs.next()) {
resultFunc(ModelConverter(rs))
}
} catch {
case e: Exception => //What to do in case of an exception???
}
}
override def receive() = {
case startEvent => startExport(DbConfig.ModelExtractionQuery)(sendModelToCsvWorker)
}
}
My next question would be, is the code written above, the proper way to query the database, wrap it in a model and send the result to the CSVWorker? I am not sure if I am following the scala idioms properly. Also, what would be the proper way to handle exceptions in this case?
It will be great to get some guidance on this.
Thanks
I think your approach is ok with a couple of minor changes:
For the DB actor, you might want to look into making these long lived actors, pooled behind a Router. Let this actor hold a Connection as it's state, opening it once when started and closing then reopening in case of restart due to failure. I think this might be a better approach as you won't always need to be opening connections for calls to export data. You just need to write some code for perhaps checking the state of the connection (and reconnecting) before making calls to it.
Once you make the DB actor stateful and long lived, you won't be able to pass the CSVWorker in via the constructor. You should instead pass it in via the message to this actor indicating that you want an export. You could do that via a case class like so:
case class ExportQuery(query:String, csvWorker:ActorRef)
Change your receive to look like this:
def receive = {
case ExportQuery(query, csvWorker) =>
...
}
And lastly, remove the try/catch logic. Unless you can do something meaningful based on this failure (like call some alternate code path) it doesn't make sense catching it. Let the actor fail and get restarted (and close/reopen the connection) and move on.
I think using actors here is probably overkill.
Actors are useful when you want to operate on mutable state with multiple threads safely. But, in your case, you say that each query writes to a separate CSV file (so there's only one thread per CSV file). I don't think the CSVWorker actor is necessary. It could even potentially be harmful, as the actor mailbox could grow and consume a significant amount of memory, if the DBWorker is signifcantly faster than the CSVWorker.
Personally, I'd just call the CSV writer directly.
The question about separation of concerns depends on whether you expect this code to be re-used in unrelated contexts. If you're likely to want to use your JDBC worker with other writers, then it may be worth it (although there's a school of thought that says you're better off waiting until a need arises before refactoring - You Aint Gonna Need It or YAGNI). Otherwise, you might be better off simplifying.
If you do decide to attach the JDBC code to the CSV code directly, you might also want to take out the case class conversion. Again, if this is code that will be re-used elsewhere, then it's better to keep it.
Exception handling depends on your application, but in Scala (unlike in Java), if you don't know what to do about an Exception, you probably shouldn't do anything. Take the try..catch block out, and just let the exception propagate - something will catch it, and report it.
Java forces you to handle exceptions, which is a great idea in theory, but in practice often leads to error handling code that does nothing of any real use (either re-throwing, or worse, swallowing errors).
Oh, and if you're writing a lot of code that turns ResultSets into case classes, and vice versa, you might want to look at using an Object Relation Mapping framework, like Slick or Squeryl. They're optimised for precisely this use case.

Internal scala compilation. Working with interactive.Global

I am trying to retrieve the AST from scala souce file. I have simplified the code (only relevant code) to following.
trait GetAST {
val settings = new Settings
val global = new Global(settings, new ConsoleReporter(settings))
def getSt = "hello" //global.typedTree(src, true)
}
object Tre extends GetAST {
def main(args:Array[String])
{
println(getSt.getClass)
println("exiting program")
}
}
The above code compiles fine and runs fine. But the problem is the program does not exit. The prompt is not displayed after printing "exiting program". I have to use ^c to exit.
Any idea what the problem might be
I believe Michael is correct, the compiler uses Threads and therefore the JVM doesn't just exit.
The good news is that interactive.Global mixes in interactive.CompilerControl trait whose askShutdown method you can call at the end of your main to let the program exit.
Without knowing what Settings, Global and ConsoleReporter are nobody can give you an exact answer. I would guess that at least one of them is creating a thread. The JVM waits until all threads are done (or all running are deamon threads). See here.
I would bet if you comment out the settings and global lines it will exit as expected.