> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neuro-tech.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Refresh reports for a dashboard

> Run reports on a backend schedule, cache completed results, and provide a controlled manual refresh.

Run a report in a backend job and serve its last successful result to your dashboard.
Report execution can be expensive. Opening, reloading, or navigating a dashboard should read cached data rather than start another report.

## Choose a refresh policy

Agree on data freshness and execution frequency with your provider before enabling recurring runs.
Choose one of these policies:

| Policy                        | When to use it                                                             | Behavior                                                                                      |
| ----------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| Scheduled                     | Users need a regularly updated summary.                                    | A backend scheduler starts a job at the agreed interval. All viewers share its cached result. |
| Manual                        | Reports are needed occasionally.                                           | An authorized user requests a refresh; the backend queues one job and returns immediately.    |
| Scheduled with manual refresh | Users normally accept scheduled data but occasionally need a newer result. | Manual requests use the same queue, concurrency limit, and cooldown as scheduled jobs.        |

For daily statistics, once per day after the reporting day closes is a reasonable starting proposal.
For example, `0 2 * * *` on a scheduler explicitly configured for UTC means 02:00 UTC daily.
This example is an application choice, not a service limit or a guarantee that the provider's data is complete at that time.
Confirm the time and acceptable data age with your provider.

## Separate execution from dashboard reads

```mermaid theme={null}
flowchart LR
    S[Backend schedule] --> Q[Refresh queue]
    M[Authorized manual refresh] --> Q
    Q --> W[One report worker]
    W --> A[Agent API]
    A --> W
    W --> C[Last successful result]
    C --> B[Dashboard backend]
    B --> D[Dashboard viewers]
```

The report worker signs in, resolves the target, submits the report, and collects progress to completion.
It replaces the cached result only after checking completion, errors, and the expected output.
See [Run a report over HTTP](/reports/execute-over-http) for the API sequence.

Keep the Agent API password and JWT in the backend. Browser users authenticate to your application and receive only the data they are allowed to see.
An expired Agent API JWT does not invalidate an already completed cached report.

## Prevent duplicate work

* Acquire a shared lock before starting a refresh. Use a lock shared across backend instances, not just an in-memory browser flag.
* If a matching job is already running, return its status instead of submitting another execution.
* Apply a server-side cooldown to manual requests. Disabling a button alone does not prevent duplicate requests.
* Skip or coalesce a scheduled refresh when the previous one is still active.
* Do not tie report submission to component mounting, page loads, UI polling, or each viewer's session.

With `PopMessages`, use one consumer for the Agent API account and dispatch messages by their query ID.
For an initial integration, serialize report runs for that account. Competing consumers can take each other's progress messages.
The [execution guide](/reports/execute-over-http#collect-progress-messages) explains why polling consumes account messages.

## Choose explicit report parameters

Calculate the reporting window once when the job starts, in the report's documented time zone.
Persist those dates with the result so the dashboard shows the actual period that was requested.

For a UTC report, two possible policies are:

* Previous complete day: yesterday for both start and end dates, if the report uses inclusive dates.
* Trailing seven complete days: UTC today minus seven days through UTC yesterday, if dates are inclusive.

Confirm the report's date semantics rather than inferring them from its filename.
Current-state metrics and lifetime counters may be independent of the selected dates.
Show both the reporting period and the result's completion time.

If the report has optional parameters that save snapshots or perform other writes, leave them unset for ordinary dashboard refreshes unless that behavior is intended.
Do not assume a report is read-only because it produces statistics.

## Store the last successful result

Scope the cache to the authorized tenant or account, Neuron host, Reports JID, report ID, language, and normalized parameter values.
Avoid sharing cached data across tenants merely because the report ID matches.

Store the completed output together with:

| Metadata              | Purpose                                                          |
| --------------------- | ---------------------------------------------------------------- |
| Requested parameters  | Identify the exact date window and options.                      |
| Query ID              | Correlate execution with diagnostics.                            |
| Completion timestamp  | Show when the cached result was last refreshed.                  |
| Last attempt status   | Show whether a refresh is queued, running, completed, or failed. |
| Expected next refresh | Explain when new data is normally due.                           |

Keep the previous successful result while a new run is in progress.
If the new run fails, retain the previous result and label it as stale with the last successful refresh time.
An aborted query, a timeout, or an incomplete table must not replace a complete cached result.

## Handle manual refresh and first use

An authorized refresh request should enqueue work and return a job status from your backend.
The browser can poll your backend for that status; each status poll must not execute another Neuron report.
When the job completes, the dashboard reads the updated cache.

Before any successful run exists, show a pending or unavailable state and queue at most one initial job.
Do not let every visitor independently trigger the first execution.

## Recover from failures

Distinguish a rejected submission from an accepted execution whose completion was not observed.
A client timeout does not cancel the Neuron query. Keep its ID and avoid automatically submitting a second expensive run.
Use a bounded retry policy for failures where a new attempt is appropriate, and do not retry permission failures until access is corrected.

The application owns its scheduler, cache, locks, deadlines, and cooldowns. The Reports API does not provide these merely because execution is asynchronous.

## Verify before rollout

1. Run the intended report with the partner account and explicit parameters.
2. Check the returned table IDs, columns, cell types, and error messages against the dashboard's needs.
3. Open the dashboard in multiple sessions and confirm that these reads start no new Neuron executions.
4. Request refresh twice and confirm that only one job runs.
5. Confirm that a failed refresh retains the last successful result and shows its age.

Use [report response formats](/reports/responses) when mapping the result to your dashboard.
