Uploaded image for project: 'Tapestry 5'
  1. Tapestry 5
  2. TAP5-256

Page Pool Limit exhausted when exception occurs (during PageAttached lifecycle) on a link

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 5.0.15
    • 5.0.16
    • tapestry-core
    • None

    Description

      Whenever an exception occurs on a linked page (PageA in the attached example code), the size of the "inUse" LinkedList is never reset. The reason for this is that Tapestry has no chance to mark the page causing the exception (PageA) as dirty and add it to the request page cache. Therefore at the end of the request, when the thread cleanup event occurs, the page in error is never removed (when dirty) and released. However the requested page (PageB in the attached JMeter test) is marked as dirty and added to the request page cache and is subsequently removed and released.

      I have attached a sample project which has 3 pages (PageA, PageB, and PageC). On each page, there is side menu that links to PageA, B and C. In PageA during the PageAttached lifecycle, I have added a Runtime exception (note that in our production environment we are getting Connection reset exceptions). To run this application, you need to do the following:

      • Extract the attached tutorial1.zip
      • mvn clean install
      • mvn jetty:run

      A Jmeter test (PagePoolLoadTest.jmx) has also been provided, to automatically go to PageB and assert that the exception generated by PageA exists as part of the response. The test has 20 concurrent users which should run successfully during the first attempt. However, during the second attempt, the test should fail because Tapestry will report that page pool limit exceeded for PageA eventhough there are only 20 concurrent users.

      The patch I applied to our production version of Tapestry (5.0.15) is to modify the RequestpageCacheImpl get method to catch the RuntimeException and mark the page as dirty and add it to the request page cache:

      public Page get(String logicalPageName)
      {
      Page page = cache.get(logicalPageName);

      if (page == null)
      {
      page = pagePool.checkout(logicalPageName);

      try

      { page.attached(); cache.put(logicalPageName, page); }

      catch(RuntimeException e)

      { page.incrementDirtyCount(); cache.put(logicalPageName, page); throw e; }

      }

      return page;
      }

      Attachments

        1. tutorial1.zip
          36 kB
          Carlo Simbag
        2. PagePoolLoadTest.jmx
          10 kB
          Carlo Simbag

        Activity

          People

            hlship Howard Lewis Ship
            csimbag Carlo Simbag
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: