feat: enhance host resolution, filtering, and cache management
Release / release (push) Successful in 49s
Release / release (push) Successful in 49s
- **Strategies**: Add resolver strategy input validation and parsing in setup wizard. Support comma-separated input with known strategy mapping. - **Client**: Extend Search and SearchAll to include kind and tag filters. Add pagination for full cache refresh handling large datasets. - **Cache**: Introduce `RecentlyUsed` and `MarkUsed`. Persist `LastUsed` timestamps for entries. - **TUI**: Add recent hosts view, tag/kind filters, and inline editor for user/port override. - **Tests**: Comprehensive unit tests for new features, including strategy validation, cache behavior, and client filtering. - **Docs**: Update README with new TUI features and cache subcommands.
This commit is contained in:
Vendored
+35
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -15,6 +16,7 @@ type Entry struct {
|
||||
Kind string `json:"kind"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
CachedAt time.Time `json:"cached_at"`
|
||||
LastUsed time.Time `json:"last_used,omitempty"`
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
@@ -86,6 +88,39 @@ func (c *Cache) Upsert(e Entry) {
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// MarkUsed records the current time as LastUsed for the named entry.
|
||||
// It is a no-op if the entry does not exist.
|
||||
func (c *Cache) MarkUsed(name string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if e, ok := c.entries[name]; ok {
|
||||
e.LastUsed = time.Now()
|
||||
c.entries[name] = e
|
||||
}
|
||||
}
|
||||
|
||||
// RecentlyUsed returns the n most recently used entries, sorted by LastUsed desc.
|
||||
// Entries that have never been used (LastUsed zero) are excluded.
|
||||
// If n <= 0, all used entries are returned.
|
||||
func (c *Cache) RecentlyUsed(n int) []Entry {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
var used []Entry
|
||||
for _, e := range c.entries {
|
||||
if !e.LastUsed.IsZero() {
|
||||
used = append(used, e)
|
||||
}
|
||||
}
|
||||
sort.Slice(used, func(i, j int) bool {
|
||||
return used[i].LastUsed.After(used[j].LastUsed)
|
||||
})
|
||||
if n > 0 && len(used) > n {
|
||||
used = used[:n]
|
||||
}
|
||||
return used
|
||||
}
|
||||
|
||||
// Search returns all entries whose name starts with prefix (case-insensitive).
|
||||
// TTL is intentionally ignored — this is used for shell completion.
|
||||
func (c *Cache) Search(prefix string) []Entry {
|
||||
|
||||
Reference in New Issue
Block a user