2025-05-20 09:40:15 +00:00
|
|
|
// Copyright 2025 Cloudbase Solutions SRL
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
|
// not use this file except in compliance with the License. You may obtain
|
|
|
|
|
// a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
|
// License for the specific language governing permissions and limitations
|
|
|
|
|
// under the License.
|
2025-04-16 16:39:16 +00:00
|
|
|
package cache
|
|
|
|
|
|
|
|
|
|
import (
|
2025-05-14 21:09:02 +00:00
|
|
|
"fmt"
|
2025-04-16 16:39:16 +00:00
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
|
|
|
|
"github.com/cloudbase/garm/params"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var githubToolsCache *GithubToolsCache
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
ghToolsCache := &GithubToolsCache{
|
|
|
|
|
entities: make(map[string]GithubEntityTools),
|
|
|
|
|
}
|
|
|
|
|
githubToolsCache = ghToolsCache
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type GithubEntityTools struct {
|
|
|
|
|
updatedAt time.Time
|
2025-05-14 00:34:54 +00:00
|
|
|
expiresAt time.Time
|
2025-05-14 21:09:02 +00:00
|
|
|
err error
|
2025-05-12 21:47:13 +00:00
|
|
|
entity params.ForgeEntity
|
2025-04-16 16:39:16 +00:00
|
|
|
tools []commonParams.RunnerApplicationDownload
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type GithubToolsCache struct {
|
|
|
|
|
mux sync.Mutex
|
|
|
|
|
// entity IDs are UUID4s. It is highly unlikely they will collide (🤞).
|
|
|
|
|
entities map[string]GithubEntityTools
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 21:09:02 +00:00
|
|
|
func (g *GithubToolsCache) Get(entityID string) ([]commonParams.RunnerApplicationDownload, error) {
|
2025-04-16 16:39:16 +00:00
|
|
|
g.mux.Lock()
|
|
|
|
|
defer g.mux.Unlock()
|
|
|
|
|
|
2025-05-07 23:01:22 +00:00
|
|
|
if cache, ok := g.entities[entityID]; ok {
|
2025-05-14 00:34:54 +00:00
|
|
|
if cache.entity.Credentials.ForgeType == params.GithubEndpointType {
|
|
|
|
|
if time.Now().UTC().After(cache.expiresAt.Add(-5 * time.Minute)) {
|
|
|
|
|
// Stale cache, remove it.
|
|
|
|
|
delete(g.entities, entityID)
|
2025-05-14 21:09:02 +00:00
|
|
|
return nil, fmt.Errorf("cache expired for entity %s", entityID)
|
2025-05-14 00:34:54 +00:00
|
|
|
}
|
2025-04-16 16:39:16 +00:00
|
|
|
}
|
2025-05-19 19:45:45 +00:00
|
|
|
if cache.err != nil {
|
|
|
|
|
return nil, cache.err
|
|
|
|
|
}
|
|
|
|
|
return cache.tools, nil
|
2025-04-16 16:39:16 +00:00
|
|
|
}
|
2025-05-14 21:09:02 +00:00
|
|
|
return nil, fmt.Errorf("no cache found for entity %s", entityID)
|
2025-04-16 16:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
2025-05-12 21:47:13 +00:00
|
|
|
func (g *GithubToolsCache) Set(entity params.ForgeEntity, tools []commonParams.RunnerApplicationDownload) {
|
2025-04-16 16:39:16 +00:00
|
|
|
g.mux.Lock()
|
|
|
|
|
defer g.mux.Unlock()
|
|
|
|
|
|
2025-05-14 00:34:54 +00:00
|
|
|
forgeTools := GithubEntityTools{
|
2025-04-16 16:39:16 +00:00
|
|
|
updatedAt: time.Now(),
|
|
|
|
|
entity: entity,
|
|
|
|
|
tools: tools,
|
2025-05-14 21:09:02 +00:00
|
|
|
err: nil,
|
2025-04-16 16:39:16 +00:00
|
|
|
}
|
2025-05-14 00:34:54 +00:00
|
|
|
|
|
|
|
|
if entity.Credentials.ForgeType == params.GithubEndpointType {
|
2025-05-14 23:20:18 +00:00
|
|
|
forgeTools.expiresAt = time.Now().Add(1 * time.Hour)
|
2025-05-14 00:34:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g.entities[entity.ID] = forgeTools
|
2025-04-16 16:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 21:09:02 +00:00
|
|
|
func (g *GithubToolsCache) SetToolsError(entity params.ForgeEntity, err error) {
|
|
|
|
|
g.mux.Lock()
|
|
|
|
|
defer g.mux.Unlock()
|
|
|
|
|
|
|
|
|
|
// If the entity is not in the cache, add it with the error.
|
|
|
|
|
cache, ok := g.entities[entity.ID]
|
|
|
|
|
if !ok {
|
|
|
|
|
g.entities[entity.ID] = GithubEntityTools{
|
|
|
|
|
updatedAt: time.Now(),
|
|
|
|
|
entity: entity,
|
|
|
|
|
err: err,
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the error for the existing entity.
|
|
|
|
|
cache.err = err
|
|
|
|
|
g.entities[entity.ID] = cache
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-12 21:47:13 +00:00
|
|
|
func SetGithubToolsCache(entity params.ForgeEntity, tools []commonParams.RunnerApplicationDownload) {
|
2025-04-16 16:39:16 +00:00
|
|
|
githubToolsCache.Set(entity, tools)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 21:09:02 +00:00
|
|
|
func GetGithubToolsCache(entityID string) ([]commonParams.RunnerApplicationDownload, error) {
|
2025-05-07 23:01:22 +00:00
|
|
|
return githubToolsCache.Get(entityID)
|
2025-04-16 16:39:16 +00:00
|
|
|
}
|
2025-05-19 19:45:45 +00:00
|
|
|
|
|
|
|
|
func SetGithubToolsCacheError(entity params.ForgeEntity, err error) {
|
|
|
|
|
githubToolsCache.SetToolsError(entity, err)
|
|
|
|
|
}
|