go-cache/docs/development.md

189 lines
4.2 KiB
Markdown
Raw Permalink Normal View History

---
title: Development
description: Building, testing, and contributing to go-cache.
---
# Development
This guide covers how to build, test, and contribute to `go-cache`.
## Prerequisites
- **Go 1.26** or later
- Access to `forge.lthn.ai` modules (`GOPRIVATE=forge.lthn.ai/*`)
- The `core` CLI (optional, for `core go test` and `core go qa`)
## Getting the Source
```bash
git clone ssh://git@forge.lthn.ai:2223/core/go-cache.git
cd go-cache
```
If you are working within the Go workspace at `~/Code/go.work`, the module is
already available locally and dependency resolution will use workspace overrides.
## Running Tests
With the `core` CLI:
```bash
core go test
```
With plain Go:
```bash
go test ./...
```
To run a single test:
```bash
core go test --run TestCache
# or
go test -run TestCache ./...
```
The test suite uses `io.NewMockMedium()` for all storage operations, so no
files are written to disc and tests run quickly in any environment.
## Test Coverage
```bash
core go cov # Generate coverage report
core go cov --open # Generate and open in browser
```
## Code Quality
The full QA pipeline runs formatting, vetting, linting, and tests in one
command:
```bash
core go qa # fmt + vet + lint + test
core go qa full # adds race detector, vulnerability scan, security audit
```
Individual steps:
```bash
core go fmt # Format with gofmt
core go vet # Static analysis
core go lint # Linter checks
```
## Project Structure
```
go-cache/
.core/
build.yaml # Build configuration (targets, flags)
release.yaml # Release configuration (changelog rules)
cache.go # Package source
cache_test.go # Tests
go.mod # Module definition
go.sum # Dependency checksums
docs/ # This documentation
```
The package is intentionally small -- a single source file and a single test
file. There are no sub-packages.
## Writing Tests
Tests follow the standard Go testing conventions. The codebase uses
`testing.T` directly (not testify assertions) for simplicity. When adding tests:
1. Use `io.NewMockMedium()` rather than the real filesystem.
2. Keep TTLs short (milliseconds) when testing expiry behaviour.
3. Name test functions descriptively: `TestCacheExpiry`, `TestCacheDefaults`, etc.
Example of testing cache expiry:
```go
func TestCacheExpiry(t *testing.T) {
m := io.NewMockMedium()
c, err := cache.New(m, "/tmp/test", 10*time.Millisecond)
if err != nil {
t.Fatalf("failed to create cache: %v", err)
}
c.Set("key", "value")
time.Sleep(50 * time.Millisecond)
var result string
found, _ := c.Get("key", &result)
if found {
t.Error("expected expired entry to be a cache miss")
}
}
```
## Commit Conventions
This project uses conventional commits:
```
feat(cache): add batch eviction support
fix(cache): handle corrupted JSON gracefully
refactor: simplify Path() traversal check
```
The release configuration (`.core/release.yaml`) includes `feat`, `fix`,
`perf`, and `refactor` in changelogs, and excludes `chore`, `docs`, `style`,
`test`, and `ci`.
## Build Configuration
The `.core/build.yaml` defines cross-compilation targets:
| OS | Architecture |
|---------|-------------|
| Linux | amd64 |
| Linux | arm64 |
| Darwin | arm64 |
| Windows | amd64 |
Since `go-cache` is a library (no `main` package), the build configuration is
primarily used by the CI pipeline for compilation checks rather than producing
binaries.
## Adding a New Storage Backend
To use the cache with a different storage medium, implement the `io.Medium`
interface from `go-io` and pass it to `cache.New()`. The cache only requires
five methods: `EnsureDir`, `Read`, `Write`, `Delete`, and `DeleteAll`. See
the [architecture](architecture.md) document for the full method mapping.
```go
import (
"forge.lthn.ai/core/go-cache"
"forge.lthn.ai/core/go-io/store"
"time"
)
// Use SQLite as the cache backend
medium, err := store.NewMedium("/path/to/cache.db")
if err != nil {
panic(err)
}
c, err := cache.New(medium, "cache", 30*time.Minute)
```
## Licence
EUPL-1.2. See the repository root for the full licence text.