Skip to content

feat: import the c3e cache library as a standalone module#1

Merged
christiangda merged 1 commit into
mainfrom
feat/import-c3e-library
Jul 11, 2026
Merged

feat: import the c3e cache library as a standalone module#1
christiangda merged 1 commit into
mainfrom
feat/import-c3e-library

Conversation

@christiangda

Copy link
Copy Markdown
Contributor

Imports the dependency-aware caching layer (previously pkg/c3e in svc-qu3ry-core, hardened across PRs #298–#304) into its own module so it can be released as github.com/slashdevops/c3e and consumed externally.

What's in here

Library

  • CacheManager (low-level Valkey ops + dependency graph)
  • SafeCacheManager — stale-while-revalidate, singleflight thundering-herd protection, TTL jitter, bounded query-timeout fallback
  • TypedSafeCacheManager[T] / GetSafe[T] — compile-time type safety
  • Observability: injectable *slog.Logger + metrics/tracing Hooks (OnGet/OnRefresh/OnInvalidate, Result enum)

Module & CI

  • go.mod (go 1.26, valkey-go v1.0.76, x/sync v0.22.0) + go.sum
  • Workflows: pr, release, codeql — the test jobs run a Valkey service container so the cache tests execute for real (-tags=integration)
  • .golangci.yaml, .testcoverage.yml (gate 75% total / 70% package; currently 87.8%), dependabot.yml, FUNDING.yml, release-notes config, SECURITY.md

Docs

  • Split the monolithic README into docs/: architecture, usage, configuration, observability, best-practices, limitations — with Mermaid diagrams
  • Slimmed the README to install + quick start + two diagrams + doc links
  • Corrected inaccuracies: Go 1.26, valkey v1.0.76, Apache-2.0 (was mislabeled MIT), and removed a fabricated benchmark table

Bug fixes surfaced by running against a real Valkey

  • GetWithEncoder built SafeCacheManager as a struct literal, bypassing the constructor → logger was nil (panic on first Warn) and QueryTimeout was 0 (already-expired lookup context, forcing every read onto the fallback path). Now applies the constructor defaults on that path, plus a nil-safe logger accessor as defense-in-depth.
  • ExampleGetWithEncoder wasn't hermetic — it read a JSON-cached key with the Gob decoder (unexpected EOF). It now starts from a clean slate.
  • Shrank the stale-while-revalidate integration case from a 65s wall-clock wait to ~2.5s via a short soft TTL (full suite: 71s → ~9s).

Verification

go build, go vet (both tag sets), golangci-lint (0 issues), go test -race (unit + -tags=integration against Valkey), coverage gate — all green locally.

After merge: tag v1.0.1, then svc-qu3ry-core swaps its pkg/c3e import for the external module (separate PR).

🤖 Generated with Claude Code

Extract the dependency-aware caching layer (previously pkg/c3e in
svc-qu3ry-core) into its own module, github.com/slashdevops/c3e, so it can
be released and consumed as an external dependency.

Contents:
- Source: CacheManager, SafeCacheManager (stale-while-revalidate,
  singleflight, TTL jitter, query-timeout fallback), TypedSafeCacheManager,
  observability hooks, and an injectable slog logger.
- Module: go.mod (go 1.26, valkey-go v1.0.76, x/sync v0.22.0) + go.sum.
- CI/config: pr/release/codeql workflows (with a Valkey service so the cache
  tests run for real), .golangci.yaml, .testcoverage.yml, dependabot, funding,
  release-notes, SECURITY.md.
- Docs: split the monolithic README into docs/ (architecture, usage,
  configuration, observability, best-practices, limitations) with Mermaid
  diagrams; slimmed the README to install + a quick start + two diagrams +
  links. Fixed inaccuracies (Go 1.26, valkey v1.0.76, Apache-2.0, dropped the
  fabricated benchmark table).

Fixes uncovered once the suite runs against a real Valkey:
- GetWithEncoder built SafeCacheManager as a struct literal, bypassing the
  constructor, so logger was nil (panic on the first Warn) and QueryTimeout was
  0 (an already-expired lookup context forcing every read onto the fallback
  path). Apply the constructor defaults on that path and add a nil-safe logger
  accessor.
- Made ExampleGetWithEncoder self-contained (it read a JSON-cached key with the
  Gob decoder) and shrank the stale-while-revalidate integration case from a
  65s wall-clock wait to ~2.5s via a short soft TTL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Comment thread .github/workflows/pr.yaml
Comment on lines +13 to +102
runs-on: ubuntu-latest

services:
valkey:
image: valkey/valkey:latest
ports:
- 6379:6379
options: >-
--health-cmd "valkey-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- name: Checkout
uses: actions/checkout@v7

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: ./go.mod

- name: Summary Information
run: |
echo "# Pull Request Summary" > $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Repository:** ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY
echo "**Pull Request:** ${{ github.event.pull_request.title }}" >> $GITHUB_STEP_SUMMARY
echo "**Author:** ${{ github.event.pull_request.user.login }}" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** ${{ github.event.pull_request.head.ref }}" >> $GITHUB_STEP_SUMMARY
echo "**Base:** ${{ github.event.pull_request.base.ref }}" >> $GITHUB_STEP_SUMMARY
echo "**Commits:** ${{ github.event.pull_request.commits }}" >> $GITHUB_STEP_SUMMARY
echo "**Changed Files:** ${{ github.event.pull_request.changed_files }}" >> $GITHUB_STEP_SUMMARY
echo "**Additions:** ${{ github.event.pull_request.additions }}" >> $GITHUB_STEP_SUMMARY
echo "**Deletions:** ${{ github.event.pull_request.deletions }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

- name: Tools and versions
run: |
echo "## Tools and versions" >> $GITHUB_STEP_SUMMARY

ubuntu_version=$(lsb_release -a 2>&1 | grep "Description" | awk '{print $2, $3, $4}')
echo "Ubuntu version: $ubuntu_version"
echo "**Ubuntu Version:** $ubuntu_version" >> $GITHUB_STEP_SUMMARY

bash_version=$(bash --version | head -n 1 | awk '{print $4}')
echo "Bash version: $bash_version"
echo "**Bash Version:** $bash_version" >> $GITHUB_STEP_SUMMARY

git_version=$(git --version | awk '{print $3}')
echo "Git version: $git_version"
echo "**Git Version:** $git_version" >> $GITHUB_STEP_SUMMARY

go_version=$(go version | awk '{print $3}')
echo "Go version: $go_version"
echo "**Go Version:** $go_version" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

- name: Lint
uses: golangci/golangci-lint-action@v8
with:
version: latest

- name: Lines of code
run: |
echo "## Lines of code" >> $GITHUB_STEP_SUMMARY

go install github.com/boyter/scc/v3@latest
scc --format html-table . | tee -a $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

- name: test
env:
C3E_TEST_VALKEY_ADDR: localhost:6379
run: |
echo "### Test report" >> $GITHUB_STEP_SUMMARY

go test -race -coverprofile=coverage.txt -covermode=atomic -tags=integration ./... | tee -a $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

- name: test coverage
run: |
echo "## Test Coverage" >> $GITHUB_STEP_SUMMARY

go install github.com/vladopajic/go-test-coverage/v2@latest

# execute again to get the summary
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Coverage report" >> $GITHUB_STEP_SUMMARY
go-test-coverage --config=./.testcoverage.yml | sed 's/PASS/PASS ✅/g' | sed 's/FAIL/FAIL ❌/g' | tee -a $GITHUB_STEP_SUMMARY
@christiangda christiangda self-assigned this Jul 11, 2026
@christiangda
christiangda merged commit 213df7c into main Jul 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants