Files
ezbookkeeping/pkg/duplicatechecker/in_memory_duplicate_checker.go
2025-10-21 01:52:28 +08:00

113 lines
4.0 KiB
Go

package duplicatechecker
import (
"fmt"
"sync"
"time"
"github.com/patrickmn/go-cache"
"github.com/mayswind/ezbookkeeping/pkg/settings"
)
// InMemoryDuplicateChecker represents in-memory duplicate checker
type InMemoryDuplicateChecker struct {
cache *cache.Cache
mutex sync.Mutex
}
// NewInMemoryDuplicateChecker returns a new in-memory duplicate checker
func NewInMemoryDuplicateChecker(config *settings.Config) (*InMemoryDuplicateChecker, error) {
checker := &InMemoryDuplicateChecker{
cache: cache.New(config.DuplicateSubmissionsIntervalDuration, config.InMemoryDuplicateCheckerCleanupIntervalDuration),
}
return checker, nil
}
// GetSubmissionRemark returns whether the same submission has been processed and related remark
func (c *InMemoryDuplicateChecker) GetSubmissionRemark(checkerType DuplicateCheckerType, uid int64, identification string) (bool, string) {
existedRemark, found := c.cache.Get(c.getCacheKey(checkerType, uid, identification))
if found {
return true, existedRemark.(string)
}
return false, ""
}
// SetSubmissionRemark saves the identification and remark to in-memory cache
func (c *InMemoryDuplicateChecker) SetSubmissionRemark(checkerType DuplicateCheckerType, uid int64, identification string, remark string) {
c.cache.Set(c.getCacheKey(checkerType, uid, identification), remark, cache.DefaultExpiration)
}
// SetSubmissionRemarkWithCustomExpiration saves the identification and remark to in-memory cache with custom expiration time
func (c *InMemoryDuplicateChecker) SetSubmissionRemarkWithCustomExpiration(checkerType DuplicateCheckerType, uid int64, identification string, remark string, expiration time.Duration) {
c.cache.Set(c.getCacheKey(checkerType, uid, identification), remark, expiration)
}
// RemoveSubmissionRemark removes the identification and remark in in-memory cache
func (c *InMemoryDuplicateChecker) RemoveSubmissionRemark(checkerType DuplicateCheckerType, uid int64, identification string) {
c.cache.Delete(c.getCacheKey(checkerType, uid, identification))
}
// GetOrSetCronJobRunningInfo returns the running info when the cron job is running or saves the running info by the current duplicate checker
func (c *InMemoryDuplicateChecker) GetOrSetCronJobRunningInfo(jobName string, runningInfo string, runningInterval time.Duration) (bool, string) {
c.mutex.Lock()
defer c.mutex.Unlock()
existedRunningInfo, found := c.cache.Get(c.getCacheKey(DUPLICATE_CHECKER_TYPE_BACKGROUND_CRON_JOB, 0, jobName))
if found {
return true, existedRunningInfo.(string)
}
expiration := runningInterval
if expiration > 1*time.Second {
expiration = expiration - 1*time.Second
}
c.cache.Set(c.getCacheKey(DUPLICATE_CHECKER_TYPE_BACKGROUND_CRON_JOB, 0, jobName), runningInfo, expiration)
return false, ""
}
// RemoveCronJobRunningInfo removes the running info of the cron job by the current duplicate checker
func (c *InMemoryDuplicateChecker) RemoveCronJobRunningInfo(jobName string) {
c.cache.Delete(c.getCacheKey(DUPLICATE_CHECKER_TYPE_BACKGROUND_CRON_JOB, 0, jobName))
}
// GetFailureCount returns the failure count of the specified failure key
func (c *InMemoryDuplicateChecker) GetFailureCount(failureKey string) uint32 {
existedFailureCount, found := c.cache.Get(c.getCacheKey(DUPLICATE_CHECKER_TYPE_FAILURE_CHECK, 0, failureKey))
if found {
return existedFailureCount.(uint32)
}
return 0
}
// IncreaseFailureCount increases the failure count of the specified failure key
func (c *InMemoryDuplicateChecker) IncreaseFailureCount(failureKey string) uint32 {
c.mutex.Lock()
defer c.mutex.Unlock()
cacheKey := c.getCacheKey(DUPLICATE_CHECKER_TYPE_FAILURE_CHECK, 0, failureKey)
_, found := c.cache.Get(cacheKey)
if found {
failureCount, _ := c.cache.IncrementUint32(cacheKey, uint32(1))
return failureCount
} else {
c.cache.Set(cacheKey, uint32(1), 1*time.Minute)
return 1
}
}
func (c *InMemoryDuplicateChecker) getCacheKey(checkerType DuplicateCheckerType, uid int64, identification string) string {
return fmt.Sprintf("%d|%d|%s", checkerType, uid, identification)
}