Files
shop/pricerule/cache.go
2017-11-07 15:35:47 +01:00

168 lines
4.0 KiB
Go

package pricerule
import (
"fmt"
"log"
"sync"
"time"
"gopkg.in/mgo.v2/bson"
)
// Cache - the cache struct type
type Cache struct {
groupsCache map[GroupType]map[string][]string
catalogValidRulesCache []PriceRule
cacheMutex *sync.Mutex
blacklistedItemIDs []string
enabled bool
}
// NewCache -
func NewCache() *Cache {
c := &Cache{}
c.cacheMutex = &sync.Mutex{}
c.enabled = false
return c
}
// GetGroupsCache -
func (c *Cache) GetGroupsCache() map[GroupType]map[string][]string {
return c.groupsCache
}
// InitCatalogCalculationCache - load groups data into memory
func (c *Cache) InitCatalogCalculationCache() (err error) {
now := time.Now()
//synchronize code code
c.cacheMutex.Lock()
defer c.cacheMutex.Unlock()
err = c.loadGroupCacheByItem()
if err != nil {
return
}
catalogValidRulesCache, getPromotionsErr := GetValidPriceRulesForPromotions([]Type{TypePromotionCustomer, TypePromotionProduct, TypePromotionOrder}, nil)
if getPromotionsErr != nil {
err = getPromotionsErr
return
}
c.catalogValidRulesCache = catalogValidRulesCache
//load the blacklisted products
blacklistedItems, blacklistLoadErr := GetBlacklistedItemIds()
if blacklistLoadErr != nil {
err = blacklistLoadErr
log.Println(err)
return
}
c.blacklistedItemIDs = blacklistedItems
// done all
c.enabled = true
timeTrack(now, "[InitCatalogCalculationCache] cache loading took ")
return
}
// ClearCache - will force the use of data from db
func (c *Cache) ClearCatalogCalculationCache() {
c.groupsCache = make(map[GroupType]map[string][]string)
c.catalogValidRulesCache = []PriceRule{}
c.enabled = false
}
// GetGroupsIDSForItem - use cache or fallback to db retrieval
func (c *Cache) GetGroupsIDSForItem(itemID string, groupType GroupType) []string {
// if we have the cache use it,
if c.enabled == true {
if groupIDs, ok := c.groupsCache[groupType][itemID]; ok {
return groupIDs
} else {
groupIDs := []string{} //TODO: if not in the cache means we do not have it
c.groupsCache[groupType][itemID] = groupIDs
return groupIDs
}
}
groupIDs := GetGroupsIDSForItem(itemID, groupType)
return groupIDs
}
// CachedGetValidProductAndCustomerPriceRules -
func (c *Cache) CachedGetValidProductAndCustomerPriceRules(customProvider PriceRuleCustomProvider) ([]PriceRule, error) {
if c.enabled {
return c.catalogValidRulesCache, nil
}
return GetValidPriceRulesForPromotions([]Type{TypePromotionCustomer, TypePromotionProduct}, customProvider)
}
func (c *Cache) GetBlacklistedItemIDs() (itemIDs []string) {
itemIDs = []string{}
if c.enabled {
return c.blacklistedItemIDs
}
itemIDs, err := GetBlacklistedItemIds()
if err != nil {
log.Println(err)
itemIDs = []string{}
}
return
}
// remove value from array - by value not index
func removeValueFromArray(val string, vals []string) []string {
ret := []string{}
for _, inVal := range vals {
if inVal != val {
ret = append(ret, inVal)
}
}
return ret
}
func (c *Cache) loadGroupCacheByItem() error {
now := time.Now()
p := GetPersistorForObject(&Group{})
session, collection := p.GetCollection()
defer session.Close()
tempMap := make(map[GroupType]map[string][]string)
for _, groupType := range []GroupType{ProductGroup, CustomerGroup} {
query := bson.M{"type": groupType}
var result = []Group{}
err := collection.Find(query).Sort("priority").All(&result)
if err != nil {
return err
}
if _, ok := tempMap[groupType]; !ok {
tempMap[groupType] = make(map[string][]string)
}
for _, group := range result {
for _, itemID := range group.ItemIDs {
// if we have a key already append
if _, ok := tempMap[groupType][itemID]; ok {
tempMap[groupType][itemID] = append(tempMap[groupType][itemID], group.ID)
} else {
// initialize and add
tempMap[groupType][itemID] = []string{group.ID}
}
}
}
}
c.groupsCache = tempMap
if Verbose {
fmt.Println(c.GetGroupsCache())
}
c.enabled = true
timeTrack(now, "[loadGroupCacheByItem] cache loading took")
return nil
}