-
Notifications
You must be signed in to change notification settings - Fork 0
Add SyncMap cache implementation and tests #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| .cursor | ||
| .DS_Store | ||
| .vscode | ||
| .vscode | ||
| .windsurf |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package cachex | ||
|
|
||
| import ( | ||
| "context" | ||
| "sync" | ||
|
|
||
| "github.com/pkg/errors" | ||
| ) | ||
|
|
||
| // SyncMap is a cache implementation using sync.Map | ||
| type SyncMap[T any] struct { | ||
| sync.Map | ||
| } | ||
|
|
||
| var _ Cache[any] = &SyncMap[any]{} | ||
|
|
||
| func NewSyncMap[T any]() *SyncMap[T] { | ||
| return &SyncMap[T]{} | ||
| } | ||
|
|
||
| func (s *SyncMap[T]) Set(_ context.Context, key string, value T) error { | ||
| s.Store(key, value) | ||
| return nil | ||
| } | ||
|
|
||
| func (s *SyncMap[T]) Get(_ context.Context, key string) (T, error) { | ||
| var zero T | ||
| v, ok := s.Load(key) | ||
| if !ok { | ||
| return zero, errors.Wrapf(&ErrKeyNotFound{}, "key not found in syncmap for key: %s", key) | ||
| } | ||
| return v.(T), nil | ||
|
||
| } | ||
|
|
||
| func (s *SyncMap[T]) Del(_ context.Context, key string) error { | ||
| s.Delete(key) | ||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package cachex | ||
|
|
||
| import ( | ||
| "context" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestSyncMapBasics(t *testing.T) { | ||
| ctx := context.Background() | ||
| cache := NewSyncMap[string]() | ||
|
|
||
| require.NoError(t, cache.Set(ctx, "key1", "value1")) | ||
|
|
||
| value, err := cache.Get(ctx, "key1") | ||
| require.NoError(t, err) | ||
| assert.Equal(t, "value1", value) | ||
|
|
||
| require.NoError(t, cache.Del(ctx, "key1")) | ||
|
|
||
| _, err = cache.Get(ctx, "key1") | ||
| assert.True(t, IsErrKeyNotFound(err)) | ||
| } | ||
|
|
||
| func TestSyncMapEmbeddedMethods(t *testing.T) { | ||
| cache := NewSyncMap[int]() | ||
|
|
||
| cache.Store("a", 1) | ||
| cache.Store("b", 2) | ||
|
|
||
| v, ok := cache.Load("a") | ||
| require.True(t, ok) | ||
| assert.Equal(t, 1, v) | ||
|
|
||
| count := 0 | ||
| cache.Range(func(k, v any) bool { | ||
| count++ | ||
| return true | ||
| }) | ||
| assert.Equal(t, 2, count) | ||
| } | ||
|
Comment on lines
+27
to
+43
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Embedding sync.Map exposes its untyped methods (Store, Load, Delete, Range, etc.) which bypass the generic type safety provided by the Cache interface. This creates a confusing API where users can accidentally store values of the wrong type using cache.Store() directly, leading to runtime panics in Get(). Consider using composition instead of embedding (e.g., having a private field 'data sync.Map') to maintain type safety and provide a cleaner API surface.