Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/smoke-otel-backends.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ err := cli.RunHealth(cli.HealthConfig{
- `github.com/github/gh-aw/pkg/gitutil` — Git and GitHub CLI helpers
- `github.com/github/gh-aw/pkg/repoutil` — repository name parsing and normalization
- `github.com/github/gh-aw/pkg/stringutil` — string manipulation and sanitization utilities
- `github.com/github/gh-aw/pkg/syncutil` — thread-safe one-shot caching (used for repository slug lookup)

**External**:
- `github.com/spf13/cobra` — CLI framework
Expand Down
65 changes: 65 additions & 0 deletions pkg/syncutil/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# syncutil Package

The `syncutil` package provides thread-safe synchronization utilities for concurrent operations.

## Overview

This package provides generic types for common concurrency patterns with zero-allocation caching. It is designed for situations where an expensive or fallible operation should be executed at most once, with subsequent callers receiving the cached result.

## Public API

### Types

| Symbol | Kind | Description |
|--------|------|-------------|
| `OnceLoader[T]` | struct | Caches the result of an expensive, fallible one-shot fetch; safe for concurrent use |

### Methods on `OnceLoader[T]`

| Method | Signature | Description |
|--------|-----------|-------------|
| `Get` | `func (o *OnceLoader[T]) Get(loader func() (T, error)) (T, error)` | Returns the cached result, invoking `loader` exactly once |
| `Reset` | `func (o *OnceLoader[T]) Reset()` | Clears the cached result and error so that the next `Get` call re-invokes `loader` |

## Usage Examples

```go
import "github.com/github/gh-aw/pkg/syncutil"

var cache syncutil.OnceLoader[string]

// loader is called only once; subsequent calls return the cached value
value, err := cache.Get(func() (string, error) {
return expensiveOperation()
})

// Reset allows re-fetching the value on the next Get call
cache.Reset()
```

**Typical usage as a package-level cache**:

```go
var currentRepoSlugCache syncutil.OnceLoader[string]

func getCurrentRepoSlug() (string, error) {
return currentRepoSlugCache.Get(func() (string, error) {
return fetchRepoSlugFromGitHub()
})
}
```

## Design Notes

- The internal mutex ensures that `loader` is invoked at most once, even when multiple goroutines call `Get` concurrently.
- If `loader` returns an error, the error is cached alongside the zero value of `T`; subsequent calls return the same error without re-invoking `loader`.
- `Reset` acquires the same mutex, making it safe to call concurrently with `Get`.
- The zero value of `OnceLoader[T]` is ready to use; no constructor is needed.

## Dependencies

This package has no internal or external dependencies beyond the Go standard library (`sync`).

---

*This specification is automatically maintained by the [spec-extractor](../../.github/workflows/spec-extractor.md) workflow.*
1 change: 1 addition & 0 deletions pkg/workflow/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ pkg/workflow ── FrontmatterConfig (typed structs)
- `github.com/github/gh-aw/pkg/typeutil` — safe type conversions
- `github.com/github/gh-aw/pkg/tty` — terminal capability detection
- `github.com/github/gh-aw/pkg/stringutil`, `github.com/github/gh-aw/pkg/fileutil`, `github.com/github/gh-aw/pkg/gitutil`, `github.com/github/gh-aw/pkg/sliceutil` — utilities
- `github.com/github/gh-aw/pkg/syncutil` — thread-safe one-shot caching (used for repository feature cache)
- `github.com/github/gh-aw/pkg/types` — shared MCP types

**External**:
Expand Down