Skip to content

Commit 6828005

Browse files
authored
Improve the documentation for the public API (#17)
1 parent ce5fb56 commit 6828005

9 files changed

+280
-91
lines changed

.golangci.yml

+10-44
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,16 @@ linters:
3636
- asciicheck # checks that your code does not contain non-ASCII identifiers
3737
- bidichk # checks for dangerous unicode character sequences
3838
- bodyclose # checks whether HTTP response body is closed successfully
39-
# - cyclop # checks function and package cyclomatic complexity
39+
- cyclop # checks function and package cyclomatic complexity
4040
- dupl # tool for code clone detection
4141
- durationcheck # checks for two durations multiplied together
4242
- errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error
4343
- errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13
44-
- execinquery # checks query string in Query function which reads your Go src files and warning it finds
4544
- exhaustive # checks exhaustiveness of enum switch statements
4645
- exportloopref # checks for pointers to enclosing loop variables
4746
- forbidigo # forbids identifiers
4847
- funlen # tool for detection of long functions
4948
- gocheckcompilerdirectives # validates go compiler directive comments (//go:)
50-
# - gochecknoglobals # checks that no global variables exist
5149
- gochecknoinits # checks that no init functions are present in Go code
5250
- gochecksumtype # checks exhaustiveness on Go "sum types"
5351
- gocognit # computes and checks the cognitive complexity of functions
@@ -98,36 +96,28 @@ linters:
9896
- decorder # checks declaration order and count of types, constants, variables and functions
9997
- dogsled # checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
10098
- paralleltest # detects missing usage of t.Parallel() method in your Go test
99+
- tagalign # checks that struct tags are well aligned
101100

102-
## you may want to enable
101+
## may want to enable
102+
# - wrapcheck # checks that errors returned from external packages are wrapped
103103
#- gci # controls golang package import order and makes it always deterministic
104104
#- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega
105105
#- godox # detects FIXME, TODO and other comment keywords
106106
#- goheader # checks is file header matches to pattern
107107
#- inamedparam # [great idea, but too strict, need to ignore a lot of cases by default] reports interfaces with unnamed method parameters
108108
#- interfacebloat # checks the number of methods inside an interface
109-
#- ireturn # accept interfaces, return concrete types
110-
#- tagalign # checks that struct tags are well aligned
111-
#- varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope
112-
#- wrapcheck # checks that errors returned from external packages are wrapped
113-
#- zerologlint # detects the wrong usage of zerolog that a user forgets to dispatch zerolog.Event
109+
# - ireturn # accept interfaces, return concrete types
110+
# - varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope
114111
# - nlreturn # checks for a new line before return and branch statements to increase code clarity
115112

116113
## disabled
117114
# - lll # reports long lines
118-
# - exhaustruct # [highly recommend to enable] checks if all structure fields are initialized
119-
#- depguard # [replaced by gomodguard] checks if package imports are in a list of acceptable packages
120-
#- dupword # [useless without config] checks for duplicate words in the source code
121-
#- errchkjson # [don't see profit + I'm against of omitting errors like in the first example https://github.com/breml/errchkjson] checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted
122-
#- forcetypeassert # [replaced by errcheck] finds forced type assertions
115+
# - exhaustruct # checks if all structure fields are initialized
123116
#- goerr113 # [too strict] checks the errors handling expressions
124-
#- gofmt # [replaced by goimports] checks whether code was gofmt-ed
125-
#- gofumpt # [replaced by goimports, gofumports is not available yet] checks whether code was gofumpt-ed
126117
#- gosmopolitan # reports certain i18n/l10n anti-patterns in your Go codebase
127118
#- grouper # analyzes expression groups
128119
#- importas # enforces consistent import aliases
129120
#- maintidx # measures the maintainability index of each function
130-
#- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines
131121
#- tagliatelle # checks the struct tags
132122
#- contextcheck # Check whether the function uses a non-inherited context.
133123

@@ -163,33 +153,9 @@ linters-settings:
163153
nlreturn:
164154
block-size: 8
165155

166-
exhaustruct:
167-
# Default: []
168-
exclude:
169-
- ".*_test.go$"
170-
# std libs
171-
- "^net/http.Client$"
172-
- "^net/http.Cookie$"
173-
- "^net/http.Request$"
174-
- "^net/http.Response$"
175-
- "^net/http.Server$"
176-
- "^net/http.Transport$"
177-
- "^net/url.URL$"
178-
- "^os/exec.Cmd$"
179-
- "^reflect.StructField$"
180-
# public libs
181-
- "^github.com/Shopify/sarama.Config$"
182-
- "^github.com/Shopify/sarama.ProducerMessage$"
183-
- "^github.com/mitchellh/mapstructure.DecoderConfig$"
184-
- "^github.com/prometheus/client_golang/.+Opts$"
185-
- "^github.com/spf13/cobra.Command$"
186-
- "^github.com/spf13/cobra.CompletionOptions$"
187-
- "^github.com/stretchr/testify/mock.Mock$"
188-
- "^github.com/testcontainers/testcontainers-go.+Request$"
189-
- "^github.com/testcontainers/testcontainers-go.FromDockerfile$"
190-
- "^golang.org/x/tools/go/analysis.Analyzer$"
191-
- "^google.golang.org/protobuf/.+Options$"
192-
- "^gopkg.in/yaml.v3.Node$"
156+
gosec:
157+
excludes:
158+
- G404 # Ignore insecure random number source.
193159

194160
funlen:
195161
# Checks the number of lines in a function.

cache.go

+74-7
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ func (c *Client[T]) getWithState(key string) (value T, exists, markedAsMissing,
135135
}
136136

137137
// Get retrieves a single value from the cache.
138+
//
139+
// Parameters:
140+
//
141+
// key - The key to be retrieved.
142+
//
143+
// Returns:
144+
//
145+
// The value corresponding to the key and a boolean indicating if the value was found.
138146
func (c *Client[T]) Get(key string) (T, bool) {
139147
shard := c.getShard(key)
140148
val, ok, markedAsMissing, refresh := shard.get(key)
@@ -143,6 +151,14 @@ func (c *Client[T]) Get(key string) (T, bool) {
143151
}
144152

145153
// GetMany retrieves multiple values from the cache.
154+
//
155+
// Parameters:
156+
//
157+
// keys - The list of keys to be retrieved.
158+
//
159+
// Returns:
160+
//
161+
// A map of keys to their corresponding values.
146162
func (c *Client[T]) GetMany(keys []string) map[string]T {
147163
records := make(map[string]T, len(keys))
148164
for _, key := range keys {
@@ -155,9 +171,18 @@ func (c *Client[T]) GetMany(keys []string) map[string]T {
155171

156172
// GetManyKeyFn follows the same API as GetOrFetchBatch and PassthroughBatch.
157173
// You provide it with a slice of IDs and a keyFn, which is applied to create
158-
// the cache key. The returned map uses the IDs as keys instead of the cache key.
159-
// If you've used ScanKeys to retrieve the actual keys, you can retrieve the records
160-
// using GetMany instead.
174+
// the cache key. The returned map uses the IDs as keys instead of the cache
175+
// key. If you've used ScanKeys to retrieve the actual keys, you can retrieve
176+
// the records using GetMany instead.
177+
//
178+
// Parameters:
179+
//
180+
// ids - The list of IDs to be retrieved.
181+
// keyFn - A function that generates the cache key for each ID.
182+
//
183+
// Returns:
184+
//
185+
// A map of IDs to their corresponding values.
161186
func (c *Client[T]) GetManyKeyFn(ids []string, keyFn KeyFn) map[string]T {
162187
records := make(map[string]T, len(ids))
163188
for _, id := range ids {
@@ -168,7 +193,16 @@ func (c *Client[T]) GetManyKeyFn(ids []string, keyFn KeyFn) map[string]T {
168193
return records
169194
}
170195

171-
// Set writes a single value to the cache. Returns true if it triggered an eviction.
196+
// Set writes a single value to the cache.
197+
//
198+
// Parameters:
199+
//
200+
// key - The key to be set.
201+
// value - The value to be associated with the key.
202+
//
203+
// Returns:
204+
//
205+
// A boolean indicating if the set operation triggered an eviction.
172206
func (c *Client[T]) Set(key string, value T) bool {
173207
shard := c.getShard(key)
174208
return shard.set(key, value, false)
@@ -181,7 +215,15 @@ func (c *Client[T]) StoreMissingRecord(key string) bool {
181215
return shard.set(key, zero, true)
182216
}
183217

184-
// SetMany writes a map of key value pairs to the cache.
218+
// SetMany writes a map of key-value pairs to the cache.
219+
//
220+
// Parameters:
221+
//
222+
// records - A map of keys to values to be set in the cache.
223+
//
224+
// Returns:
225+
//
226+
// A boolean indicating if any of the set operations triggered an eviction.
185227
func (c *Client[T]) SetMany(records map[string]T) bool {
186228
var triggeredEviction bool
187229
for key, value := range records {
@@ -193,9 +235,18 @@ func (c *Client[T]) SetMany(records map[string]T) bool {
193235
return triggeredEviction
194236
}
195237

196-
// SetManyKeyFn follows the same API as GetOrFetchBatch and PassThroughBatch. It
197-
// takes a map of records where the keyFn is applied to each key in the map
238+
// SetManyKeyFn follows the same API as GetOrFetchBatch and PassthroughBatch.
239+
// It takes a map of records where the keyFn is applied to each key in the map
198240
// before it's stored in the cache.
241+
//
242+
// Parameters:
243+
//
244+
// records - A map of IDs to values to be set in the cache.
245+
// cacheKeyFn - A function that generates the cache key for each ID.
246+
//
247+
// Returns:
248+
//
249+
// A boolean indicating if any of the set operations triggered an eviction.
199250
func (c *Client[T]) SetManyKeyFn(records map[string]T, cacheKeyFn KeyFn) bool {
200251
var triggeredEviction bool
201252
for id, value := range records {
@@ -208,6 +259,10 @@ func (c *Client[T]) SetManyKeyFn(records map[string]T, cacheKeyFn KeyFn) bool {
208259
}
209260

210261
// ScanKeys returns a list of all keys in the cache.
262+
//
263+
// Returns:
264+
//
265+
// A slice of strings representing all the keys in the cache.
211266
func (c *Client[T]) ScanKeys() []string {
212267
keys := make([]string, 0, c.Size())
213268
for _, shard := range c.shards {
@@ -217,6 +272,10 @@ func (c *Client[T]) ScanKeys() []string {
217272
}
218273

219274
// Size returns the number of entries in the cache.
275+
//
276+
// Returns:
277+
//
278+
// An integer representing the total number of entries in the cache.
220279
func (c *Client[T]) Size() int {
221280
var sum int
222281
for _, shard := range c.shards {
@@ -226,12 +285,20 @@ func (c *Client[T]) Size() int {
226285
}
227286

228287
// Delete removes a single entry from the cache.
288+
//
289+
// Parameters:
290+
//
291+
// key: The key of the entry to be removed.
229292
func (c *Client[T]) Delete(key string) {
230293
shard := c.getShard(key)
231294
shard.delete(key)
232295
}
233296

234297
// NumKeysInflight returns the number of keys that are currently being fetched.
298+
//
299+
// Returns:
300+
//
301+
// An integer representing the total number of keys that are currently being fetched.
235302
func (c *Client[T]) NumKeysInflight() int {
236303
c.inFlightMutex.Lock()
237304
defer c.inFlightMutex.Unlock()

distribution.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func distributedBatchFetch[V, T any](c *Client[T], keyFn KeyFn, fetchFn BatchFet
159159
}
160160

161161
return func(ctx context.Context, ids []string) (map[string]V, error) {
162-
// We need to be able to lookup the ID of the record based on the key.
162+
// We need to be able to look up the ID of the record based on the key.
163163
keyIDMap := make(map[string]string, len(ids))
164164
keys := make([]string, 0, len(ids))
165165
for _, id := range ids {
@@ -193,7 +193,7 @@ func distributedBatchFetch[V, T any](c *Client[T], keyFn KeyFn, fetchFn BatchFet
193193

194194
// If distributedStaleStorage isn't enabled it means all records are fresh, otherwise checked the CreatedAt time.
195195
if !c.distributedEarlyRefreshes || c.clock.Since(record.CreatedAt) < c.distributedRefreshAfterDuration {
196-
// We never wan't to return missing records.
196+
// We never want to return missing records.
197197
if !record.IsMissingRecord {
198198
fresh[id] = record.Value
199199
} else {
@@ -205,7 +205,7 @@ func distributedBatchFetch[V, T any](c *Client[T], keyFn KeyFn, fetchFn BatchFet
205205
idsToRefresh = append(idsToRefresh, id)
206206
c.reportDistributedRefresh()
207207

208-
// We never wan't to return missing records.
208+
// We never want to return missing records.
209209
if !record.IsMissingRecord {
210210
stale[id] = record.Value
211211
} else {
@@ -218,7 +218,7 @@ func distributedBatchFetch[V, T any](c *Client[T], keyFn KeyFn, fetchFn BatchFet
218218
}
219219

220220
dataSourceResponses, err := fetchFn(ctx, idsToRefresh)
221-
// Incase of an error, we'll proceed with the ones we got from the distributed storage.
221+
// In case of an error, we'll proceed with the ones we got from the distributed storage.
222222
if err != nil {
223223
for i := 0; i < len(stale); i++ {
224224
c.reportDistributedStaleFallback()

fetch.go

+64-9
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,40 @@ func getFetch[V, T any](ctx context.Context, c *Client[T], key string, fetchFn F
5757
}
5858

5959
// GetOrFetch attempts to retrieve the specified key from the cache. If the value
60-
// is absent, it invokes the "fetchFn" function to obtain it and then stores
61-
// the result. Additionally, when background refreshes is enabled, GetOrFetch
62-
// determines if the record needs refreshing and, if necessary, schedules this
63-
// task for background execution.
60+
// is absent, it invokes the fetchFn function to obtain it and then stores the result.
61+
// Additionally, when background refreshes are enabled, GetOrFetch determines if the record
62+
// needs refreshing and, if necessary, schedules this task for background execution.
63+
//
64+
// Parameters:
65+
//
66+
// ctx - The context to be used for the request.
67+
// key - The key to be fetched.
68+
// fetchFn - Used to retrieve the data from the underlying data source if the key is not found in the cache.
69+
//
70+
// Returns:
71+
//
72+
// The value corresponding to the key and an error if one occurred.
6473
func (c *Client[T]) GetOrFetch(ctx context.Context, key string, fetchFn FetchFn[T]) (T, error) {
6574
return getFetch[T, T](ctx, c, key, fetchFn)
6675
}
6776

6877
// GetOrFetch is a convenience function that performs type assertion on the result of client.GetOrFetch.
78+
//
79+
// Parameters:
80+
//
81+
// ctx - The context to be used for the request.
82+
// c - The cache client.
83+
// key - The key to be fetched.
84+
// fetchFn - Used to retrieve the data from the underlying data source if the key is not found in the cache.
85+
//
86+
// Returns:
87+
//
88+
// The value corresponding to the key and an error if one occurred.
89+
//
90+
// Type Parameters:
91+
//
92+
// V - The type returned by the fetchFn. Must be assignable to T.
93+
// T - The type stored in the cache.
6994
func GetOrFetch[V, T any](ctx context.Context, c *Client[T], key string, fetchFn FetchFn[V]) (V, error) {
7095
res, err := getFetch[V, T](ctx, c, key, fetchFn)
7196
return unwrap[V](res, err)
@@ -104,16 +129,46 @@ func getFetchBatch[V, T any](ctx context.Context, c *Client[T], ids []string, ke
104129
return cachedRecords, nil
105130
}
106131

107-
// GetOrFetchBatch attempts to retrieve the specified ids from the cache. If any
108-
// of the values are absent, it invokes the fetchFn function to obtain them and
109-
// then stores the result. Additionally, when background refreshes is enabled,
110-
// GetOrFetch determines if any of the records needs refreshing and, if
132+
// GetOrFetchBatch attempts to retrieve the specified ids from the cache. If
133+
// any of the values are absent, it invokes the fetchFn function to obtain them
134+
// and then stores the result. Additionally, when background refreshes are
135+
// enabled, GetOrFetch determines if any of the records need refreshing and, if
111136
// necessary, schedules this to be performed in the background.
137+
//
138+
// Parameters:
139+
//
140+
// ctx - The context to be used for the request.
141+
// ids - The list of IDs to be fetched.
142+
// keyFn - Used to generate the cache key for each ID.
143+
// fetchFn - Used to retrieve the data from the underlying data source if any IDs are not found in the cache.
144+
//
145+
// Returns:
146+
//
147+
// A map of IDs to their corresponding values and an error if one occurred.
112148
func (c *Client[T]) GetOrFetchBatch(ctx context.Context, ids []string, keyFn KeyFn, fetchFn BatchFetchFn[T]) (map[string]T, error) {
113149
return getFetchBatch[T, T](ctx, c, ids, keyFn, fetchFn)
114150
}
115151

116-
// GetOrFetchBatch is a convenience function that performs type assertion on the result of client.GetOrFetchBatch.
152+
// GetOrFetchBatch is a convenience function that performs type assertion on the
153+
// result of client.GetOrFetchBatch.
154+
//
155+
// Parameters:
156+
//
157+
// ctx - The context to be used for the request.
158+
// c - The cache client.
159+
// ids - The list of IDs to be fetched.
160+
// keyFn - Used to prefix each ID in order to create a unique cache key.
161+
// fetchFn - Used to retrieve the data from the underlying data source.
162+
//
163+
// Returns:
164+
//
165+
// A map of ids to their corresponding values and an error if one occurred.
166+
//
167+
// Type Parameters:
168+
//
169+
// V - The type returned by the fetchFn. Must be assignable to T.
170+
// T - The type stored in the cache.
171+
117172
func GetOrFetchBatch[V, T any](ctx context.Context, c *Client[T], ids []string, keyFn KeyFn, fetchFn BatchFetchFn[V]) (map[string]V, error) {
118173
res, err := getFetchBatch[V, T](ctx, c, ids, keyFn, fetchFn)
119174
return unwrapBatch[V](res, err)

0 commit comments

Comments
 (0)