0

We have a web application in Java which calls progress procedures. Progress 4gl version is 10.x and is on AIX.

Requirement is to implement the following functionality: Suppose that a progress procedure is called by the web application. This makes an appserver transaction to run. While the transaction is processing, if the user closes the browser window the appserver process needs to be identified and should be killed using its process id. Killing of process can be implemented by invoking a shell script. How to identify the appserver process id for a web application session which is about to be closed?

  • How, specifically, does the "web application in Java" call the Progress app-server? Is the "web application in Java" aware that the user closed the browser window? Is the "web application in Java" expected to kill the app server session? Or is some uninvolved 3rd party supposed to magically understand the linkage between them? – Tom Bascom Aug 08 '14 at 16:49

3 Answers3

0

If the appserver process takes long enough that this is a concern, then you're doing something wrong - typically round-trip calls to an appserver should be so short that a closing a browser in the meantime wouldn't matter.

Second, if you're running state-free, there's no way to know which appserver agent a call is running as the last call could've been routed to any of a number of agents, and there's no handshaking back to the caller as to which one that is.

As such, the only reasonable way to do what you're looking for is to

  1. have the browser application fire off a 'cancel my operation' call to the web infrastructure and update a database field to indicate this request
  2. have the program(s) the appserver is running do periodic db table field checks to see if it's current operation's been cancelled, and quit processing if that flag has been set.
Tim Kuehn
  • 3,201
  • 1
  • 17
  • 23
  • The appserver process invoked by the web application is doing certain calculations as well as database updates. Data being processed is huge and so the process is taking a few minutes to complete. In the meantime, the user is getting impatient and closing the browser window, opening another window and trying the same action. This is resulting in table deadlocks. We have to run promon; identify the process id of the process holding the table lock (this could be the process invoked by the browser session which is already closed) and manually kill the process to release the table. – Kashyap Bakshi Aug 08 '14 at 20:00
  • Instead of manually killing the process, the idea is to track the browser closing action (show an alert message to user) and if user still chooses to close, kill the appserver process thus releasing the table locks. – Kashyap Bakshi Aug 08 '14 at 20:00
  • Again, tracking to the specific appserver will be difficult if not impossible, and killing an appserver agent isn't without it's own dangers - which can include crashing the db. The suggested course of action I've posted in this answer is the only safe way to cleanly stop the appserver agent from doing it's work, and accomplish what you're after. – Tim Kuehn Aug 08 '14 at 20:16
  • Another option would be to put the command into a batch file, and then have a background process pick up the command, do the execution, and then make the results available to the user in some manner. The system could notify the user when it's done via email, or by using a messaging system tied to the browser. – Tim Kuehn Aug 08 '14 at 20:18
  • An other possible fix is to put an "operation pending" flag in the database and if someone tries to run it while another process is already running it, then return an "already running, try again later" message. Deadlock problem solved. – Tim Kuehn Aug 09 '14 at 14:00
0

So the real issue is that you have long running tasks that users abandon and retry out of impatience (and possibly due to lack of feedback on the progress of the task)?

You haven't provided any details about your "web application in Java" so I don't really know what you are doing or how it relates to the Progress app server sessions.

In order for the web application to kill a process running remotely it will need to have some sort of reference to that remote process. It sounds like you are currently calling the remote process synchronously and waiting for a response. The first thing that you need to do is to call the remote process asynchronously (Progress does support asynchronous app server calls. That might be one starting point. But that depends on what "web application in Java" means.)

If you can somehow call the process asynchronously then you should obtain the PID (or some other unique identifier that can be used to xref the process) when you initiate it. That could then be used when you pop-up your confirmation alert-box to properly feed your "kill" command.

If you cannot figure out how to make an asynchronous app server call the crude way of emulating such things using a synchronous call is to marshall the request (and response) via a db table:

  1. Insert a record describing the request, provide all necessary parameters and context to start the request independently and then return a request id to the caller.

  2. The caller then loops -- pause for a period and check the status of the request. This should be a very simple call that just reads the request record from the db to pull its status.

  3. On the remote side one or more batch processes are looping reading the request table looking for new records. When they find one they launch a process to execute the request. You can get fancy here with all sorts of controls and load balancing stuff or you can keep it simple and easy.

  4. The process executing the request updates the status record as appropriate so that the web browser client can see what is going on. (step #2)

  5. When the request is finished the result is fed back to the client -- possibly via a db table or maybe as a new page. That depends on the application. The basic idea is that when step #2 notices the status is "complete" it then does whatever is appropriate to fecth the result.

If the client decides to kill a request it should have received enough information in step #1 to pass that reference to the server so that the server can act on it. Usually you would want to update the status of the request record to "killed" (or whatever) and then either allow the sub process to notice that and terminate itself or use OS level tools to execute an actual "kill".

BTW -- if you appropriately organize the "context and parameters" portion of this you might be able to recognize and eliminate duplicate requests or at least cache the answers.

Tom Bascom
  • 13,405
  • 2
  • 27
  • 33
0

You have two good answers from both Tom and Tim. I think you need to rethink your architecture.

But that doesn't answer the question about getting the PID. Assuming that you run some kind of connection to an Progress AppServer, that AppServer is running a .p-program and in that program you could do:

FIND FIRST _MyConnection NO-LOCK.
/* You might not want to DISPLAY but rather do something else: */
DISPLAY _MyConnection._MyConn-Pid.

You could also do this in the OS. Assuming you have run the proenv-script so you have your environment set up you can do:

wtbman -name asXXX -query

(Replace asXXX with the name of your appserver - default is asbroker1).

Output is something like this:

OpenEdge Release 11.3.1 as of Fri Sep 13 19:00:23 EDT 2013


Connecting to Progress AdminServer using rmi://localhost:xxxx/Chimera (8280)
Searching for asXXX (8288)
Connecting to asXXX  (8276)
Incorrect utility to use for asXXX (15827)

Broker Name                    : asXXX
Operating Mode                 : State-reset
Broker Status                  :  ACTIVE
Broker Port                    : YYYY
Broker PID                     : ZZZZ
Active Servers                 : 2
Busy Servers                   : 0
Locked Servers                 : 0
Available Servers              : 2
Active Clients (now, peak)     : (0, 2)
Client Queue Depth (cur, max)  : (0, 2)
Total Requests                 : 26322
Rq Wait (max, avg)             : (18079 ms, 25 ms)
Rq Duration (max, avg)         : (18079 ms, 25 ms)

PID   State     Port  nRq    nRcvd  nSent  Started          Last Change
16319 AVAILABLE ZZZZZ 001447 001447 001447 Aug 8, 2014 11:50 Aug 14, 2014 13:20
16320 BUSY      ZZZZZ 001385 001385 001385 Aug 8, 2014 11:50 Aug 14, 2014 13:10

Look at the list of pids. 16319 is AVAILABLE and 16320 is busy and has been for 10 minutes (if the time is 13:20 right now). That tells us that PID 16320 most likely is the hanging procedure.

Now you can do:

asbman -name asxxx -agentdetail 16320

That will give you more information like PROPATH, Stack trace and connected databases. Very helpful when looking for problems.

Jensd
  • 7,886
  • 2
  • 28
  • 37