I have a multithreaded Scala application and I have a shutdown hook that calls a shutdown() method on an object. Unfortunately this doesn't seem to be reliable. Many times it fails to handle SIGINT and throws a NoClassDefFoundError on an anonymous function.
How do I make this shutdown handler more robust?
One suggestion: Rather than registering shutdown() hook directly, create a ShutdownManager object and have it register a shutdown() hook. Your application objects add themselves to the ShutdownManager which can then call some application object shutdown method, either using a trait or through a function object.
preload all the classes your hook needs with either:
Class.forName("YourObject") or Class clasz = YourObject.class
Related
I have a StatefulService with a method. The first argument of the method accepts an interface type that corresponds to one of my Actors. The Actor calls the service method using ServiceProxy, passing this in as the first argument. This compiles file. The signatures match.
When running however, I get an error about an unexpected type of IMyActorType not being known to the DataContractSerializer. I know what this message means. Does ServiceProxy not handle ActorReferences? I know ActorProxy works. I can pass one Actor to another Actor using ActorProxy.
Or is this maybe some problem in my configuration of the StatefulService? Something with my ServiceReplicaListener setup?
I have worked around this issue for now by changing the method signatures of my StatefulService methods to ActorReference. That serializes fine, and I can unpack it on the other side. I would much rather have the proper typing, however.
Service Proxy does not handle the Actor references like Actor Proxy does. Services stack is independent of the actor and does not have knowledge of the actor references. Instead of passing the actor interface, you can pass the actor reference (https://msdn.microsoft.com/en-us/library/azure/microsoft.servicefabric.actors.actorreference.get.aspx) and then bind (https://msdn.microsoft.com/en-us/library/azure/microsoft.servicefabric.actors.actorreference.bind.aspx) the actor reference to the actor interface type on the receiving side. You can cast the output of the binding method to the actor interface.
You need to pass a simple DataContract-decorated POCO and not an interface. DataContractSerializer won't work on an interface. The same rules that would apply for WCF also apply to Service Fabric.
I am creating a redis pubsub client in a try-catch block. In the try block, the client is initialised with a callback to forward messages to a client. If there's a problem sending the message to the client, an exception will be thrown, in which case I need to stop the redis client. Here's the code:
try {
val redisClient = RedisPubSub(
channels = Seq(currentUserId.toString),
patterns = Seq(),
onMessage = (pubSubMessage: PubSubMessage) => {
responseObserver.onValue(pubSubMessage.data)
}
)
}
catch {
case e: RuntimeException =>
// redisClient isn't defined here...
redisClient.unsubscribe(currentUserId.toString)
redisClient.stop()
messageStreamResult.complete(Try(true))
responseObserver.onCompleted()
}
The problem is that the redis client val isn't defined in the catch block because there may have been an exception creating it. I also can't move the try-catch block into the callback because there's no way (that I can find) of referring to the redisClient object from within the callback (this doesn't resolve).
To solve this I'm instantiating redisClient as a var outside the try-catch block. Then inside the try block I stop the client and assign a new redisPubSub (created as above) to the redisClient var. That's an ugly hack which is also error prone (e.g. if there genuinely is a problem creating the second client, the catch block will try to call methods on an erroneous object).
Is there a better way of writing this code so that I can correctly call stop() on the redisClient if an exception is raised when trying to send the message to the responseObserver?
Update
I've just solved this using promises. Is there a simpler way though?
That exception handler is not going to be invoked if there is a problem sending the message. It is for problems in setting up the client. This SO answer talks about handling errors when sending messages.
As for the callback referring to the client, I think you want to register the callback after creating the client rather than trying to pass the callback in when you create it. Here is some sample code from Debashish Ghosh that does this.
Presumably that callback is going to run in another thread, so if it uses redisClient you'll have to be careful about concurrency. Ideally the callback could get to the client object through some argument. If not, then perhaps using volatile would be the easiest way to deal with that, although I suspect you'd eventually get into trouble if multiple callbacks can fail at once. Perhaps use an actor to manage the client connection, as Debashish has done?
In my app client uses services backed by Observables. Each service call is session based, so that a session has to be started before a business-service method can be called.
In order to init session I made an Observable that does it. My problem is that whenever client uses more than one business-service in parallel, session initialization gets duplicated. Client code is session-agnostic. I need a way to init session in such a way that the session observable only gets called once(when the first business-service method gets called). Basically all subsequent business-observers have to wait for condition(session initialization). Can you draw a pattern for it?
Client code would look like:
protected void onCreate(Bundle savedInstanceState) {
itemService.getItems(10).subscribe(new Observer<List<Item>>() {..});
userService.getProfile().subscribe(new Observer<List<Profile>>() {..});
}
While there're 2 calls, I need to make the session Observable execute once only and make business Observables wait for the session initialization to complete and then start doing its' job.
Thanks.
If the session initialization is an Observable, then you can delay all other Observables that depend on it, using the delay operator with the session initialization Observable as parameter: http://reactivex.io/RxJava/javadoc/rx/Observable.html#delay%28rx.functions.Func1%29
Since you already have a session Observable implemented, one possible solution would be to convert it to an AsyncSubject. It would execute only once and would emit only the last item (or only item) to each subscriber.
Depending on how your session initialization code works, it may be more elegant to use one of the Async operators such as Async.start() or Async.startFuture() to create your session observable.
I was trying to understand how guava's AbstractService has been implemented. In the interface Service the various state transitions have been mentioned. One such transition is from STOPPING -> TERMINATED when the call to stop() is successful.
Now when I am seeing how AbstractService's stop() has been implemented, I found that on case STOPPING, they fall through and don't change the state to TERMINATED.
I may be wrong, I am just trying to learn and understand how it works.
The code for AbstractService class is given here. http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/util/concurrent/AbstractService.java?r=8d5659ad0e137d3a594014793264292a75b48bb9
Search for stop() on the page to see its implementation
When you call stop() in the RUNNING state, the state is changed to STOPPING and the doStop() method gets called. Calling stop() again after that shouldn't do anything. The doStop() implementation should call notifyStopped() which changes the state from STOPPING to TERMINATED.
A have lift app starting ssh daemon in Boot.scala.
Here is the problem: when i run container:restart / in sbt session I get Address alread in use exception.
Now two questions:
Is it right way to start dependent service in Boot.scala?
Anyway how is it possible to handle container:stop event?
I think the Lift-y way to do it is with LiftRules.unloadHooks.
It's not well-documented (AFAIK), but if you look in the Lift source code, you'll see that when the LiftServlet is destroy()ed, the functions defined in LiftRules.unloadHooks are executed.
You can add functions to the unloadHooks RulesSeq with the append or prepend method, depending on what order you want them executed in. So, in your bootstrap.liftweb.Boot.boot method, you might do something like this:
sshDaemon.start()
LiftRules.unloadHooks.append( () => sshDaemon.stop() )
(Assuming that was how you started and stopped your SSH daemon.)
I'm not 100% certain the LiftServlet.destroy() method gets invoked when the sbt web-plugin's container:restart command is run - that's determined by the plugin and its interaction with Jetty, not by Lift - but the container:stop command should definitely do the trick.
I'm not familiar with Lift, but this advice should work for any Servlet based web application.
Register a ServletContextListener in your web.xml, and release any resources in the contextDestroyed method. (The startup should be done in the contextCreated method.)
You can use setAttribute / getAttribute to store and later retrieve the server.
Putting this all together:
import javax.servlet.{ServletContextEvent, ServletContextListener}
final class SshListener extends ServletContextListener{
val attributeKey = "sshServer"
def contextInitialized(sce: ServletContextEvent) {
val server = new Server()
server.start()
sce.getServletContext.setAttribute(attributeKey, server)
}
def contextDestroyed(sce: ServletContextEvent) {
Option(sce.getServletContext.getAttribute(attributeKey)).foreach(_.asInstanceOf[Server].stop())
}
}
class Server {
def start()
def stop()
}