Skip to content

Commit

Permalink
[standard]improve comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
vistart committed May 8, 2024
1 parent 0973d80 commit 02b2e69
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 42 deletions.
22 changes: 22 additions & 0 deletions workflow/standard/cache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,25 @@ The `KeyGetter` interface involved in the above method needs to be implemented:

- `GetKey() string`

`KeyGetter` is suitable for complex key scenarios.
Therefore, you can decide the specific implementation of the `GetKey()` method based on actual needs.

For example, consider a Key structure containing multiple attributes.
If the absence of a cache item can be determined solely based on the first attribute,
there is no need to consider the remaining attributes.

On the other hand, the attributes and their order within the Key structure can also vary.
Therefore, we abstract the KeyGetter interface and Cache interface here,
leaving the implementation details of how to compose keys up to you.

## [item.go](item.go) & [item_option.go](item_option.go)

`item.go` defines the cache item. The cache item interface needs to implement the `Value()` and `Expired()` methods.

`item_option.go` defines the options for declaring cache items. Currently, the options are designed only for expiration time.

## [memory.go](memory.go)

`memory.go` defines the simplest in-memory cache.

This implementation is only used for demonstration and testing purposes of the cache interface and cache item interface.
48 changes: 48 additions & 0 deletions workflow/standard/cache/interface.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
// Copyright (c) 2023 - 2024 vistart. All rights reserved.
// Use of this source code is governed by Apache-2.0 license
// that can be found in the LICENSE file.

// Package cache defines the cache interface and the simplest cache implementation.
package cache

// KeyGetter defines a method to retrieve keys.
type KeyGetter interface {
GetKey() string
}

// Interface defines a generic caching interface for getting, setting, deleting, and clearing caches.
type Interface interface {
// Get retrieves the value of the specified key from the cache.
//
// Parameter
//
// - key: an object implementing the KeyGetter interface to retrieve the key to get.
//
// Returns
//
// - any: the retrieved value, returned as an empty interface.
//
// - error: if an error occurs, it returns the corresponding error message.
Get(key KeyGetter) (any, error)

// Set sets the value of the specified key in the cache.
//
// Parameter
//
// - key: an object implementing the KeyGetter interface to retrieve the key to set.
//
// - value: the value to set, passed as an empty interface.
//
// - options: optional options to set cache items.
//
// Returns
//
// - error: if an error occurs, it returns the corresponding error message.
Set(key KeyGetter, value any, options ...ItemOption) error

// Delete deletes the value of the specified key from the cache.
//
// Parameter
//
// - key: an object implementing the KeyGetter interface to retrieve the key to delete.
//
// Returns
//
// - error: if an error occurs, it returns the corresponding error message.
Delete(key KeyGetter) error

// Clear clears the cache, deleting all cache items.
//
// Returns
//
// - error: if an error occurs, it returns the corresponding error message.
Clear() error
}
1 change: 0 additions & 1 deletion workflow/standard/cache/interface_test.go

This file was deleted.

20 changes: 20 additions & 0 deletions workflow/standard/cache/item.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,49 @@
// Copyright (c) 2023 - 2024 vistart. All rights reserved.
// Use of this source code is governed by Apache-2.0 license
// that can be found in the LICENSE file.

package cache

import "time"

// ItemInterface defines an interface for cache items.
type ItemInterface interface {
// Expired checks if the item has expired.
//
// Returns
//
// - bool: true if the item has expired, otherwise false.
Expired() bool

// Value retrieves the value of the item.
//
// Returns
//
// - any: the value of the item.
Value() any
}

// Item represents a cache item.
type Item struct {
value any
expiredAt *time.Time
ItemInterface
}

// Expired checks if the item has expired.
func (i *Item) Expired() bool {
if i.expiredAt == nil {
return false
}
return i.expiredAt.Before(time.Now())
}

// Value retrieves the value of the item.
func (i *Item) Value() any {
return i.value
}

// NewItem creates and initializes a new cache item with the given value.
func NewItem(value any) *Item {
return &Item{value: value}
}
53 changes: 53 additions & 0 deletions workflow/standard/cache/item_option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2023 - 2024 vistart. All rights reserved.
// Use of this source code is governed by Apache-2.0 license
// that can be found in the LICENSE file.

package cache

import "time"

// ErrInvalidTTL represents an error indicating an invalid Time To Live (TTL) value.
type ErrInvalidTTL struct {
error
}

// Error returns the error message for ErrInvalidTTL.
func (e ErrInvalidTTL) Error() string {
return "invalid TTL in cache"
}

// ErrInvalidExpiration represents an error indicating an invalid expiration time.
type ErrInvalidExpiration struct {
error
}

// Error returns the error message for ErrInvalidExpiration.
func (e ErrInvalidExpiration) Error() string {
return "invalid expiration in cache"
}

// ItemOption represents an option function that can be applied to cache items.
type ItemOption func(*Item) error

// WithTTL creates an ItemOption with a specified duration as the Time To Live (TTL) for the cache item.
func WithTTL(duration time.Duration) ItemOption {
return func(i *Item) error {
if duration <= 0 {
return ErrInvalidTTL{}
}
expiredAt := time.Now().Add(duration)
i.expiredAt = &expiredAt
return nil
}
}

// WithExpiredAt creates an ItemOption with a specified expiration time for the cache item.
func WithExpiredAt(expiredAt time.Time) ItemOption {
return func(i *Item) error {
if expiredAt.Before(time.Now()) {
return ErrInvalidExpiration{}
}
i.expiredAt = &expiredAt
return nil
}
}
4 changes: 4 additions & 0 deletions workflow/standard/cache/item_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (c) 2023 - 2024 vistart. All rights reserved.
// Use of this source code is governed by Apache-2.0 license
// that can be found in the LICENSE file.

package cache

import (
Expand Down
16 changes: 16 additions & 0 deletions workflow/standard/cache/memory.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,51 @@
// Copyright (c) 2023 - 2024 vistart. All rights reserved.
// Use of this source code is governed by Apache-2.0 license
// that can be found in the LICENSE file.

package cache

import (
"fmt"
"sync"
)

// ErrKeyNotFound represents an error indicating that a key was not found in the cache.
type ErrKeyNotFound struct {
key string
error
}

// Error returns the error message for ErrKeyNotFound.
func (e ErrKeyNotFound) Error() string {
return fmt.Sprintf("key %s not found in cache", e.key)
}

// ErrKeyExpired represents an error indicating that a key has expired in the cache.
type ErrKeyExpired struct {
key string
error
}

// Error returns the error message for ErrKeyExpired.
func (e ErrKeyExpired) Error() string {
return fmt.Sprintf("key %s has expired", e.key)
}

// MemoryCache represents an in-memory cache implementation.
type MemoryCache struct {
mu sync.RWMutex
items map[string]*Item
}

// NewMemoryCache creates and initializes a new MemoryCache instance.
func NewMemoryCache() *MemoryCache {
return &MemoryCache{
items: make(map[string]*Item),
}
}

// Get retrieves the value associated with the given key from the cache.
// If the key is not found or has expired, it returns an error.
func (c *MemoryCache) Get(key KeyGetter) (any, error) {
c.mu.RLock()
defer c.mu.RUnlock()
Expand All @@ -50,6 +62,8 @@ func (c *MemoryCache) Get(key KeyGetter) (any, error) {
return nil, ErrKeyExpired{key: keyGetter.GetKey()}
}

// Set sets the value associated with the given key in the cache.
// It accepts optional ItemOption functions to customize the cache item.
func (c *MemoryCache) Set(key KeyGetter, value any, options ...ItemOption) error {
c.mu.Lock()
defer c.mu.Unlock()
Expand All @@ -68,13 +82,15 @@ func (c *MemoryCache) Set(key KeyGetter, value any, options ...ItemOption) error
return nil
}

// Delete removes the value associated with the given key from the cache.
func (c *MemoryCache) Delete(key KeyGetter) error {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.items, key.GetKey())
return nil
}

// Clear removes all items from the cache.
func (c *MemoryCache) Clear() error {
c.mu.Lock()
defer c.mu.Unlock()
Expand Down
4 changes: 4 additions & 0 deletions workflow/standard/cache/memory_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (c) 2023 - 2024 vistart. All rights reserved.
// Use of this source code is governed by Apache-2.0 license
// that can be found in the LICENSE file.

package cache

import (
Expand Down
40 changes: 0 additions & 40 deletions workflow/standard/cache/option.go

This file was deleted.

1 change: 0 additions & 1 deletion workflow/standard/cache/option_test.go

This file was deleted.

0 comments on commit 02b2e69

Please sign in to comment.