Uploaded image for project: 'SonarQube'
  1. SonarQube
  2. SONAR-13363

Project overview loaded twice



    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 9.1
    • Component/s: Web
    • Edition:
    • Production Notes:


      When loading the Project overview, there sometimes is a double-loading visual artifact. It shows the main app spinner, then shows the page structure (Quality Gate Panel, Measures Panel, etc), then hides the structure again to show the main spinner a second time, then finally show the page structure again.

      This was introduced with SONAR-13575. The problem comes from the call we make to /api/ce/component. We check the current property from the response payload, which corresponds to the latest task executed for the currently viewed component. If this current task applies to the same branch we're currently watching, and there was no previously known task in the queue (as far as the UI is concerned), we reload the component data.

      This is what is happening:

      • At the start of the execution, we don't have any knowledge of a "current task", so this value will always be "undefined".
      • Once we load the tasks, we will always find 1 for existing projects (e.g., the last analysis report processing). The UI will then check whether it applies to the current branch (usually it does), and compare this to the existing last task, which is undefined in this case.
      • The UI will then think a "new" task has just come in, which prompts a re-load. This is useful for a new component, where we reload the page as soon as a first analysis comes in. However, in this case, for almost all components, we do a full reload of the component at every page load.

      The only cases where we do not encounter this problem, is when the last task didn't apply to the current branch. This can happen for "Issue re-indexing" tasks, which might typically be run on maintenance branches last. So when viewing the main branch, we enter this flow:

      • At the start of the execution, we don't have any knowledge of a "current task", so this value will always be "undefined".
      • Once we load the tasks, we will find this 1 "Issue re-indexing" task. The UI then goes on to check if it applies to the current branch. If it does not, it discards it. It then checks the latest "new task", which is undefined (because if was skipped). Undefined === undefined, so it assumes no new tasks came in, and stops the loading here.

      This is what we would expect every time, for projects that had prior analyses.

      Investigation details:

      ComponentContainer#fetchComponent() is the one loading all the data (and the one being called twice).

      It can only be called:

      1. When mounted (as expected)
      2. When the URL query params change (change of branch or change of component ID, expected)
      3. When the status check thinks we need to reload (which doesn't always work as planned)

      The status check (ComponentContainer#fetchStatus()) is called right after all the necessary data to start displaying the component is loaded. It will fetch the current task queue, and will take 1 of 3 paths:

      1. If it sees there's no analysis data (empty project) OR there are currently tasks in progress, it will set a timeout to check the status again.
      2. If it sees there was change in the queue compared to the previous check, it will reload the whole component.
      3. If it sees a change in the "current" task (either being processed, or already processed), it will reload the whole component. This is buggy, because a "change" can also signify we didn't have any prior information about any task, which is always the case. This is where our problem lies.

      Now, this automatic reloading has some benefits: it will allow the Overview to automatically reload, if it detects any task is currently pending. This also applies to projects that aren't empty: in their case, the Overview will still reload if we see a new analysis is about to come in. But, there's 1 major caveat: this only works if something is in the queue at the time the Overview loads. If a new task comes in once the Overview is already loaded, nothing will happen. So, the gain seems rather minimal. You have only a very small time window where you will benefit from this feature.

      The situation is different for an empty project: in that case, the status will be polled continuously until a report task is processed, after which the window reloads to show the populated dashboard.


      First, we should only rely on "Report", "View refresh" or "App refresh" tasks. Other types won't affect the data being displayed, so they will never justify a page reload.

      For non-empty projects, it only makes sense to reload if a task was previously in progress or pending. Because only in these situations will we display a banner saying something is pending, which would explain why the UI reloads without any user interaction. If we don't say in the UI that anything was pending before, the user will not expect us to reload the page without their consent.

      The solution is to rely on this for non-empty projects (as empty projects should continue to function as before): if, at some point, we displayed a "something is in progress" banner, and the component already has an analysis date, and the current task has changed, only then do we reload.




            wouter.admiraal Wouter Admiraal
            jeremy.davis Jeremy Davis
            0 Vote for this issue
            1 Start watching this issue