I've now written a few applications using scala actors and I'm interested in how people have approached or dealt with some of the problems I've encountered.
A plethora of Message classes or !?
I have an actor which reacts to a user operation and must cause something to happen. Let's say it reacts to a message UserRequestsX(id). A continuing problem I have is that, because I want to modularize my programs, a single actor on its own is unable to complete the action without involving other actors. For example, suppose I need to use the id parameter to retrieve a bunch of values and then these need to be deleted via some other actor. If I were writing a normal Java program, I might do something like:
public void reportTrades(Date date) {
Set<Trade> trades = persistence.lookup(date);
reportService.report(trades);
}
Which is simple enough. However, using actors this becomes a bit of a pain because I want to avoid using !?. One actor reacts to the ReportTrades(date) message but it must ask a PersistenceActor for the trades and then a ReportActor to report them. The only way I've found of doing this is to do:
react {
case ReportTrades(date) =>
persistenceActor ! GetTradesAndReport(date)
}
So that in my PersistenceActor I have a react block:
react {
case GetTradesAndReport(date) =>
val ts = trades.get(date) //from persietent store
reportActor ! ReportTrades(ts)
}
But now I have 2 problems:
I have to create extra message classes to represent the same request (i.e. "report trades"). In fact I have three in this scenario but I may have many more - it becomes a problem keeping track of these
What should I call the first and third message ReportTrades? It's confusing to call them both ReportTrades (or if I do, I must put them in separate packages). Essentially there is no such thing as overloading a class by val type.
Is there something I'm missing? Can I avoid this? Should I just give up and use !? Do people use some organizational structure to clarify what is going on?
To me, your ReportTrades message is mixing two different concepts. One is a Request, the order is a Response. They might be named GetTradesReport(Date) and SendTradesReport(List[Trade]), for example. Or, maybe, ReportTradesByDate(Date) and GenerateTradesReport(List[Trade]).
Are there some objections to using reply? Or passing trades around? If not, your code would probably look like
react {
case ReportTrades(date) => persistenceActor ! GetTrades(date)
case Trades(ts) => // do smth with trades
}
and
react {
case GetTrades(date) => reply(Trades(trades.get(date)))
}
respectively.
Related
I am writing a program that has to interact with a library that was implemented using Akka. In detail, this library exposes an Actor as endpoint.
As far as I know and as it is explained in the book Applied Akka Pattern, the best way to interact with an Actor system from the outside is using the Ask Pattern.
The library I have to use exposes an actor Main that accepts a Create message. In response to this message, it can respond with two different messages to the caller, CreateAck and CreateNack(error).
The code I am using is more or less the following.
implicit val timeout = Timeout(5 seconds)
def create() = (mainActor ? Create).mapTo[???]
The problem is clearly that I do not know which kind of type I have to use in mapTo function, instead of ???.
Am I using the right approach? Is there any other useful pattern to access to an Actor System from an outside program that does not use Actors?
In general it's best to leave Actors to talk between Actors, you'd simply receive a response then - simple.
If you indeed have to integrate them with the "outside", the ask pattern is fine indeed. Please note though that if you're doing this inside an Actor, this perhaps isn't the best way to go about it.
If there's a number of unrelated response types I'd suggest:
(1) Make such common type; this can be as simple as :
sealed trait CreationResponse
final case object CreatedThing extends CreationResponse
final case class FailedCreationOfThing(t: Throwable) extends CreationResponse
final case class SomethingElse...(...) extends CreationResponse
which makes the protocol understandable, and trackable. I recommend this as it's explicit and helps in understanding what's going on.
(2) For completely unrelated types simply collecting over the future would work by the way, without doing the mapTo:
val res: Future[...] = (bob ? CreateThing) collect {
case t: ThatWorked => t // or transform it
case nope: Nope => nope // or transform it to a different value
}
This would work fine type wise if the results, t and nope have a common super type, that type would then be the ... in the result Future. If a message comes back and does not match any case it'd be a match error; you could add a case _ => whatever then for example, OR it would point to a programming error.
See if CreateAck or CreateNack(error) inherit from any sort of class or object. If thats the case you can use the parent class or object in the .mapTo[CreateResultType].
Another solution is to use .mapTo[Any] and use a match case to find the resulting type.
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.
I have an intermediate remote actor (B) that is supposed forward back and forth messages from A and C ( like A <-> B <-> C ). In B's code I have something like
loop {
react {
case msg => val A = sender
//2) Should this be synchronous with !?
C ! msg
//1) What's better react or receive?
react {
case response => A ! response
}
}
}
3 Questions:
1) What's better react or receive (to nest within a react)?
2) Given that a response will be sent back, should !? be used instead of !
3) Any other recommendation for this scenario?
Thank you all!
For what concerns the standard Actor model, messages must be handled atomically (i.e. you cannot receive and process messages when you are processing another -- and that's exactly what you'd like to do here)
However, Scala Actors have a relaxed semantics, which may allow to do that.
For Question 1, you should have clear which are the differences between react and receive. Anyway, you can easily use react (as used here http://www.scala-lang.org/docu/files/actors-api/actors_api_guide.html)
Alternatively, you could not use nesting. After your actor has sent the request, its state should change so that that next loop cycle it will look for the reply.
You may also want to upgrade to Scala 2.10 which integrate actors from Akka; that model is more clear and easy to use.
I see this type of pattern (found this example here) quite often in Scala:
class UserActor extends Actor {
def receive = {
case GetUser(id) =>
// load the user, reply with None or Some(user)
val user: Option[User] = ...
sender ! user
case FindAll() =>
// find all users
val users: List[User] = ...
sender ! users
case Save(user) =>
// persist the user
sender ! Right(user)
}
}
So depending on the call you get: Option[User], List[User], Right[User]. This approach is fine! I'm just asking out of interest if this is optimal? For example (and this may be a bad one): Will it make API's better or worse to try and generalise by always returning List[User]? So when a user is not found or if a save fails, then the list will simply be empty. I'm just curious.... any other suggestions on how the above 'pattern' may be improved?
I'm just trying to identify a perfect pattern for this style of API where you sometimes get one entity and sometimes none and sometimes a list of them. Is there a 'best' way to do this, or does everyone role their own?
The return types should help clarify your API's intended behavior.
If GetUser returned a List, developers might get confused and wonder if multiple users could possibly be returned. When they see that an Option is returned, they will immediately understand the intended behavior.
I once had to work with a fairly complex API which provided CRUD operations that had been generalized in the manner you describe. I found it to be difficult to understand, vaguely defined, and hard to work with.
In my opinion it is a very good pattern for API design.
I use very often Option as return type of my functions, if I want to return a single element, obviously because I don't need to deal with null. Returning a Seq is naturally for multiple elements and Either is optimal if you want to return a failure-description, I use it often while parsing I/O. Sometimes I even combine the Seq with one of the others. You likely don't know the preferences and goals of an user of your API, so it makes sence to provide all of these return-types to make the user feel as comfortable as possible.
I am writing a web app where exceptions are used to handle error cases. Often, I find myself writing helpers like this:
def someHelper(...) : Boolean {...}
and then using it like this:
if (!someHelper(...)){
throw new SomeException()
}
These exceptions represent things like invalid parameters, and when handled they send a useful error message to the user, eg
try {
...
} catch {
case e: SomeException => "Bad user!"
}
Is this a reasonable approach? And how could I pass the exception into the helper function and have it thrown there? I have had trouble constructing a type for such a function.
I use Either most of the time, not exceptions. I generally use exceptions, as you have done or some similar way, when the control flow has to go way, way back to some distant point, and otherwise there's nothing sensible to do. However, when the exceptions can be handled fairly locally, I will instead
def myMethod(...): Either[String,ValidatedInputForm] = {
...
if (!someHelper(...)) Left("Agree button not checked")
else Right(whateverForm)
}
and then when I call this method, I can
myMethod(blah).fold({ err =>
doSomething(err)
saneReturnValue
}, { form =>
foo(form)
form.usefulField
})
or match on Left(err) vs Right(form), or various other things.
If I don't want to handle the error right there, but instead want to process the return value, I
myMethod(blah).right.map{ form =>
foo(form)
bar(form)
}
and I'll get an Either with the error message unchanged as a Left, if it was an error message, or with the result of { foo(form); bar(form) } as a Right if it was okay. You can also chain your error processing using flatMap, e.g. if you wanted to perform an additional check on so-far-correct values and reject some of them, you could
myMethod(blah).right.flatMap{ form =>
if (!checkSomething(form)) Left("Something didn't check out.")
else Right(form)
}
It's this sort of processing that makes using Either more convenient (and usually better-performing, if exceptions are common) than exceptions, which is why I use them.
(In fact, in very many cases I don't care why something went wrong, only that it went wrong, in which case I just use an Option.)
There's nothing special about passing an exception instance to some method:
def someMethod(e: SomeException) {
throw e
}
someMethod(new SomeException)
But I have to say that I get a very distinct feeling that your whole idea just smells. If you want to validate a user input just write validators, e.g. UserValidator which will have some method like isValid to test a user input and return a boolean, you can implement some messaging there too. Exceptions are really intended for different purposes.
The two most common ways to approach what you're trying to do is to either just have the helper create and throw an exception itself, or exactly what you're doing: have the calling code check the results, and throw a meaningful exception, if needed.
I've never seen a library where you pass in the exception you expect the helper to throw. As I said on another answer, there's a surprisingly substantial cost to simply instantiating an exception, and if you followed this pattern throughout your code you could see an overall performance problem. This could be mitigated through the use of by-name parameters, but if you just forget to put => in a few key functions, you've got a performance problem that's difficult to track down.
At the end of the day, if you want the helper to throw an exception, it makes sense that the helper itself already knows what sort of exception it wants to throw. If I had to choose between A and B:
def helperA(...) { if (stuff) throw new InvalidStuff() }
def helperB(..., onError: => Exception) { if (stuff) throw onError }
I would choose A every time.
Now, if I had to choose between A and what you have now, that's a toss up. It really depends on context, what you're trying to accomplish with the helpers, how else they may be used, etc.
On a final note, naming is very important in these sorts of situations. If your go the return-code-helper route, your helpers should have question names, such as isValid. If you have exception-throwing-helpers, they should have action names, such as validate. Maybe even give it emphasis, like validate_!.
For an alternative approach you could check out scalaz Validators, which give a lot of flexibility for this kind of case (e.g. should I crash on error, accumulate the errors and report at the end or ignore them completely?). A few
examples might help you decide if this is the right approach for you.
If you find it hard to find a way in to the library, this answer gives some pointers to some introductory material; or check out .