| 132 | } |
| 133 | |
| 134 | func (c *chatConfigCache) EnabledProviders(ctx context.Context) ([]database.AIProvider, error) { |
| 135 | if providers, ok := c.cachedProviders(); ok { |
| 136 | return providers, nil |
| 137 | } |
| 138 | |
| 139 | generation := c.providersGeneration() |
| 140 | providers, err := singleflightDoChan( |
| 141 | ctx, |
| 142 | &c.providerFetches, |
| 143 | fmt.Sprintf("%d:providers", generation), |
| 144 | func() ([]database.AIProvider, error) { |
| 145 | if cached, ok := c.cachedProviders(); ok { |
| 146 | return cached, nil |
| 147 | } |
| 148 | |
| 149 | fetched, err := c.db.GetAIProviders(c.ctx, database.GetAIProvidersParams{}) |
| 150 | if err != nil { |
| 151 | return nil, err |
| 152 | } |
| 153 | c.storeProviders(generation, fetched) |
| 154 | return slices.Clone(fetched), nil |
| 155 | }, |
| 156 | ) |
| 157 | if err != nil { |
| 158 | return nil, err |
| 159 | } |
| 160 | |
| 161 | return slices.Clone(providers), nil |
| 162 | } |
| 163 | |
| 164 | func (c *chatConfigCache) cachedProviders() ([]database.AIProvider, bool) { |
| 165 | c.mu.RLock() |