Skip to content

Commit

Permalink
Merge pull request #1 from yuseferi/initial-codes
Browse files Browse the repository at this point in the history
initial module with codes and documentation
  • Loading branch information
yuseferi authored Jun 9, 2023
2 parents 6082244 + 76c60af commit 575d4f4
Show file tree
Hide file tree
Showing 13 changed files with 506 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
coverage:
status:
project:
default:
target: 0
threshold: null
base: auto
patch:
default:
target: 0
threshold: null
base: auto
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @yuseferi
13 changes: 13 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

# Configure version updates for both dependencies defined in manifests and vendored dependencies

version: 2
updates:
- package-ecosystem: gomod
directory: /
schedule:
interval: "weekly"
24 changes: 24 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
name: Build
on:
workflow_run:
workflows: [Quality check]
types: [completed]

push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v4
- name: Build
run: go mod download; go build -v ./...
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
name: Quality check
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:
lint:
name: Linter
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Linter
uses: golangci/golangci-lint-action@v3
with:
version: v1.53.2
fail_ci_if_error: true
tests:
name: Tests
needs: lint
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v4
- name: Run tests
run: go mod download; go test -cover -coverprofile=./unit-cover.txt -race ./...
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
files: ./unit-cover.txt
flags: unittests
name: codecov-umbrella
fail_ci_if_error: true
verbose: true
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@

# Go workspace file
go.work
.vs/
.idea/
47 changes: 47 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
run:
deadline: 5m
issues-exit-code: 1
skip-dirs:
- docs
- mocks
- scripts

output:
format: colored-line-number
print-issued-lines: true
print-linter-name: true

linters-settings:
dupl:
threshold: 250
lll:
line-length: 160
goconst:
min-len: 2
min-occurrences: 3
errcheck:
exclude-functions:
- (io.Closer).Close
cyclop:
max-complexity: 10
funlen:
lines: 50

linters:
disable-all: true
enable:
- dupl
- errcheck
- goconst
- gosec
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- funlen
- cyclop
- lll
- forbidigo

39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# gocache (zap with context)
[![codecov](https://codecov.io/github/yuseferi/gocache/branch/codecov-integration/graph/badge.svg?token=64IHXT3ROF)](https://codecov.io/github/yuseferi/gocache)
[![CodeQL](https://github.com/yuseferi/gocache/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/yuseferi/gocache/actions/workflows/github-code-scanning/codeql)
[![Check & Build](https://github.com/yuseferi/gocache/actions/workflows/ci.yml/badge.svg)](https://github.com/yuseferi/gocache/actions/workflows/ci.yml)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/yuseferi/gocache)

gocache provides a data race-free cache implementation in Go.


### Installation

```shell
go get -u github.com/yuseferi/gocache
```

### Usage:



```Go
cache := gocache.NewCache(time.Minute * 2) // with 2 minutes interval cleaning expired items
cache.Set("key", "value", time.Minute) // set cache
value, found := cache.Get("key") // retrive cache data
cache.Delete("key") // delete specific key manually
cache.Clear() // clear all cache items ( purge)
size := cache.Size() // get cache size
```


### Contributing
We strongly believe in open-source ❤️😊. Please feel free to contribute by raising issues and submitting pull requests to make gocache even better!


Released under the [GNU GENERAL PUBLIC LICENSE](LICENSE).




11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/yuseferi/gocache

go 1.20

require github.com/stretchr/testify v1.8.4

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
114 changes: 114 additions & 0 deletions gocache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Package gocache provides a data race-free cache implementation in Go.
//
// Usage:
//
// cache := gocache.NewCache(time.Minute * 2) // with 2 minutes interval cleaning
// cache.Set("key", "value", time.Minute)
// value, found := cache.Get("key")
// cache.Delete("key")
// cache.Clear()
// size := cache.Size()
package gocache

import (
"sync"
"time"
)

// Cache represents a data race-free cache.
type Cache struct {
items map[string]cacheItem
mutex sync.RWMutex
cleanupExpiredPeriod time.Duration
}

type cacheItem struct {
value interface{}
expiration time.Time
}

// NewCache creates a new Cache instance.
func NewCache(cleanupExpiredPeriod time.Duration) *Cache {
cache := &Cache{
items: make(map[string]cacheItem),
}
cache.cleanupExpiredPeriod = cleanupExpiredPeriod
// Start a goroutine to periodically check for expired items and remove them
go cache.deleteExpiredItems()

return cache
}

// Get retrieves the value associated with the specified key from the cache.
// It returns the value and a boolean indicating whether the key was found or not.
// If the key is found but the associated item has expired, the value will be nil
// and the boolean will be false.
func (c *Cache) Get(key string) (interface{}, bool) {
c.mutex.RLock()
defer c.mutex.RUnlock()

item, found := c.items[key]
if !found {
return nil, false
}

if item.expiration.Before(time.Now()) {
return nil, false
}

return item.value, true
}

// Set adds or updates a key-value pair in the cache with the specified expiration duration.
// If the key already exists, its value and expiration are updated.
func (c *Cache) Set(key string, value interface{}, expiration time.Duration) {
c.mutex.Lock()
defer c.mutex.Unlock()

expirationTime := time.Now().Add(expiration)
c.items[key] = cacheItem{
value: value,
expiration: expirationTime,
}
}

// Delete removes the specified key and its associated value from the cache.
// If the key does not exist in the cache, the function does nothing.
func (c *Cache) Delete(key string) {
c.mutex.Lock()
defer c.mutex.Unlock()

delete(c.items, key)
}

// Clear removes all items from the cache, making it empty.
func (c *Cache) Clear() {
c.mutex.Lock()
defer c.mutex.Unlock()

c.items = make(map[string]cacheItem)
}

// Size returns the number of items currently stored in the cache.
func (c *Cache) Size() int {
c.mutex.RLock()
defer c.mutex.RUnlock()

return len(c.items)
}

// deleteExpiredItems is a background goroutine that periodically checks for expired items in the cache
// and removes them. It runs indefinitely after the Cache is created.
func (c *Cache) deleteExpiredItems() {
for {
<-time.After(c.cleanupExpiredPeriod) // Adjust the time interval for checking expired items

c.mutex.Lock()
for key, item := range c.items {
if item.expiration.Before(time.Now()) {
delete(c.items, key)
}
}
c.mutex.Unlock()
}
}
Loading

0 comments on commit 575d4f4

Please sign in to comment.