-
Notifications
You must be signed in to change notification settings - Fork 12
feat: add backend caching for AMT API endpoints #768
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nmgaston
wants to merge
28
commits into
device-management-toolkit:main
Choose a base branch
from
nmgaston:backendCaching
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
4a97c60
feat: add backend caching for AMT API endpoints
nmgaston 3287fdc
Merge branch 'main' into backendCaching
nmgaston 177381f
fix: remove unused time imports from devices package
nmgaston 722eb74
fix: resolve golangci-lint issues (godot, nlreturn, wsl_v5)
nmgaston b2c3fc7
fix: add periods to remaining godoc comments in keys.go
nmgaston 6868be0
feat: add combined KVM initialization endpoint
nmgaston e96a3e4
feat: add Prometheus and Grafana to docker-compose
nmgaston 2f48991
chore: format files
nmgaston a079f42
fix: add missing methods to ws/v1 Feature interface and regenerate mocks
nmgaston 7bc9d8d
fix: create prometheus.yml in CI workflow before docker-compose
nmgaston f233389
chore: format files
nmgaston bdd17d5
fix: replace magic number with constant for KVM init cache TTL
nmgaston 1b62eff
fix: only start required services in CI, exclude prometheus/grafana
nmgaston dfddae5
refactor: remove prometheus and grafana from docker-compose
nmgaston 0e166fb
revert: remove unnecessary quotes from AUTH_DISABLED value
nmgaston c7a13bc
Merge branch 'main' into backendCaching
nmgaston 4330058
chore: remove caching debug statements
nmgaston 51de2c5
Merge branch 'backendCaching' of https://github.com/nmgaston/console …
nmgaston aac928d
chore: fix lint issue
nmgaston 21bd4c6
feat: implement backend caching with robfig/go-cache for improved per…
nmgaston 1856a09
Merge branch 'main' into backendCaching
nmgaston 1088fb2
feat: implement backend caching with robfig/go-cache for improved per…
nmgaston 25ae30b
Merge branch 'main' into backendCaching
nmgaston 4a1a1fe
Merge branch 'main' into backendCaching
nmgaston 8030abe
Merge branch 'main' into backendCaching
nmgaston 512d0b8
Merge branch 'main' into backendCaching
nmgaston 9e7832b
Merge branch 'main' into backendCaching
nmgaston d2c57d4
Merge branch 'main' into backendCaching
nmgaston File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| package cache | ||
|
|
||
| import ( | ||
| "sync" | ||
| "time" | ||
| ) | ||
|
|
||
| const ( | ||
| // CleanupInterval is how often expired cache entries are removed. | ||
| CleanupInterval = 30 * time.Second | ||
| // PowerStateTTL is the cache duration for power state (changes frequently). | ||
| PowerStateTTL = 5 * time.Second | ||
| // FeaturesTTL is the cache duration for features (rarely changes). | ||
| FeaturesTTL = 30 * time.Second | ||
| // KVMTTL is the cache duration for KVM display settings (rarely changes). | ||
| KVMTTL = 30 * time.Second | ||
| ) | ||
|
|
||
| // Entry represents a cached value with expiration. | ||
| type Entry struct { | ||
| Value interface{} | ||
| ExpiresAt time.Time | ||
| } | ||
|
|
||
| // Cache is a simple in-memory cache with TTL support. | ||
| type Cache struct { | ||
| mu sync.RWMutex | ||
| items map[string]Entry | ||
| } | ||
|
|
||
| // New creates a new Cache instance. | ||
| func New() *Cache { | ||
| c := &Cache{ | ||
| items: make(map[string]Entry), | ||
| } | ||
| // Start cleanup goroutine | ||
| go c.cleanupExpired() | ||
|
|
||
| return c | ||
| } | ||
|
|
||
| // Set stores a value in the cache with the given TTL. | ||
| func (c *Cache) Set(key string, value interface{}, ttl time.Duration) { | ||
| c.mu.Lock() | ||
| defer c.mu.Unlock() | ||
|
|
||
| c.items[key] = Entry{ | ||
| Value: value, | ||
| ExpiresAt: time.Now().Add(ttl), | ||
| } | ||
| } | ||
|
|
||
| // Get retrieves a value from the cache. | ||
| // Returns the value and true if found and not expired, nil and false otherwise. | ||
| func (c *Cache) Get(key string) (interface{}, bool) { | ||
| c.mu.RLock() | ||
| defer c.mu.RUnlock() | ||
|
|
||
| entry, found := c.items[key] | ||
| if !found { | ||
| return nil, false | ||
| } | ||
|
|
||
| if time.Now().After(entry.ExpiresAt) { | ||
| return nil, false | ||
| } | ||
|
|
||
| return entry.Value, true | ||
| } | ||
|
|
||
| // Delete removes a value from the cache. | ||
| func (c *Cache) Delete(key string) { | ||
| c.mu.Lock() | ||
| defer c.mu.Unlock() | ||
|
|
||
| delete(c.items, key) | ||
| } | ||
|
|
||
| // DeletePattern removes all keys matching a pattern (simple prefix match). | ||
| func (c *Cache) DeletePattern(prefix string) { | ||
| c.mu.Lock() | ||
| defer c.mu.Unlock() | ||
|
|
||
| for key := range c.items { | ||
| if len(key) >= len(prefix) && key[:len(prefix)] == prefix { | ||
| delete(c.items, key) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Clear removes all items from the cache. | ||
| func (c *Cache) Clear() { | ||
| c.mu.Lock() | ||
| defer c.mu.Unlock() | ||
|
|
||
| c.items = make(map[string]Entry) | ||
| } | ||
|
|
||
| // cleanupExpired runs periodically to remove expired entries. | ||
| func (c *Cache) cleanupExpired() { | ||
| ticker := time.NewTicker(CleanupInterval) | ||
| defer ticker.Stop() | ||
|
|
||
| for range ticker.C { | ||
| c.mu.Lock() | ||
|
|
||
| now := time.Now() | ||
|
|
||
| for key, entry := range c.items { | ||
| if now.After(entry.ExpiresAt) { | ||
| delete(c.items, key) | ||
| } | ||
| } | ||
|
|
||
| c.mu.Unlock() | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package cache | ||
|
|
||
| import "fmt" | ||
|
|
||
| // Cache key prefixes. | ||
| const ( | ||
| PrefixFeatures = "features:" | ||
| PrefixPowerState = "power:" | ||
| PrefixKVMDisplay = "kvm:display:" | ||
| PrefixKVMInit = "kvm:init:" | ||
| PrefixGeneral = "general:" | ||
| ) | ||
|
|
||
| // MakeFeaturesKey creates a cache key for device features. | ||
| func MakeFeaturesKey(guid string) string { | ||
| return fmt.Sprintf("%s%s", PrefixFeatures, guid) | ||
| } | ||
|
|
||
| // MakePowerStateKey creates a cache key for power state. | ||
| func MakePowerStateKey(guid string) string { | ||
| return fmt.Sprintf("%s%s", PrefixPowerState, guid) | ||
| } | ||
|
|
||
| // MakeKVMDisplayKey creates a cache key for KVM displays. | ||
| func MakeKVMDisplayKey(guid string) string { | ||
| return fmt.Sprintf("%s%s", PrefixKVMDisplay, guid) | ||
| } | ||
|
|
||
| // MakeGeneralSettingsKey creates a cache key for general settings. | ||
| func MakeGeneralSettingsKey(guid string) string { | ||
| return fmt.Sprintf("%s%s", PrefixGeneral, guid) | ||
| } | ||
|
|
||
| // MakeKVMInitKey creates a cache key for KVM initialization data. | ||
| func MakeKVMInitKey(guid string) string { | ||
| return fmt.Sprintf("%s%s", PrefixKVMInit, guid) | ||
| } | ||
|
|
||
| // InvalidateDeviceCache removes all cached data for a device. | ||
| func InvalidateDeviceCache(c *Cache, guid string) { | ||
| c.Delete(MakeFeaturesKey(guid)) | ||
| c.Delete(MakePowerStateKey(guid)) | ||
| c.Delete(MakeKVMDisplayKey(guid)) | ||
| c.Delete(MakeKVMInitKey(guid)) | ||
| c.Delete(MakeGeneralSettingsKey(guid)) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package v1 | ||
|
|
||
| import ( | ||
| "net/http" | ||
|
|
||
| "github.com/gin-gonic/gin" | ||
| ) | ||
|
|
||
| // getKVMInitData returns all data needed to initialize a KVM session. | ||
| // This combines display settings, power state, redirection status, and features | ||
| // into a single API call to reduce latency. | ||
| func (r *deviceManagementRoutes) getKVMInitData(c *gin.Context) { | ||
| guid := c.Param("guid") | ||
|
|
||
| initData, err := r.d.GetKVMInitData(c.Request.Context(), guid) | ||
| if err != nil { | ||
| r.l.Error(err, "http - v1 - getKVMInitData") | ||
| ErrorResponse(c, err) | ||
|
|
||
| return | ||
| } | ||
|
|
||
| c.JSON(http.StatusOK, initData) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package dto | ||
|
|
||
| // KVMInitResponse combines all data needed to initialize KVM session. | ||
| // This reduces multiple API calls into a single request. | ||
| type KVMInitResponse struct { | ||
| DisplaySettings KVMScreenSettings `json:"displaySettings"` | ||
| PowerState PowerState `json:"powerState"` | ||
| RedirectionStatus KVMRedirectionStatus `json:"redirectionStatus"` | ||
| Features GetFeaturesResponse `json:"features"` | ||
| } | ||
|
|
||
| // KVMRedirectionStatus represents the status of redirection services. | ||
| type KVMRedirectionStatus struct { | ||
| IsSOLConnected bool `json:"isSOLConnected"` | ||
| IsIDERConnected bool `json:"isIDERConnected"` | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.