Announcement Announcement Module
Collapse
No announcement yet.
Remoting and long running processes Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Remoting and long running processes

    I have a use case where a client can initiate, thru a remote call, a long running process on the server. By long running, I mean something that can run for a few minutes (up to a couple of hours).

    The user must be able to start the process, track its progress, cancel it if necessary.

    It seems to me that the only way to get this is to make the client poll the server at uniform intervals, and spawn a separate thread on the server to perform the long running task. In the beginning I was thinking that the server should have sent back to the client "events" as in a classic "Observer" pattern, but it seems to be more trouble than it's worth.

    Does anyone of you have some experience on such a use case? Any consideration, comment is appreciated.

  • #2
    Instead of spawning a separate thread on the server I would suggest a thread pool. There is a JSR 166 backport (http://www.mathcs.emory.edu/dcl/util...il-concurrent/) if you can't upgrade to a 1.5 JVM.

    The Observer is a bit more work. Polling is probably the simplest to implement and I would certainly do that first to get the app working.

    If your client is a long-running process (e.g. - a webapp) you might consider letting it export a remote service of its own. Then, when it submits the request it could provide a 'return address' for progress updates and such.

    Comment


    • #3
      Originally posted by jcej
      Instead of spawning a separate thread on the server I would suggest a thread pool. There is a JSR 166 backport (http://www.mathcs.emory.edu/dcl/util...il-concurrent/) if you can't upgrade to a 1.5 JVM.
      Nice, I'll have a look at it.

      The Observer is a bit more work. Polling is probably the simplest to implement and I would certainly do that first to get the app working.

      If your client is a long-running process (e.g. - a webapp) you might consider letting it export a remote service of its own. Then, when it submits the request it could provide a 'return address' for progress updates and such.
      Unfortunately it's a rich client that could be behind some NAT or firewall, so I simply can't use this solution... I would need something like a persistent connection initiated by the client, but apparently there is no support for this approach in Spring remoting.

      Comment


      • #4
        Can you have the remote client write an entry to the db, which is polled by a something that can start Quartz jobs?

        That way, you don't have to write your own job scheduling/handling system.

        Comment


        • #5
          Originally posted by gmatthews
          Can you have the remote client write an entry to the db, which is polled by a something that can start Quartz jobs?

          That way, you don't have to write your own job scheduling/handling system.
          Hum... the client will have a progress bar and a cancel button, this means that the long running process must start right away and be controllable. I would have to poll the database each 0.5/1 seconds and then, how do I interact with the Quartz job?
          You see, it's not really scheduling, it's an interactive long running process. When it ends, I have to show the user a report. In one case, I have to wait for an intermediate result, have the user confirm it, and start the second part of the long running process (possibily without removing what I have done so far from the main memory).

          Comment


          • #6
            Can you elaborate on exactly what your long running process is?

            Comment


            • #7
              Originally posted by gmatthews
              Can you elaborate on exactly what your long running process is?
              Metereological data validation and analysis. The data rows under analysis may be hundred of thousands. Usually the process is scheduled, but the user may request interactive runs in order to test new validation and configuration parameters, or to invalidate a scheduled run that did not get proper results.

              Comment


              • #8
                I've implemented a similar requirement as follows. On the server we present a simple facade with an interface like this:

                Code:
                interface LongRunningJobManager {
                      JobKey start(JobDefinition jobDefinition);
                      JobStatus getStatus(JobKey jobKey);
                      void cancel(JobKey jobKey);
                }
                behind this facade is a thread pool for running the jobs and a map from JobKey to status+executing thread of each active job. On the client we adapt this (convenient for remoting but not for the client) interface to the following:

                Code:
                interface LongRunningJob {
                      JobDefinition getDefinition();
                      void start();
                      void cancel();
                      void addJobEventListener(JobEventListener listener);
                }
                
                interface JobEventListener {
                      void jobStarted(LongRunningJob job);
                      void jobCompletedSomeWork(LongRunningJob job, JobStatus status);
                      void jobCancelled(LongRunningJob job);
                      void jobFinished(LongRunningJob job, JobResult result);
                }
                The implementation of LongRunningJob simply pools the server interface at some useful interval (to cut down on remote invocations we use an adaptive interval that is based on the rate the job is progressing) and if you're using Swing remember to fire the JobEventListener methods in the event dispatch thread!

                HTH

                Ollie

                Comment


                • #9
                  Oliver, that's more or less what I have here now (I've started developing it yesterday).
                  Yet, the adaptive polling is a nice touch I didn't thought about.
                  Willing to share some more details? ;-)

                  Comment


                  • #10
                    The jobs in our system progress at a reasonably predicable rate so initially we poll quite frequently but once we've received enough status info to roughly guess when the job will be complete we slow down the polling considerably. To keep the user happy we also spawn a thread that updates a status bar every 250ms based on an estimate of the actual progress - it's important that something is hapening on the screen to indicate that the job is actualy progressing.

                    Ollie

                    Comment


                    • #11
                      Ollie,

                      behind this facade is a thread pool for running the jobs and a map from JobKey to status+executing thread of each active job.
                      I was wondering what is this status you are returning. I mean is it something you persist somwhere or I guess i am wondering how to measure this as its running in some thread?

                      Amad

                      Comment


                      • #12
                        Amad,

                        my example above is not an exactly copy of our system it's merely intended as a clear example of the approach we use.

                        In our system the JobKey is just a String it could be an int, long or anything that uniquely identifies each job. For thread pooling we have just switched to using a Java 1.5 ExecutorService allocated using Executors.newCachedThreadPool() - if your using Java 1.4/3 there's plenty of thread pool implementations including back port of the Java 1.5 stuff.

                        The job status info is updated by each job as it progresses through it's various tasks. In out system this is quite simple as we have lots of small steps which gives us lots of opportunity to update this value, however if your job is on the monolithic side you may not be able to update the status so often (an indeterminate progress bar can be a big help here)

                        Ollie

                        Comment


                        • #13
                          if your job is on the monolithic side you may not be able to update the status so often (an indeterminate progress bar can be a big help here)
                          Thats the case I am working with, so would advice aginst persisting the state of task in database or some persistent store?

                          Is there anything on richclient side you are using (ActionCommand etc) that is helping you to update the client status. (i.e progress bar in status bar).

                          Amad

                          Comment


                          • #14
                            Thats the case I am working with, so would advice aginst persisting the state of task in database or some persistent store?
                            If there's no way to know how long the job's going to take or how much it's progressed then attempting maintaining any progress info is pointless. Perhaps you could use the average execution time of your jobs as a base point to guess the execution time of new jobs?

                            Is there anything on rich client side you are using (ActionCommand etc) that is helping you to update the client status. (i.e progress bar in status bar).
                            Not really. We have a dialog that pops up showing the progress bar (which is updated by a timer thread) and a cancel button. I could imagine a much nicer solution, along the lines of Eclipse's job running system, with the ability to send jobs to the background etc. but this is not a requirement for us.

                            Ollie

                            Comment

                            Working...
                            X