Skip to content

Add optional refresh cooldown for non-admin users#7714

Open
seungoh-lee wants to merge 5 commits into
getredash:masterfrom
seungoh-lee:feature/refresh-cooldown
Open

Add optional refresh cooldown for non-admin users#7714
seungoh-lee wants to merge 5 commits into
getredash:masterfrom
seungoh-lee:feature/refresh-cooldown

Conversation

@seungoh-lee

@seungoh-lee seungoh-lee commented May 27, 2026

Copy link
Copy Markdown

What type of PR is this?

  • Feature

Description

Adds an optional refresh cooldown for non-admin users. When enabled (org setting non_admin_refresh_cooldown, in seconds), non-admin users cannot re-run a query or refresh a dashboard more frequently than the configured interval. Admins are exempt.

스크린샷 2026-05-27 오전 11 04 59
  • Backend (run_query): for non-admin users, when the cooldown is set, a forced refresh (max_age=0, or a max_age smaller than the cooldown) is raised to the cooldown value, so a recent cached result is served instead of enqueuing a new execution.
  • Frontend: a useRefreshCooldown hook drives the Query (QueryView / QuerySource) and Dashboard refresh buttons — they show a Refresh (Ns) countdown and surface a notification while on cooldown.
  • Settings: new "Non-Admin Refresh Cooldown (seconds)" field under Settings → General (exposed to the client as clientConfig.nonAdminRefreshCooldown).

Defaults to 0 (disabled), so refresh behavior is unchanged unless an admin opts in. Also configurable via the REDASH_NON_ADMIN_REFRESH_COOLDOWN environment variable.

How is this tested?

  • Unit tests (pytest, jest)
  • Manually

TestNonAdminRefreshCooldown (tests/handlers/test_query_results.py) covers: disabled-by-default forces a fresh run, an enabled cooldown serves a recent cached result to non-admins, and admins bypass the cooldown. Verified locally — backend test_query_results.py: 38 passed; frontend pnpm run test (type-check + jest): 15 suites / 89 passed; ruff + black + eslint clean. Also exercised the button countdown / notification manually in a local Docker stack.

Related Tickets & Documents

#7675

Mobile & Desktop Screenshots/Recordings (if there are UI changes)

UI changes: the Query/Dashboard refresh (and Execute) buttons show a Refresh (Ns) countdown while on cooldown, plus a "Refresh is on cooldown" notification; a new numeric setting appears under Settings → General. Screenshots to be added.

🤖 Generated with Claude Code

seungoh-lee and others added 2 commits May 27, 2026 10:33
add notification
- Default non_admin_refresh_cooldown to 0 (opt-in) so the feature does not
  alter refresh behavior for existing non-admin users unless explicitly
  enabled. Matches the "Set to 0 to disable" hint in the settings UI and
  keeps the existing test_execute_new_query behavior intact.
- Add TestNonAdminRefreshCooldown: disabled-by-default forces a fresh run,
  an enabled cooldown serves a recent cached result to non-admins, and
  admins bypass the cooldown entirely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 10 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread client/app/pages/queries/QuerySource.jsx Outdated
The refresh-cooldown countdown state lived at the top of QuerySource and
QueryView, so during an active cooldown setInterval re-rendered the whole
page (editor + visualizations) every second.

Split useRefreshCooldown into a pure click-time gate
(notifyRefreshCooldown / getRefreshCooldownRemaining) and the ticking
display hook. The page now evaluates the cooldown gate at click time and
the per-second countdown lives in a small RefreshCooldownLabel leaf, so
only the button label re-renders while on cooldown. Execution gating
(button, keyboard shortcut, parameter-change paths) is unchanged.

DashboardHeader already scoped the hook to its RefreshButton leaf and is
left untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="client/app/lib/hooks/useRefreshCooldown.js">

<violation number="1" location="client/app/lib/hooks/useRefreshCooldown.js:60">
P2: useEffect only depends on retrievedAt but reads mutable globals (currentUser.isAdmin, clientConfig.nonAdminRefreshCooldown), so UI cooldown state can become stale when those globals change at runtime without retrievedAt changing.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread client/app/pages/queries/QueryView.jsx
Comment thread client/app/pages/queries/QuerySource.jsx
Comment thread client/app/lib/hooks/useRefreshCooldown.js
@seungoh-lee

Copy link
Copy Markdown
Author

@yoshiokatsuneo I would appreciate it if you could review the PR? Thanks

@seungoh-lee

seungoh-lee commented Jun 18, 2026

Copy link
Copy Markdown
Author

Friendly bump this PR has been open for a few weeks now and is still passing CI. Whenever a maintainer has a spare moment, I'd really appreciate a review. Happy to rebase or address any feedback.
cc @yoshiokatsuneo, @arikfr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant