TDD a CLI Caching Script - Part Six - Utility

2020-02-05

This is part six in a series about writing a general-purpose script to cache CLI output. In this brief post we'll make our script more useful as a utility to other scripts by adding some new options.

If you want to try your hand at implementing these features, checkout 780d577 locally. I'll omit my implementation here but will link to the appropriate diffs.

--check

We can implement --check to allow checking to see if the cache is fresh per the provided --ttl and --stale-while-revalidate options. The best way to communicate this freshness is with exit status, IMHO. This will allow a shell script to use cache --check as a conditional. We'll return 0 (truthy) if the cache is fresh and 1 (falsy) if it is not.

Example usage:

fresh() {
    cache --check --ttl 1 test-cache-key
}

if fresh; then
    echo "FRESH"
else
    echo "NOT FRESH"
fi

Here's the tests for the feature:

@test "--check returns 0 if the content exists and is inside the TTL/SWR" {
  run ./cache $TEST_KEY echo 1
  [ "$status" -eq 0 ]
  [ "$output" = "1" ]

  run ./cache --stale-while-revalidate 1 --ttl 1 --check $TEST_KEY
  [ "$status" -eq 0 ]
  [ "$output" = "" ]
}

@test "--check returns 1 if the content exists but is outside the TTL/SWR" {
  run ./cache $TEST_KEY echo 1
  [ "$status" -eq 0 ]
  [ "$output" = "1" ]

  wait_for_second_to_pass

  run ./cache --stale-while-revalidate 1 --ttl 0 --check $TEST_KEY
  [ "$status" -eq 1 ]
  [ "$output" = "" ]
}

@test "--check returns 1 if the content is not yet cached" {
  run ./cache --check $TEST_KEY
  [ "$status" -eq 1 ]
  [ "$output" = "" ]
}

Between the feature description and the tests, you can probably guess the implementation. You can check out the --check implementation as you wish.

--purge

Every cache needs a good mechanism for clearing the cached content on-demand. Maybe your cache key wasn't specific enough or outside forces have made the content stale before the TTL naturally expires. Whatever your reason, we'll support cache --purge <cache-key> to remove the content currently cached at the provided key.

Here's the tests for --purge:

@test "--purge exits with 0 if the content is not yet cached" {
  [ ! -f "$CACHE_DIR$TEST_KEY" ]

  run ./cache --purge $TEST_KEY
  [ "$status" -eq 0 ]
  [ "$output" = "" ]

  [ ! -f "$CACHE_DIR$TEST_KEY" ]
}

@test "--purge exits with 0 and removes the file if the content is cached" {
  touch "$CACHE_DIR$TEST_KEY"

  [ -f "$CACHE_DIR$TEST_KEY" ]

  run ./cache --purge $TEST_KEY
  [ "$status" -eq 0 ]
  [ "$output" = "" ]

  [ ! -f "$CACHE_DIR$TEST_KEY" ]
}

Try implementing this feature and then check out my implementation afterwards.

Closing

With a few small tweaks we've made our cache script more useful. This will wrap up the series for now, but I'm sure you'll see the cache script appear as a background character in future posts.

My goofy face

Hi, I'm Jeffrey Chupp.
I solve problems, often with code.