Skip to content

Commit

Permalink
store last access date in cache and delete 30 days
Browse files Browse the repository at this point in the history
By default delete only the cache not accessed within 30 days

Signed-off-by: Yves Brissaud <[email protected]>
  • Loading branch information
eunomie committed Oct 16, 2024
1 parent 09899c9 commit bb6db60
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 18 deletions.
16 changes: 14 additions & 2 deletions docs/reference/docker_runx_cache_prune.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
command: docker runx cache prune
short: Remove all cache entries
long: Remove all cache entries
short: Remove cache entries not accessed recently
long: |
By default remove cache entries not accessed in the last 30 days. Use --all/-a to remove all cache entries.
usage: docker runx cache prune
pname: docker runx cache
plink: docker_runx_cache.yaml
options:
- option: all
shorthand: a
value_type: bool
default_value: "false"
description: Remove all cache entries
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: force
shorthand: f
value_type: bool
Expand Down
8 changes: 4 additions & 4 deletions docs/reference/runx_cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Manage Docker RunX cache and temporary files

### Subcommands

| Name | Description |
|:-------------------------------|:-------------------------|
| [`df`](runx_cache_df.md) | Show disk usage |
| [`prune`](runx_cache_prune.md) | Remove all cache entries |
| Name | Description |
|:-------------------------------|:-------------------------------------------|
| [`df`](runx_cache_df.md) | Show disk usage |
| [`prune`](runx_cache_prune.md) | Remove cache entries not accessed recently |



Expand Down
3 changes: 2 additions & 1 deletion docs/reference/runx_cache_prune.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# docker runx cache prune

<!---MARKER_GEN_START-->
Remove all cache entries
By default remove cache entries not accessed in the last 30 days. Use --all/-a to remove all cache entries.

### Options

| Name | Type | Default | Description |
|:----------------|:-------|:--------|:-------------------------------|
| `-a`, `--all` | `bool` | | Remove all cache entries |
| `-f`, `--force` | `bool` | | Do not prompt for confirmation |


Expand Down
15 changes: 14 additions & 1 deletion internal/commands/cache/df.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/spf13/cobra"

"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter/tabwriter"
"github.com/eunomie/docker-runx/runkit"
)

Expand All @@ -31,9 +32,21 @@ func dfNewCmd(dockerCli command.Cli) *cobra.Command {
str := strings.Builder{}
str.WriteString("Cache directory: " + cacheDir + "\n")
str.WriteString("\n")

w := tabwriter.NewWriter(&str, 0, 0, 1, ' ', 0)
_, _ = fmt.Fprintln(w, "Digest\tSize\tLast Access")
for _, e := range entries {
str.WriteString(fmt.Sprintf("%s: %s\n", e.Digest, humanize.Bytes(uint64(e.Size))))
t := "--"
if e.LastAccess != nil {
t = e.LastAccess.Format("2006-01-02 15:04:05")
}
_, _ = fmt.Fprintf(w,
"%s\t%s\t%s\n",
e.Digest,
humanize.Bytes(uint64(e.Size)),
t)
}
_ = w.Flush()
str.WriteString(fmt.Sprintf("Total: %s\n", humanize.Bytes(uint64(totalSize))))

_, _ = fmt.Fprintln(dockerCli.Out(), str.String())
Expand Down
21 changes: 16 additions & 5 deletions internal/commands/cache/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@ import (
"github.com/spf13/cobra"

"github.com/docker/cli/cli/command"
"github.com/eunomie/docker-runx/internal/sugar"
"github.com/eunomie/docker-runx/runkit"
)

var force bool
var (
force bool
all bool
)

func pruneNewCmd(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "prune",
Short: "Remove all cache entries",
Short: "Remove cache entries not accessed recently",
Long: "By default remove cache entries not accessed in the last 30 days. Use --all/-a to remove all cache entries.",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
var err error
cache := runkit.NewLocalCache(dockerCli)

if !force {
err := huh.NewConfirm().
Title("Are you sure you want to remove all cache entries?").
err = huh.NewConfirm().
Title(sugar.If(all, "Are you sure you want to remove all cache entries?", "Are you sure you want to remove cache entries not accessed in the last 30 days?")).
Value(&force).Run()
if err != nil {
return err
Expand All @@ -34,7 +40,11 @@ func pruneNewCmd(dockerCli command.Cli) *cobra.Command {
return nil
}

err := cache.Erase()
if !all {
err = cache.EraseNotAccessedInLast30Days()
} else {
err = cache.EraseAll()
}
if err != nil {
return err
}
Expand All @@ -46,6 +56,7 @@ func pruneNewCmd(dockerCli command.Cli) *cobra.Command {

flags := cmd.Flags()
flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation")
flags.BoolVarP(&all, "all", "a", false, "Remove all cache entries")

return cmd
}
55 changes: 50 additions & 5 deletions runkit/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"io/fs"
"os"
"path/filepath"
"strings"
"time"

"github.com/docker/cli/cli/command"
"github.com/eunomie/docker-runx/internal/constants"
Expand All @@ -13,6 +15,7 @@ import (
const (
runxConfigFile = "runx.yaml"
runxDocFile = "README.md"
accessFile = "access"
)

var subCacheDir = filepath.Join(constants.SubCommandName, "cache", "sha256")
Expand All @@ -23,8 +26,9 @@ type (
}

CacheEntry struct {
Digest string
Size int64
LastAccess *time.Time
Digest string
Size int64
}
)

Expand Down Expand Up @@ -66,12 +70,21 @@ func (c *LocalCache) Get(digest, src string) (*RunKit, error) {
}

if found {
if err := c.writeAccessFile(digest); err != nil {
return nil, err
}

rk.src = src
return rk, nil
}
return nil, nil
}

func (c *LocalCache) writeAccessFile(digest string) error {
accessDate := time.Now().Format(time.RFC3339)
return os.WriteFile(filepath.Join(c.cacheDir, digest, accessFile), []byte(accessDate), 0o644)
}

func (c *LocalCache) Set(digest string, runxConfig, runxDoc []byte) error {
digestDir := filepath.Join(c.cacheDir, digest)
if err := os.MkdirAll(digestDir, 0o755); err != nil {
Expand All @@ -89,6 +102,9 @@ func (c *LocalCache) Set(digest string, runxConfig, runxDoc []byte) error {
return err
}
}
if err := c.writeAccessFile(digest); err != nil {
return err
}
return nil
}

Expand All @@ -105,9 +121,11 @@ func (c *LocalCache) ListCache() (string, []CacheEntry, int64, error) {
return e
}
totalSize += s
t := c.lastAccess(path)
entries = append(entries, CacheEntry{
Digest: filepath.Base(path),
Size: s,
Digest: filepath.Base(path),
Size: s,
LastAccess: t,
})
return fs.SkipDir
}
Expand All @@ -122,10 +140,37 @@ func (c *LocalCache) ListCache() (string, []CacheEntry, int64, error) {
return c.cacheDir, entries, totalSize, nil
}

func (c *LocalCache) Erase() error {
func (c *LocalCache) EraseAll() error {
return os.RemoveAll(c.cacheDir)
}

func (c *LocalCache) EraseNotAccessedInLast30Days() error {
_, entries, _, err := c.ListCache()
if err != nil {
return err
}
for _, e := range entries {
if e.LastAccess != nil && time.Since(*e.LastAccess) > 30*24*time.Hour {
if err := os.RemoveAll(filepath.Join(c.cacheDir, e.Digest)); err != nil {
return err
}
}
}
return nil
}

func (c *LocalCache) lastAccess(path string) *time.Time {
b, err := os.ReadFile(filepath.Join(path, accessFile))
if err != nil {
return nil
}
if t, err := time.Parse(time.RFC3339, strings.TrimSpace(string(b))); err != nil {
return nil
} else {
return &t
}
}

func dirSize(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(path string, info fs.FileInfo, err error) error {
Expand Down

0 comments on commit bb6db60

Please sign in to comment.