Fix trial widget delayed on initial landing after registration
Summary
After a user completes trial registration, the trial is provisioned asynchronously. This causes a brief flash where the free-tier UI (free namespace icon, "Free" tier badge) is shown before the real trial data arrives from CustomersDot.
This MR implements Solution 3 from the issue discussion: a short-lived Rails.cache presence marker that allows in-scope surfaces to render the trial state optimistically until real data lands.
What Changed
Surface 1: Left-nav trial widget (StatusWidgetPresenter)
Added optimistic_trial_active? predicate:
- Returns
trueonly when (a) marker is active AND (b) no real trial yet exists - Real data always wins — the moment
eligible_trial_active?is true, the optimistic branch is never taken - When active,
trial_statusderives dates fromTrialDurationService(start = now, end = now + trial duration days)
Surface 2: Project/group home page free-tier badge (TrialsHelper#show_tier_badge_for_new_trial?)
Returns false when the pending trial marker is active, suppressing the badge during the window.
Guardrails
- Marker written only on successful trial submission (never written on failure)
- Optimistic branch taken only when marker active AND no real trial row exists
- Real data always wins over fake data
- Marker self-expires at 5 minutes — no cleanup code needed
- Provisioning flow is completely unchanged
Screenshots/videos
Note that billing page is out of scope. We only care about landing page right after trial application, which is the project page
How to reproduce locally
Verifying that in-scope surfaces render trial state optimistically while the trial is still being provisioned. The natural race is a brief window between trial submission and CustomersDot returning real trial data, so it is impractical to catch by hand — instead, simulate the marker directly.
Setup
These are SaaS-only code paths. Enable SaaS simulation in your GDK:
echo 'GITLAB_SIMULATE_SAAS=1' >> env.runit
gdk restartFast path: simulate the marker
Pick a group you own that has no trial and no paid subscription. From rails console:
group = Group.find_by_full_path('your-group-path')
GitlabSubscriptions::Trials::PendingTrialMarker.set(group.id)
GitlabSubscriptions::Trials::PendingTrialMarker.active?(group.id)
# => trueThen load the group's home page and observe:
- The left-nav trial widget appears, showing roughly 30 days remaining (dates come from
GitlabSubscriptions::TrialDurationService— start is today, end is today + duration days). - The "Free" tier badge on the group/project home page is gone.
The marker TTL is CACHE_TTL = 5.minutes, so it self-expires. Reload after five minutes (or clear it manually with Rails.cache.delete("gitlab_subscriptions:trials:pending_trial_marker:#{group.id}")) and confirm the UI reverts to free-tier: badge returns, widget disappears.
What are the relevant issue numbers?
Related to https://gitlab.com/gitlab-org/gitlab/-/issues/587952