user.go
package slackscot
import (
"fmt"
"github.com/alexandre-normand/slackscot/config"
"github.com/hashicorp/golang-lru"
"github.com/slack-go/slack"
"github.com/spf13/viper"
)
const (
userInfoCacheSizeDisabledValue = 0
)
// UserInfoFinder defines the interface for finding a slack user's info
type UserInfoFinder interface {
GetUserInfo(userID string) (user *slack.User, err error)
}
// selfInfoFinder defines the interface for finding our (the slackscot instance) user info
type selfInfoFinder interface {
GetInfo() (user *slack.Info)
}
// cachingUserInfoFinder holds a cache and a loading UserInfoFinder to implement the UserInfoFinder loading entries from cache
type cachingUserInfoFinder struct {
loader UserInfoFinder
logger SLogger
userProfileCache *lru.ARCCache
}
// NewCachingUserInfoFinder creates a new user info service with caching if enabled via userProfileCacheSizeKey. It requires an implementation
// of the interface that will do the actual loading when not in cache
func NewCachingUserInfoFinder(v *viper.Viper, loader UserInfoFinder, logger SLogger) (uf UserInfoFinder, err error) {
cuf := new(cachingUserInfoFinder)
cs := v.GetInt(config.UserInfoCacheSizeKey)
if cs > userInfoCacheSizeDisabledValue {
cuf.userProfileCache, err = lru.NewARC(cs)
if err != nil {
return nil, err
}
}
cuf.loader = loader
cuf.logger = logger
return cuf, nil
}
// GetUserInfo gets the user info or returns an error and a nil user is not found or
// an error occurred during retrieval
func (c cachingUserInfoFinder) GetUserInfo(userID string) (u *slack.User, err error) {
if c.userProfileCache == nil {
c.logger.Debugf("Cache disabled, loading user info for [%s] from slack instead\n", userID)
return c.loader.GetUserInfo(userID)
}
if userProfile, exists := c.userProfileCache.Get(userID); exists {
c.logger.Debugf("User info in cache [%s] so using that\n", userID)
userProfile, ok := userProfile.(slack.User)
if !ok {
return nil, fmt.Errorf("Error converting cached value for user id [%s]: %v", userID, err)
}
return &userProfile, nil
}
c.logger.Debugf("User info for [%s] not found in cache, retrieving from slack and saving\n", userID)
u, err = c.loader.GetUserInfo(userID)
// Add the user to cache if it was loaded without error
if u != nil {
c.userProfileCache.Add(userID, *u)
}
return u, err
}