LoadSubscription will load subscription. If there is no license, we will return a free plan subscription without expiration time. If there is expired license, we will return a free plan subscription with the expiration time of the expired license.
(ctx context.Context, workspaceID string)
| 199 | // If there is no license, we will return a free plan subscription without expiration time. |
| 200 | // If there is expired license, we will return a free plan subscription with the expiration time of the expired license. |
| 201 | func (s *LicenseService) LoadSubscription(ctx context.Context, workspaceID string) *v1pb.Subscription { |
| 202 | if workspaceID == "" { |
| 203 | return defaultFreeSubscription |
| 204 | } |
| 205 | key := licenseCacheKey(workspaceID) |
| 206 | |
| 207 | // Fast path: cache hit (TTL handled automatically by expirable.LRU) |
| 208 | if sub, ok := s.cache.Get(key); ok { |
| 209 | return sub |
| 210 | } |
| 211 | |
| 212 | // Slow path: load from DB with singleflight to prevent thundering herd |
| 213 | v, _, _ := s.sfGroup.Do(key, func() (any, error) { |
| 214 | // Double check after entering singleflight |
| 215 | if sub, ok := s.cache.Get(key); ok { |
| 216 | return sub, nil |
| 217 | } |
| 218 | |
| 219 | subscription := s.loadSubscriptionFromDB(ctx, workspaceID) |
| 220 | |
| 221 | // Only cache non-free subscriptions. Free plan may be a transient failure |
| 222 | // (e.g. DB not ready during startup), and caching it would mask the real |
| 223 | // license for the TTL duration. |
| 224 | if subscription.Plan != v1pb.PlanType_FREE { |
| 225 | s.cache.Add(key, subscription) |
| 226 | } |
| 227 | return subscription, nil |
| 228 | }) |
| 229 | |
| 230 | if sub, ok := v.(*v1pb.Subscription); ok { |
| 231 | return sub |
| 232 | } |
| 233 | return defaultFreeSubscription |
| 234 | } |
| 235 | |
| 236 | func (s *LicenseService) loadSubscriptionFromDB(ctx context.Context, workspaceID string) *v1pb.Subscription { |
| 237 | setting, err := s.store.GetSystemSetting(ctx, workspaceID) |
no test coverage detected