diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 71d6ed90..c3e86a3c 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -48,9 +48,17 @@ func main() { } if cfg.Frontend.Enabled { + err = services.StartFrontendCache() + if err != nil { + logger.Fatalf("error starting frontend cache service: %v", err) + } + startFrontend() - } + } else { + utils.WaitForCtrlC() + logger.Println("exiting...") + } } func startFrontend() { diff --git a/handlers/epoch.go b/handlers/epoch.go index e8cae14e..50670194 100644 --- a/handlers/epoch.go +++ b/handlers/epoch.go @@ -56,17 +56,22 @@ func Epoch(w http.ResponseWriter, r *http.Request) { func getEpochPageData(epoch uint64) *models.EpochPageData { pageData := &models.EpochPageData{} pageCacheKey := fmt.Sprintf("epoch:%v", epoch) - if !utils.Config.Frontend.Debug && services.GlobalBeaconService.GetFrontendCache(pageCacheKey, pageData) == nil { - logrus.Printf("epoch page served from cache: %v", epoch) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + pageData, cacheTimeout := buildEpochPageData(epoch) + pageCall.CacheTimeout = cacheTimeout return pageData - } + }).(*models.EpochPageData) + return pageData +} + +func buildEpochPageData(epoch uint64) (*models.EpochPageData, time.Duration) { logrus.Printf("epoch page called: %v", epoch) now := time.Now() currentSlot := utils.TimeToSlot(uint64(now.Unix())) currentEpoch := utils.EpochOfSlot(currentSlot) if epoch > currentEpoch { - return nil + return nil, -1 } finalizedHead, _ := services.GlobalBeaconService.GetFinalizedBlockHead() @@ -74,7 +79,7 @@ func getEpochPageData(epoch uint64) *models.EpochPageData { dbEpochs := services.GlobalBeaconService.GetDbEpochs(epoch, 1) if dbEpochs[0] == nil { - return nil + return nil, -1 } dbEpoch := dbEpochs[0] nextEpoch := epoch + 1 @@ -83,7 +88,7 @@ func getEpochPageData(epoch uint64) *models.EpochPageData { } firstSlot := epoch * utils.Config.Chain.Config.SlotsPerEpoch lastSlot := firstSlot + utils.Config.Chain.Config.SlotsPerEpoch - 1 - pageData = &models.EpochPageData{ + pageData := &models.EpochPageData{ Epoch: epoch, PreviousEpoch: epoch - 1, NextEpoch: nextEpoch, @@ -175,15 +180,11 @@ func getEpochPageData(epoch uint64) *models.EpochPageData { } pageData.BlockCount = uint64(blockCount) - if pageCacheKey != "" { - var cacheTimeout time.Duration - if pageData.Finalized { - cacheTimeout = 30 * time.Minute - } else { - cacheTimeout = 12 * time.Second - } - services.GlobalBeaconService.SetFrontendCache(pageCacheKey, pageData, cacheTimeout) + var cacheTimeout time.Duration + if pageData.Finalized { + cacheTimeout = 30 * time.Minute + } else { + cacheTimeout = 12 * time.Second } - - return pageData + return pageData, cacheTimeout } diff --git a/handlers/epochs.go b/handlers/epochs.go index 5f6246d2..c1408d43 100644 --- a/handlers/epochs.go +++ b/handlers/epochs.go @@ -45,11 +45,17 @@ func Epochs(w http.ResponseWriter, r *http.Request) { func getEpochsPageData(firstEpoch uint64, pageSize uint64) *models.EpochsPageData { pageData := &models.EpochsPageData{} pageCacheKey := fmt.Sprintf("epochs:%v:%v", firstEpoch, pageSize) - if !utils.Config.Frontend.Debug && services.GlobalBeaconService.GetFrontendCache(pageCacheKey, pageData) == nil { - logrus.Printf("epochs page served from cache: %v:%v", firstEpoch, pageSize) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + pageData, cacheTimeout := buildEpochsPageData(firstEpoch, pageSize) + pageCall.CacheTimeout = cacheTimeout return pageData - } + }).(*models.EpochsPageData) + return pageData +} + +func buildEpochsPageData(firstEpoch uint64, pageSize uint64) (*models.EpochsPageData, time.Duration) { logrus.Printf("epochs page called: %v:%v", firstEpoch, pageSize) + pageData := &models.EpochsPageData{} now := time.Now() currentEpoch := utils.TimeToEpoch(now) @@ -133,15 +139,11 @@ func getEpochsPageData(firstEpoch uint64, pageSize uint64) *models.EpochsPageDat pageData.FirstEpoch = firstEpoch pageData.LastEpoch = firstEpoch - pageData.EpochCount + 1 - if pageCacheKey != "" { - var cacheTimeout time.Duration - if firstEpoch+2 < uint64(currentEpoch) { - cacheTimeout = 10 * time.Minute - } else { - cacheTimeout = 12 * time.Second - } - services.GlobalBeaconService.SetFrontendCache(pageCacheKey, pageData, cacheTimeout) + var cacheTimeout time.Duration + if firstEpoch+2 < uint64(currentEpoch) { + cacheTimeout = 10 * time.Minute + } else { + cacheTimeout = 12 * time.Second } - - return pageData + return pageData, cacheTimeout } diff --git a/handlers/index.go b/handlers/index.go index b80a5466..760ba996 100644 --- a/handlers/index.go +++ b/handlers/index.go @@ -41,10 +41,15 @@ func Index(w http.ResponseWriter, r *http.Request) { func getIndexPageData() *models.IndexPageData { pageData := &models.IndexPageData{} pageCacheKey := fmt.Sprintf("index") - if !utils.Config.Frontend.Debug && services.GlobalBeaconService.GetFrontendCache(pageCacheKey, pageData) == nil { - logrus.Printf("index page served from cache") + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + pageData, cacheTimeout := buildIndexPageData() + pageCall.CacheTimeout = cacheTimeout return pageData - } + }).(*models.IndexPageData) + return pageData +} + +func buildIndexPageData() (*models.IndexPageData, time.Duration) { logrus.Printf("index page called") recentEpochCount := 15 @@ -79,7 +84,7 @@ func getIndexPageData() *models.IndexPageData { isSynced = true } - pageData = &models.IndexPageData{ + pageData := &models.IndexPageData{ NetworkName: utils.Config.Chain.Name, DepositContract: utils.Config.Chain.Config.DepositContractAddress, ShowSyncingMessage: !isSynced, @@ -214,8 +219,5 @@ func getIndexPageData() *models.IndexPageData { } pageData.RecentBlockCount = uint64(len(pageData.RecentBlocks)) - if pageCacheKey != "" { - services.GlobalBeaconService.SetFrontendCache(pageCacheKey, pageData, 12*time.Second) - } - return pageData + return pageData, 12 * time.Second } diff --git a/handlers/slot.go b/handlers/slot.go index c5d07bc7..b33d4a77 100644 --- a/handlers/slot.go +++ b/handlers/slot.go @@ -34,9 +34,6 @@ func Slot(w http.ResponseWriter, r *http.Request) { var notfoundTemplateFiles = append(layoutTemplateFiles, "slot/notfound.html", ) - var errorTemplateFiles = append(layoutTemplateFiles, - "slot/error.html", - ) w.Header().Set("Content-Type", "text/html") vars := mux.Vars(r) @@ -55,13 +52,41 @@ func Slot(w http.ResponseWriter, r *http.Request) { } } + pageData := getSlotPageData(blockSlot, blockRootHash) + if pageData == nil { + data := InitPageData(w, r, "blockchain", "/slots", fmt.Sprintf("Slot %v", slotOrHash), notfoundTemplateFiles) + data.Data = "slot" + if handleTemplateError(w, r, "slot.go", "Slot", "notFound", templates.GetTemplate(notfoundTemplateFiles...).ExecuteTemplate(w, "layout", data)) != nil { + return // an error has occurred and was processed + } + return + } + + template := templates.GetTemplate(slotTemplateFiles...) + data := InitPageData(w, r, "blockchain", "/slots", fmt.Sprintf("Slot %v", slotOrHash), slotTemplateFiles) + data.Data = pageData + if handleTemplateError(w, r, "index.go", "Slot", "", template.ExecuteTemplate(w, "layout", data)) != nil { + return // an error has occurred and was processed + } +} + +func getSlotPageData(blockSlot int64, blockRoot []byte) *models.SlotPageData { + pageData := &models.SlotPageData{} + pageCacheKey := fmt.Sprintf("slot:%v:%x", blockSlot, blockRoot) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + return buildSlotPageData(blockSlot, blockRoot) + }).(*models.SlotPageData) + return pageData +} + +func buildSlotPageData(blockSlot int64, blockRoot []byte) *models.SlotPageData { finalizedHead, err := services.GlobalBeaconService.GetFinalizedBlockHead() var blockData *rpctypes.CombinedBlockResponse if err == nil { if blockSlot > -1 { blockData, err = services.GlobalBeaconService.GetSlotDetailsBySlot(uint64(blockSlot), true) } else { - blockData, err = services.GlobalBeaconService.GetSlotDetailsByBlockroot(blockRootHash, true) + blockData, err = services.GlobalBeaconService.GetSlotDetailsByBlockroot(blockRoot, true) } } @@ -70,37 +95,19 @@ func Slot(w http.ResponseWriter, r *http.Request) { if blockSlot > -1 { dbBlocks := services.GlobalBeaconService.GetDbBlocksForSlots(uint64(blockSlot), 1, true) if len(dbBlocks) > 0 { - blockRootHash = dbBlocks[0].Root + blockRoot = dbBlocks[0].Root } } - if blockRootHash != nil { - blockData = services.GlobalBeaconService.GetOrphanedBlock(blockRootHash) + if blockRoot != nil { + blockData = services.GlobalBeaconService.GetOrphanedBlock(blockRoot) } } - var slot uint64 - if blockData == nil && err == nil { - if blockSlot > -1 { - slot = uint64(blockSlot) - } else { - data := InitPageData(w, r, "blockchain", "/slots", fmt.Sprintf("Slot %v", slotOrHash), notfoundTemplateFiles) - data.Data = "slot" - if handleTemplateError(w, r, "slot.go", "Slot", "notFound", templates.GetTemplate(notfoundTemplateFiles...).ExecuteTemplate(w, "layout", data)) != nil { - return // an error has occurred and was processed - } - return - } - } else if err != nil { - logrus.Printf("slot page error: %v", err) - data := InitPageData(w, r, "blockchain", "/slots", fmt.Sprintf("Slot %v", slotOrHash), errorTemplateFiles) - data.Data = err.Error() - if handleTemplateError(w, r, "slot.go", "Slot", "notFound", templates.GetTemplate(errorTemplateFiles...).ExecuteTemplate(w, "layout", data)) != nil { - return // an error has occurred and was processed - } - return - } else { - slot = uint64(blockData.Header.Data.Header.Message.Slot) + if blockData == nil { + return nil } + slot := uint64(blockData.Header.Data.Header.Message.Slot) + logrus.Printf("slot page called: %v", slot) pageData := &models.SlotPageData{ Slot: slot, @@ -117,9 +124,6 @@ func Slot(w http.ResponseWriter, r *http.Request) { // we can safely continue here. the UI is prepared to work without epoch duties, but fields related to the duties are not shown } - template := templates.GetTemplate(slotTemplateFiles...) - data := InitPageData(w, r, "blockchain", "/slots", fmt.Sprintf("Slot %v", slotOrHash), slotTemplateFiles) - if blockData == nil { pageData.Status = uint16(models.SlotStatusMissed) @@ -138,12 +142,7 @@ func Slot(w http.ResponseWriter, r *http.Request) { pageData.Block = getSlotPageBlockData(blockData, assignments) } - logrus.Printf("slot page called") - data.Data = pageData - - if handleTemplateError(w, r, "index.go", "Slot", "", template.ExecuteTemplate(w, "layout", data)) != nil { - return // an error has occurred and was processed - } + return pageData } func getSlotPageBlockData(blockData *rpctypes.CombinedBlockResponse, assignments *rpctypes.EpochAssignments) *models.SlotPageBlockData { diff --git a/handlers/slots.go b/handlers/slots.go index 13b7fdb5..77fe0821 100644 --- a/handlers/slots.go +++ b/handlers/slots.go @@ -59,11 +59,17 @@ func Slots(w http.ResponseWriter, r *http.Request) { func getSlotsPageData(firstSlot uint64, pageSize uint64) *models.SlotsPageData { pageData := &models.SlotsPageData{} pageCacheKey := fmt.Sprintf("slots:%v:%v", firstSlot, pageSize) - if !utils.Config.Frontend.Debug && services.GlobalBeaconService.GetFrontendCache(pageCacheKey, pageData) == nil { - logrus.Printf("slots page served from cache: %v:%v", firstSlot, pageSize) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + pageData, cacheTimeout := buildSlotsPageData(firstSlot, pageSize) + pageCall.CacheTimeout = cacheTimeout return pageData - } + }).(*models.SlotsPageData) + return pageData +} + +func buildSlotsPageData(firstSlot uint64, pageSize uint64) (*models.SlotsPageData, time.Duration) { logrus.Printf("slots page called: %v:%v", firstSlot, pageSize) + pageData := &models.SlotsPageData{} now := time.Now() currentSlot := utils.TimeToSlot(uint64(now.Unix())) @@ -181,19 +187,25 @@ func getSlotsPageData(firstSlot uint64, pageSize uint64) *models.SlotsPageData { pageData.FirstSlot = firstSlot pageData.LastSlot = lastSlot - if pageCacheKey != "" { - var cacheTimeout time.Duration - if firstEpoch < uint64(currentEpoch) { - cacheTimeout = 10 * time.Minute - } else { - cacheTimeout = 12 * time.Second - } - services.GlobalBeaconService.SetFrontendCache(pageCacheKey, pageData, cacheTimeout) + var cacheTimeout time.Duration + if firstEpoch < uint64(currentEpoch) { + cacheTimeout = 10 * time.Minute + } else { + cacheTimeout = 12 * time.Second } - return pageData + return pageData, cacheTimeout } func getSlotsPageDataWithGraffitiFilter(graffiti string, pageIdx uint64, pageSize uint64) *models.SlotsPageData { + pageData := &models.SlotsPageData{} + pageCacheKey := fmt.Sprintf("slots:%v:%v:g-%v", pageIdx, pageSize, graffiti) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(_ *services.FrontendCacheProcessingPage) interface{} { + return buildSlotsPageDataWithGraffitiFilter(graffiti, pageIdx, pageSize) + }).(*models.SlotsPageData) + return pageData +} + +func buildSlotsPageDataWithGraffitiFilter(graffiti string, pageIdx uint64, pageSize uint64) *models.SlotsPageData { pageData := &models.SlotsPageData{ GraffitiFilter: graffiti, } diff --git a/handlers/validator.go b/handlers/validator.go index e6f2c199..868425c6 100644 --- a/handlers/validator.go +++ b/handlers/validator.go @@ -73,19 +73,24 @@ func Validator(w http.ResponseWriter, r *http.Request) { } } -func getValidatorPageData(validatorIndex uint64) *models.ValidatorPageData { - pageData := &models.ValidatorPageData{} +func getValidatorPageData(validatorIndex uint64) *models.EpochPageData { + pageData := &models.EpochPageData{} pageCacheKey := fmt.Sprintf("validator:%v", validatorIndex) - if !utils.Config.Frontend.Debug && services.GlobalBeaconService.GetFrontendCache(pageCacheKey, pageData) == nil { - logrus.Printf("validator page served from cache: %v", validatorIndex) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + pageData, cacheTimeout := buildValidatorPageData(validatorIndex) + pageCall.CacheTimeout = cacheTimeout return pageData - } + }).(*models.EpochPageData) + return pageData +} + +func buildValidatorPageData(validatorIndex uint64) (*models.ValidatorPageData, time.Duration) { logrus.Printf("validator page called: %v", validatorIndex) validatorSetRsp := services.GlobalBeaconService.GetCachedValidatorSet() validator := validatorSetRsp.Data[validatorIndex] - pageData = &models.ValidatorPageData{ + pageData := &models.ValidatorPageData{ CurrentEpoch: uint64(utils.TimeToEpoch(time.Now())), Index: uint64(validator.Index), Name: services.GlobalBeaconService.GetValidatorName(uint64(validator.Index)), @@ -167,8 +172,5 @@ func getValidatorPageData(validatorIndex uint64) *models.ValidatorPageData { } pageData.RecentBlockCount = uint64(len(pageData.RecentBlocks)) - if pageCacheKey != "" { - services.GlobalBeaconService.SetFrontendCache(pageCacheKey, pageData, 10*time.Minute) - } - return pageData + return pageData, 10 * time.Minute } diff --git a/handlers/validators.go b/handlers/validators.go index 628c19d7..c7c40dbc 100644 --- a/handlers/validators.go +++ b/handlers/validators.go @@ -46,19 +46,25 @@ func Validators(w http.ResponseWriter, r *http.Request) { } } -func getValidatorsPageData(firstValIdx uint64, pageSize uint64, stateFilter string) *models.ValidatorsPageData { - pageData := &models.ValidatorsPageData{} +func getValidatorsPageData(firstValIdx uint64, pageSize uint64, stateFilter string) *models.EpochPageData { + pageData := &models.EpochPageData{} pageCacheKey := fmt.Sprintf("validators:%v:%v:%v", firstValIdx, pageSize, stateFilter) - if !utils.Config.Frontend.Debug && services.GlobalBeaconService.GetFrontendCache(pageCacheKey, pageData) == nil { - logrus.Printf("validators page served from cache: %v:%v", firstValIdx, pageSize) + pageData = services.GlobalFrontendCache.ProcessCachedPage(pageCacheKey, true, pageData, func(pageCall *services.FrontendCacheProcessingPage) interface{} { + pageData, cacheTimeout := buildValidatorsPageData(firstValIdx, pageSize, stateFilter) + pageCall.CacheTimeout = cacheTimeout return pageData - } + }).(*models.EpochPageData) + return pageData +} + +func buildValidatorsPageData(firstValIdx uint64, pageSize uint64, stateFilter string) (*models.ValidatorsPageData, time.Duration) { logrus.Printf("validators page called: %v:%v:%v", firstValIdx, pageSize, stateFilter) + pageData := &models.ValidatorsPageData{} // get latest validator set validatorSetRsp := services.GlobalBeaconService.GetCachedValidatorSet() if validatorSetRsp == nil { - return pageData + return nil, 5 * time.Minute } validatorSet := validatorSetRsp.Data if stateFilter != "" { @@ -161,8 +167,5 @@ func getValidatorsPageData(firstValIdx uint64, pageSize uint64, stateFilter stri pageData.FirstValidator = firstValIdx pageData.LastValidator = lastValIdx - if pageCacheKey != "" { - services.GlobalBeaconService.SetFrontendCache(pageCacheKey, pageData, 10*time.Minute) - } - return pageData + return pageData, 10 * time.Minute } diff --git a/services/beaconservice.go b/services/beaconservice.go index 9f9dcf0d..740c3a67 100644 --- a/services/beaconservice.go +++ b/services/beaconservice.go @@ -1,12 +1,10 @@ package services import ( - "fmt" "strings" "sync" "time" - "github.com/pk910/light-beaconchain-explorer/cache" "github.com/pk910/light-beaconchain-explorer/db" "github.com/pk910/light-beaconchain-explorer/dbtypes" "github.com/pk910/light-beaconchain-explorer/indexer" @@ -17,7 +15,6 @@ import ( type BeaconService struct { rpcClient *rpc.BeaconClient - frontendCache *cache.TieredCache indexer *indexer.Indexer validatorNames *ValidatorNames @@ -42,12 +39,6 @@ func StartBeaconService() error { return err } - cachePrefix := fmt.Sprintf("%sgui-", utils.Config.BeaconApi.RedisCachePrefix) - frontendCache, err := cache.NewTieredCache(utils.Config.BeaconApi.LocalCacheSize, utils.Config.BeaconApi.RedisCacheAddr, cachePrefix) - if err != nil { - return err - } - indexer, err := indexer.NewIndexer(rpcClient) if err != nil { return err @@ -67,22 +58,12 @@ func StartBeaconService() error { GlobalBeaconService = &BeaconService{ rpcClient: rpcClient, - frontendCache: frontendCache, indexer: indexer, validatorNames: validatorNames, } return nil } -func (bs *BeaconService) GetFrontendCache(pageKey string, returnValue interface{}) error { - _, err := bs.frontendCache.Get(pageKey, returnValue) - return err -} - -func (bs *BeaconService) SetFrontendCache(pageKey string, value interface{}, timeout time.Duration) error { - return bs.frontendCache.Set(pageKey, value, timeout) -} - func (bs *BeaconService) GetValidatorName(index uint64) string { return bs.validatorNames.GetValidatorName(index) } diff --git a/services/frontendcache.go b/services/frontendcache.go new file mode 100644 index 00000000..ffcc6347 --- /dev/null +++ b/services/frontendcache.go @@ -0,0 +1,101 @@ +package services + +import ( + "fmt" + "sync" + "time" + + "github.com/pk910/light-beaconchain-explorer/cache" + "github.com/pk910/light-beaconchain-explorer/utils" + "github.com/sirupsen/logrus" +) + +type FrontendCacheService struct { + tieredCache *cache.TieredCache + + processingMutex sync.Mutex + processingDict map[string]*FrontendCacheProcessingPage +} + +type FrontendCacheProcessingPage struct { + modelMutex sync.RWMutex + pageModel interface{} + CacheTimeout time.Duration +} + +var GlobalFrontendCache *FrontendCacheService + +// StartFrontendCache is used to start the global frontend cache service +func StartFrontendCache() error { + if GlobalFrontendCache != nil { + return nil + } + + cachePrefix := fmt.Sprintf("%sgui-", utils.Config.BeaconApi.RedisCachePrefix) + tieredCache, err := cache.NewTieredCache(utils.Config.BeaconApi.LocalCacheSize, utils.Config.BeaconApi.RedisCacheAddr, cachePrefix) + if err != nil { + return err + } + + GlobalFrontendCache = &FrontendCacheService{ + tieredCache: tieredCache, + processingDict: make(map[string]*FrontendCacheProcessingPage), + } + return nil +} + +func (fc *FrontendCacheService) GetFrontendCache(pageKey string, returnValue interface{}) error { + _, err := fc.tieredCache.Get(pageKey, returnValue) + return err +} + +func (fc *FrontendCacheService) SetFrontendCache(pageKey string, value interface{}, timeout time.Duration) error { + return fc.tieredCache.Set(pageKey, value, timeout) +} + +func (fc *FrontendCacheService) ProcessCachedPage(pageKey string, caching bool, returnValue interface{}, buildFn func(pageCall *FrontendCacheProcessingPage) interface{}) interface{} { + fc.processingMutex.Lock() + processingPage := fc.processingDict[pageKey] + if processingPage != nil { + fc.processingMutex.Unlock() + logrus.Printf("page already processing: %v", pageKey) + + processingPage.modelMutex.RLock() + defer processingPage.modelMutex.RUnlock() + return processingPage.pageModel + } + + processingPage = &FrontendCacheProcessingPage{ + CacheTimeout: -1, + } + fc.processingDict[pageKey] = processingPage + processingPage.modelMutex.Lock() + defer fc.completePageLoad(pageKey, processingPage) + fc.processingMutex.Unlock() + + returnValue = fc.processCachedPageData(pageKey, caching, returnValue, buildFn, processingPage) + processingPage.pageModel = returnValue + return returnValue +} + +func (fc *FrontendCacheService) completePageLoad(pageKey string, processingPage *FrontendCacheProcessingPage) { + processingPage.modelMutex.Unlock() + fc.processingMutex.Lock() + delete(fc.processingDict, pageKey) + fc.processingMutex.Unlock() +} + +func (fc *FrontendCacheService) processCachedPageData(pageKey string, caching bool, pageData interface{}, buildFn func(pageCall *FrontendCacheProcessingPage) interface{}, pageCall *FrontendCacheProcessingPage) interface{} { + // check cache + if !utils.Config.Frontend.Debug && caching && fc.GetFrontendCache(pageKey, pageData) == nil { + logrus.Printf("page served from cache: %v", pageKey) + return pageData + } + + pageData = buildFn(pageCall) + + if !utils.Config.Frontend.Debug && caching && pageCall.CacheTimeout >= 0 { + fc.SetFrontendCache(pageKey, pageData, pageCall.CacheTimeout) + } + return pageData +} diff --git a/templates/slot/error.html b/templates/slot/error.html deleted file mode 100644 index 6d106e17..00000000 --- a/templates/slot/error.html +++ /dev/null @@ -1,27 +0,0 @@ -{{ define "js" }} -{{ end }} - -{{ define "css" }} -{{ end }} - -{{ define "page" }} -
-
-
-

Error while fetching Slot details

- -
-
-
-
-
Sorry there was an unexpected error: {{ . }}
-
-
-
-{{ end }}