Mo Ziauddin
Mo Ziauddin

Reputation: 410

Grails view hangs when calling a controller action

I have a view that has a link using the g:link GSP tag with action that runs and updates on a significant number of rows, so it takes some time. In the meantime, the browser is in limbo and times out after 30 sec (which is the timeout on the servlet container).

Problem:

  1. It is a bad user experience that the page times out.
  2. The browser submits the controller action each time the timeout occurs. I have handled this by checking if the query is already running so this is no longer an issue.

Question:

How can I trigger the controller action and reload the page to the same view? Or is there a better way to handle this like triggering the action async?

I tried to reload the page using js, but it does not seem to reload the page. I have read about implementing a message queue, but it seems like a lot of work for a simple issue. Any ideas will be good. Thank you in advance.

View:

<li>
  <a class=""
     href="${g.createLink(controller: "hello", action: "dbAction")}">Run Update on DB
  </a>
</li>

Controller Action:

def dbAction() {
        some code...
        myservice.dbAction();
        redirect(action: 'index')progress"
        }
    }

My Service dbAction:

def dbAction() {
    Sql sql = getSql()
    sql.executeUpdate('''
    update mytable
    set
        mydata = calculate_data,
        updated_by = 'dbAction',
        updated_at = now()
    where
        id in (1,2,3)
}

Upvotes: 1

Views: 119

Answers (1)

tom6502
tom6502

Reputation: 190

I have exactly your problem. The query takes so long to run, the controller cannot respond back to the browser. So, the browser times out.

I tried 3 different ways to fix this.

The easy way out: I am using Tomcat. So, I set the connection timeout value longer. The connectionTimeout variable is in the server.xml file.

The lazy way out: I don't know if Grails has any sort of Message Queue function or not. So, I rolled my own. When I click the submit button to run a very long update query, the action will INSERT INTO a sort of update command in a database table along with the state. I then use Quartz to schedule maybe every 10 seconds to read this table to check the state. If the state is NEW, I change the state to "IN PROGRESS". And then I let the trigger to run the update query in the background. After it finish, I change the state to FINISH.

So, the action is just adding a row to the database and then respond back the view that says something like... You have issued the request. The system will process your request in a few moment.

The hard way out: I went over all my SQL and functions in the actions to calculate the time it will take the SQL and codes to finish the query. I then rearrange/rewrite the functions and procedures. I am not good enough for this. If I can get to O(n), that will be enough for me.

Upvotes: 1

Related Questions