mirror of
https://github.com/foomo/gocontentful.git
synced 2025-10-16 12:25:39 +00:00
fix: parents update, race conditions
This commit is contained in:
parent
65c1022c2b
commit
f2ec27ebd7
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,3 +16,5 @@ bin
|
||||
*.idea
|
||||
/.vscode/*
|
||||
/untracked_*.go
|
||||
cover.html
|
||||
cover.out
|
||||
8
Makefile
8
Makefile
@ -16,12 +16,18 @@ build:
|
||||
## Run tests
|
||||
test:
|
||||
go run ./main.go -exportfile ./test/test-space-export.json ./test/testapi
|
||||
go test -count=1 ./...
|
||||
go test ./...
|
||||
|
||||
race:
|
||||
go run ./main.go -exportfile ./test/test-space-export.json ./test/testapi
|
||||
go test -race ./...
|
||||
|
||||
cover:
|
||||
rm cover.out cover.html
|
||||
go run ./main.go -exportfile ./test/test-space-export.json ./test/testapi
|
||||
go test -cover -coverprofile cover.out -coverpkg=./test/testapi ./...
|
||||
go tool cover -html=cover.out -o cover.html; open cover.html
|
||||
|
||||
.PHONY: lint
|
||||
## Run linter
|
||||
lint:
|
||||
|
||||
@ -210,6 +210,8 @@ func (cc *ContentfulClient) CacheHasContentType(contentTypeID string) bool {
|
||||
if cc.Cache == nil {
|
||||
return false
|
||||
}
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
defer cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
for _, cachedContentType := range cc.Cache.contentTypes {
|
||||
if cachedContentType == contentTypeID {
|
||||
return true
|
||||
@ -223,6 +225,8 @@ func (cc *ContentfulClient) ClientStats() {
|
||||
cc.logFn(nil, LogWarn, "ClientStats: no client available")
|
||||
return
|
||||
}
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
defer cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cc.logFn != nil {
|
||||
fieldsMap := map[string]interface{}{
|
||||
"space ID": cc.SpaceID,
|
||||
@ -235,7 +239,14 @@ func (cc *ContentfulClient) ClientStats() {
|
||||
if cc.cacheInit {
|
||||
fieldsMap["cache asset count"] = len(cc.Cache.assets)
|
||||
fieldsMap["cache entry count"] = len(cc.Cache.idContentTypeMap)
|
||||
fieldsMap["cache parentMap length"] = len(cc.Cache.parentMap)
|
||||
fieldsMap["cache parentMap children"] = len(cc.Cache.parentMap)
|
||||
cc.cacheMutex.parentMapGcLock.RLock()
|
||||
defer cc.cacheMutex.parentMapGcLock.RUnlock()
|
||||
referenceCount := 0
|
||||
for _, parents := range cc.Cache.parentMap {
|
||||
referenceCount += len(parents)
|
||||
}
|
||||
fieldsMap["cache parentMap parents"] = referenceCount
|
||||
}
|
||||
cc.logFn(fieldsMap, LogInfo, "Contentful ClientStats")
|
||||
}
|
||||
@ -283,10 +294,13 @@ func (cc *ContentfulClient) GetAssetByID(id string, forceNoCache ...bool) (*cont
|
||||
if cc == nil || cc.Client == nil {
|
||||
return nil, errors.New("GetAssetByID: No client available")
|
||||
}
|
||||
if cc.cacheInit && cc.Cache.assets != nil && (len(forceNoCache) == 0 || !forceNoCache[0]) {
|
||||
cc.cacheMutex.assetsGcLock.Lock()
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cacheInit := cc.cacheInit
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
cc.cacheMutex.assetsGcLock.Lock()
|
||||
defer cc.cacheMutex.assetsGcLock.Unlock()
|
||||
if cacheInit && cc.Cache.assets != nil && (len(forceNoCache) == 0 || !forceNoCache[0]) {
|
||||
asset, okAsset := cc.Cache.assets[id]
|
||||
cc.cacheMutex.assetsGcLock.Unlock()
|
||||
if okAsset {
|
||||
return asset, nil
|
||||
} else {
|
||||
@ -583,6 +597,8 @@ func (cc *ContentfulClient) SetOfflineFallback(filename string) error {
|
||||
}
|
||||
|
||||
func (cc *ContentfulClient) SetSyncMode(mode bool) error {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
defer cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cc.offline {
|
||||
return errors.New("SetSyncMode: client is set offline, can't enable sync")
|
||||
}
|
||||
@ -595,14 +611,18 @@ func (cc *ContentfulClient) ResetSync() {
|
||||
}
|
||||
|
||||
func (cc *ContentfulClient) UpdateCache(ctx context.Context, contentTypes []string, cacheAssets bool) error {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
ctxAtWork, cancel := context.WithTimeout(ctx, time.Second*time.Duration(cc.cacheUpdateTimeout))
|
||||
defer cancel()
|
||||
if cc.offline {
|
||||
ctxAtWork = ctx
|
||||
}
|
||||
if !cc.offline {
|
||||
time.Sleep(time.Second * 2)
|
||||
}
|
||||
defer cancel()
|
||||
localOffline := cc.offline
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
|
||||
if localOffline {
|
||||
ctxAtWork = ctx
|
||||
}
|
||||
if !localOffline {
|
||||
time.Sleep(time.Second * 2)
|
||||
}
|
||||
if contentTypes == nil {
|
||||
contentTypes = spaceContentTypes
|
||||
} else {
|
||||
@ -647,7 +667,9 @@ func (cc *ContentfulClient) UpdateCache(ctx context.Context, contentTypes []stri
|
||||
|
||||
func (cc *ContentfulClient) syncCache(ctx context.Context, contentTypes []string) error {
|
||||
start := time.Now()
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cc.Cache.contentTypes = contentTypes
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
if cc.logFn != nil && cc.logLevel <= LogInfo {
|
||||
cc.logFn(map[string]interface{}{"task": "syncCache"}, LogInfo, InfoCacheUpdateQueued)
|
||||
}
|
||||
@ -658,8 +680,10 @@ func (cc *ContentfulClient) syncCache(ctx context.Context, contentTypes []string
|
||||
cc.syncToken,
|
||||
)
|
||||
col.GetAll()
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cc.syncToken = col.SyncToken
|
||||
cc.cacheInit = true
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
if len(col.Items) == 0 {
|
||||
if cc.logFn != nil && cc.logLevel <= LogInfo {
|
||||
cc.logFn(map[string]interface{}{"time elapsed": fmt.Sprint(time.Since(start)), "task": "syncCache"}, LogInfo, InfoUpdateCacheTime)
|
||||
@ -805,11 +829,21 @@ func (cc *ContentfulClient) cacheSpace(ctx context.Context, contentTypes []strin
|
||||
cc.logFn(map[string]interface{}{"time elapsed": fmt.Sprint(time.Since(start)), "task": "UpdateCache"}, LogInfo, InfoUpdateCacheTime)
|
||||
}
|
||||
cc.cacheMutex.fullCacheGcLock.Lock()
|
||||
defer cc.cacheMutex.fullCacheGcLock.Unlock()
|
||||
cc.Cache = tempCache
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cc.cacheMutex.assetsGcLock.Lock()
|
||||
cc.cacheMutex.idContentTypeMapGcLock.Lock()
|
||||
cc.cacheMutex.parentMapGcLock.Lock()
|
||||
{{ range $index , $contentType := $contentTypes }}cc.cacheMutex.{{ $contentType.Sys.ID }}GcLock.Lock()
|
||||
{{ end }}
|
||||
cc.Cache = tempCache
|
||||
cc.offline = offlinePreviousState
|
||||
{{ range $index , $contentType := $contentTypes }}cc.cacheMutex.{{ $contentType.Sys.ID }}GcLock.Unlock()
|
||||
{{ end }}
|
||||
cc.cacheMutex.parentMapGcLock.Unlock()
|
||||
cc.cacheMutex.idContentTypeMapGcLock.Unlock()
|
||||
cc.cacheMutex.assetsGcLock.Unlock()
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
cc.cacheMutex.fullCacheGcLock.Unlock()
|
||||
}
|
||||
|
||||
func ToAssetReference(asset *contentful.Asset) (refSys ContentTypeSys) {
|
||||
@ -922,12 +956,17 @@ func (cc *ContentfulClient) getAllAssets(tryCacheFirst bool) (map[string]*conten
|
||||
if cc == nil || cc.Client == nil {
|
||||
return nil, errors.New("getAllAssets: No client available")
|
||||
}
|
||||
if cc.cacheInit && cc.Cache.assets != nil && tryCacheFirst {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
offline := cc.offline
|
||||
cacheInit := cc.cacheInit
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
|
||||
if cacheInit && cc.Cache.assets != nil && tryCacheFirst {
|
||||
return cc.Cache.assets, nil
|
||||
}
|
||||
allItems := []interface{}{}
|
||||
assets := map[string]*contentful.Asset{}
|
||||
if cc.offline {
|
||||
if offline {
|
||||
for _, asset := range cc.offlineTemp.Assets {
|
||||
allItems = append(allItems,asset)
|
||||
}
|
||||
|
||||
@ -20,10 +20,14 @@ func (cc *ContentfulClient) GetAll{{ firstCap $contentType.Sys.ID }}() (voMap ma
|
||||
if cc == nil {
|
||||
return nil, errors.New("GetAll{{ firstCap $contentType.Sys.ID }}: No client available")
|
||||
}
|
||||
if cc.cacheInit {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
cacheInit := cc.cacheInit
|
||||
optimisticPageSize := cc.optimisticPageSize
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cacheInit {
|
||||
return cc.Cache.entryMaps.{{ $contentType.Sys.ID }}, nil
|
||||
}
|
||||
col, err := cc.optimisticPageSizeGetAll("{{ $contentType.Sys.ID }}", cc.optimisticPageSize)
|
||||
col, err := cc.optimisticPageSizeGetAll("{{ $contentType.Sys.ID }}", optimisticPageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -740,9 +744,9 @@ func (cc *ContentfulClient) cache{{ firstCap $contentType.Sys.ID }}ByID(ctx cont
|
||||
// delete as child
|
||||
delete(cc.Cache.parentMap, id)
|
||||
// delete as parent
|
||||
for childID, child := range cc.Cache.parentMap {
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range child {
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
@ -761,12 +765,14 @@ func (cc *ContentfulClient) cache{{ firstCap $contentType.Sys.ID }}ByID(ctx cont
|
||||
}
|
||||
cc.Cache.entryMaps.{{ $contentType.Sys.ID }}[id] = {{ $contentType.Sys.ID }}
|
||||
cc.Cache.idContentTypeMap[id] = {{ $contentType.Sys.ID }}.Sys.ContentType.Sys.ID
|
||||
allChildrensIds := map[string]bool{}
|
||||
{{ range $fieldIndex, $field := $contentType.Fields }}
|
||||
{{ if fieldIsMultipleReference $field }}
|
||||
for _, loc := range cc.locales {
|
||||
children, okChildren := {{ $contentType.Sys.ID }}.Fields.{{ firstCap $field.ID }}[string(loc)]
|
||||
if okChildren {
|
||||
for _, child := range children {
|
||||
allChildrensIds[child.Sys.ID] = true
|
||||
if cc.Cache.parentMap[child.Sys.ID] == nil {
|
||||
cc.Cache.parentMap[child.Sys.ID] = []EntryReference{}
|
||||
}
|
||||
@ -787,6 +793,7 @@ func (cc *ContentfulClient) cache{{ firstCap $contentType.Sys.ID }}ByID(ctx cont
|
||||
for _, loc := range cc.locales {
|
||||
child, okChild := {{ $contentType.Sys.ID }}.Fields.{{ firstCap $field.ID }}[string(loc)]
|
||||
if okChild {
|
||||
allChildrensIds[child.Sys.ID] = true
|
||||
if cc.Cache.parentMap[child.Sys.ID] == nil {
|
||||
cc.Cache.parentMap[child.Sys.ID] = []EntryReference{}
|
||||
}
|
||||
@ -803,6 +810,20 @@ func (cc *ContentfulClient) cache{{ firstCap $contentType.Sys.ID }}ByID(ctx cont
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
_ = allChildrensIds // safety net
|
||||
// clean up child-parents that don't exist anymore
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
if _, isCollectedChildID := allChildrensIds[childID]; isCollectedChildID {
|
||||
continue
|
||||
}
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
}
|
||||
cc.Cache.parentMap[childID] = newParents
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
2
main.go
2
main.go
@ -13,7 +13,7 @@ import (
|
||||
"github.com/foomo/gocontentful/erm"
|
||||
)
|
||||
|
||||
var VERSION = "v1.0.17"
|
||||
var VERSION = "v1.0.18"
|
||||
|
||||
type contentfulRc struct {
|
||||
ManagementToken string `json:"managementToken"`
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
contentfulClient, err := getTestClient()
|
||||
contentfulClient.ClientStats()
|
||||
require.NoError(t, err)
|
||||
stats, err := contentfulClient.GetCacheStats()
|
||||
require.NoError(t, err)
|
||||
@ -17,6 +18,8 @@ func TestCache(t *testing.T) {
|
||||
require.Equal(t, 12, stats.AssetCount)
|
||||
require.Equal(t, 9, stats.EntryCount)
|
||||
require.Equal(t, 6, stats.ParentCount)
|
||||
err = contentfulClient.SetSyncMode(true)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestBrokenReferences(t *testing.T) {
|
||||
@ -32,6 +35,15 @@ func TestCacheHasContentType(t *testing.T) {
|
||||
require.True(t, contentfulClient.CacheHasContentType("brand"))
|
||||
}
|
||||
|
||||
func TestGetAsset(t *testing.T) {
|
||||
contentfulClient, err := getTestClient()
|
||||
require.NoError(t, err)
|
||||
_, err = contentfulClient.GetAssetByID("Xc0ny7GWsMEMCeASWO2um")
|
||||
require.NoError(t, err)
|
||||
newAsset := testapi.NewAssetFromURL("12345", "https://example.com", "PNG", "New Asset")
|
||||
require.NotNil(t, newAsset)
|
||||
}
|
||||
|
||||
func TestDeleteAssetFromCache(t *testing.T) {
|
||||
contentfulClient, err := getTestClient()
|
||||
require.NoError(t, err)
|
||||
@ -91,7 +103,7 @@ func TestPreserveCacheIfNewer(t *testing.T) {
|
||||
require.Equal(t, 2.0, brand.Sys.Version)
|
||||
}
|
||||
|
||||
func TestAddEntryAndSet(t *testing.T) {
|
||||
func TestEntry(t *testing.T) {
|
||||
contentfulClient, err := getTestClient()
|
||||
require.NoError(t, err)
|
||||
cfProduct := testapi.NewCfProduct(contentfulClient)
|
||||
|
||||
@ -19,8 +19,26 @@ func readWorker(contentfulClient *testapi.ContentfulClient, i int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = contentfulClient.GetAllProduct()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
price := product.Price()
|
||||
testLogger.Infof("Read worker %d read price: %f", i, price)
|
||||
_ = product.Brand()
|
||||
_ = product.Categories()
|
||||
_ = product.Image()
|
||||
_ = product.Nodes()
|
||||
_ = product.ProductDescription()
|
||||
_ = product.ProductName()
|
||||
_ = product.Quantity()
|
||||
_ = product.SeoText()
|
||||
_ = product.Sizetypecolor()
|
||||
_ = product.Sku()
|
||||
_ = product.Slug()
|
||||
_ = product.Tags()
|
||||
_ = product.Website()
|
||||
_ = product.GetPublishingStatus()
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -48,6 +66,19 @@ func writeWorker(contentfulClient *testapi.ContentfulClient, i int) error {
|
||||
}
|
||||
contentfulClient.SetProductInCache(product)
|
||||
testLogger.Infof("Write worker %d set price: %d", i, i)
|
||||
product.SetBrand(testapi.ContentTypeSys{})
|
||||
product.SetCategories([]testapi.ContentTypeSys{})
|
||||
product.SetImage([]testapi.ContentTypeSys{})
|
||||
product.SetNodes(nil)
|
||||
product.SetProductDescription("")
|
||||
product.SetProductName("")
|
||||
product.SetQuantity(1)
|
||||
product.SetSeoText("")
|
||||
product.SetSizetypecolor("")
|
||||
product.SetSku("")
|
||||
product.SetSlug("")
|
||||
product.SetTags([]string{""})
|
||||
product.SetWebsite("")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.16 - DO NOT EDIT.
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.18 - DO NOT EDIT.
|
||||
package testapi
|
||||
|
||||
import (
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.16 - DO NOT EDIT.
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.18 - DO NOT EDIT.
|
||||
package testapi
|
||||
|
||||
import "github.com/foomo/contentful"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.16 - DO NOT EDIT.
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.18 - DO NOT EDIT.
|
||||
package testapi
|
||||
|
||||
import (
|
||||
@ -227,6 +227,8 @@ func (cc *ContentfulClient) CacheHasContentType(contentTypeID string) bool {
|
||||
if cc.Cache == nil {
|
||||
return false
|
||||
}
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
defer cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
for _, cachedContentType := range cc.Cache.contentTypes {
|
||||
if cachedContentType == contentTypeID {
|
||||
return true
|
||||
@ -240,6 +242,8 @@ func (cc *ContentfulClient) ClientStats() {
|
||||
cc.logFn(nil, LogWarn, "ClientStats: no client available")
|
||||
return
|
||||
}
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
defer cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cc.logFn != nil {
|
||||
fieldsMap := map[string]interface{}{
|
||||
"space ID": cc.SpaceID,
|
||||
@ -252,7 +256,14 @@ func (cc *ContentfulClient) ClientStats() {
|
||||
if cc.cacheInit {
|
||||
fieldsMap["cache asset count"] = len(cc.Cache.assets)
|
||||
fieldsMap["cache entry count"] = len(cc.Cache.idContentTypeMap)
|
||||
fieldsMap["cache parentMap length"] = len(cc.Cache.parentMap)
|
||||
fieldsMap["cache parentMap children"] = len(cc.Cache.parentMap)
|
||||
cc.cacheMutex.parentMapGcLock.RLock()
|
||||
defer cc.cacheMutex.parentMapGcLock.RUnlock()
|
||||
referenceCount := 0
|
||||
for _, parents := range cc.Cache.parentMap {
|
||||
referenceCount += len(parents)
|
||||
}
|
||||
fieldsMap["cache parentMap parents"] = referenceCount
|
||||
}
|
||||
cc.logFn(fieldsMap, LogInfo, "Contentful ClientStats")
|
||||
}
|
||||
@ -300,10 +311,13 @@ func (cc *ContentfulClient) GetAssetByID(id string, forceNoCache ...bool) (*cont
|
||||
if cc == nil || cc.Client == nil {
|
||||
return nil, errors.New("GetAssetByID: No client available")
|
||||
}
|
||||
if cc.cacheInit && cc.Cache.assets != nil && (len(forceNoCache) == 0 || !forceNoCache[0]) {
|
||||
cc.cacheMutex.assetsGcLock.Lock()
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cacheInit := cc.cacheInit
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
cc.cacheMutex.assetsGcLock.Lock()
|
||||
defer cc.cacheMutex.assetsGcLock.Unlock()
|
||||
if cacheInit && cc.Cache.assets != nil && (len(forceNoCache) == 0 || !forceNoCache[0]) {
|
||||
asset, okAsset := cc.Cache.assets[id]
|
||||
cc.cacheMutex.assetsGcLock.Unlock()
|
||||
if okAsset {
|
||||
return asset, nil
|
||||
} else {
|
||||
@ -617,6 +631,8 @@ func (cc *ContentfulClient) SetOfflineFallback(filename string) error {
|
||||
}
|
||||
|
||||
func (cc *ContentfulClient) SetSyncMode(mode bool) error {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
defer cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cc.offline {
|
||||
return errors.New("SetSyncMode: client is set offline, can't enable sync")
|
||||
}
|
||||
@ -629,12 +645,16 @@ func (cc *ContentfulClient) ResetSync() {
|
||||
}
|
||||
|
||||
func (cc *ContentfulClient) UpdateCache(ctx context.Context, contentTypes []string, cacheAssets bool) error {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
ctxAtWork, cancel := context.WithTimeout(ctx, time.Second*time.Duration(cc.cacheUpdateTimeout))
|
||||
defer cancel()
|
||||
if cc.offline {
|
||||
localOffline := cc.offline
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
|
||||
if localOffline {
|
||||
ctxAtWork = ctx
|
||||
}
|
||||
if !cc.offline {
|
||||
if !localOffline {
|
||||
time.Sleep(time.Second * 2)
|
||||
}
|
||||
if contentTypes == nil {
|
||||
@ -681,7 +701,9 @@ func (cc *ContentfulClient) UpdateCache(ctx context.Context, contentTypes []stri
|
||||
|
||||
func (cc *ContentfulClient) syncCache(ctx context.Context, contentTypes []string) error {
|
||||
start := time.Now()
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cc.Cache.contentTypes = contentTypes
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
if cc.logFn != nil && cc.logLevel <= LogInfo {
|
||||
cc.logFn(map[string]interface{}{"task": "syncCache"}, LogInfo, InfoCacheUpdateQueued)
|
||||
}
|
||||
@ -692,8 +714,10 @@ func (cc *ContentfulClient) syncCache(ctx context.Context, contentTypes []string
|
||||
cc.syncToken,
|
||||
)
|
||||
col.GetAll()
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cc.syncToken = col.SyncToken
|
||||
cc.cacheInit = true
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
if len(col.Items) == 0 {
|
||||
if cc.logFn != nil && cc.logLevel <= LogInfo {
|
||||
cc.logFn(map[string]interface{}{"time elapsed": fmt.Sprint(time.Since(start)), "task": "syncCache"}, LogInfo, InfoUpdateCacheTime)
|
||||
@ -839,11 +863,25 @@ func (cc *ContentfulClient) cacheSpace(ctx context.Context, contentTypes []strin
|
||||
cc.logFn(map[string]interface{}{"time elapsed": fmt.Sprint(time.Since(start)), "task": "UpdateCache"}, LogInfo, InfoUpdateCacheTime)
|
||||
}
|
||||
cc.cacheMutex.fullCacheGcLock.Lock()
|
||||
defer cc.cacheMutex.fullCacheGcLock.Unlock()
|
||||
cc.Cache = tempCache
|
||||
cc.cacheMutex.sharedDataGcLock.Lock()
|
||||
cc.cacheMutex.assetsGcLock.Lock()
|
||||
cc.cacheMutex.idContentTypeMapGcLock.Lock()
|
||||
cc.cacheMutex.parentMapGcLock.Lock()
|
||||
cc.cacheMutex.brandGcLock.Lock()
|
||||
cc.cacheMutex.categoryGcLock.Lock()
|
||||
cc.cacheMutex.productGcLock.Lock()
|
||||
|
||||
cc.Cache = tempCache
|
||||
cc.offline = offlinePreviousState
|
||||
cc.cacheMutex.brandGcLock.Unlock()
|
||||
cc.cacheMutex.categoryGcLock.Unlock()
|
||||
cc.cacheMutex.productGcLock.Unlock()
|
||||
|
||||
cc.cacheMutex.parentMapGcLock.Unlock()
|
||||
cc.cacheMutex.idContentTypeMapGcLock.Unlock()
|
||||
cc.cacheMutex.assetsGcLock.Unlock()
|
||||
cc.cacheMutex.sharedDataGcLock.Unlock()
|
||||
cc.cacheMutex.fullCacheGcLock.Unlock()
|
||||
}
|
||||
|
||||
func ToAssetReference(asset *contentful.Asset) (refSys ContentTypeSys) {
|
||||
@ -966,12 +1004,17 @@ func (cc *ContentfulClient) getAllAssets(tryCacheFirst bool) (map[string]*conten
|
||||
if cc == nil || cc.Client == nil {
|
||||
return nil, errors.New("getAllAssets: No client available")
|
||||
}
|
||||
if cc.cacheInit && cc.Cache.assets != nil && tryCacheFirst {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
offline := cc.offline
|
||||
cacheInit := cc.cacheInit
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
|
||||
if cacheInit && cc.Cache.assets != nil && tryCacheFirst {
|
||||
return cc.Cache.assets, nil
|
||||
}
|
||||
allItems := []interface{}{}
|
||||
assets := map[string]*contentful.Asset{}
|
||||
if cc.offline {
|
||||
if offline {
|
||||
for _, asset := range cc.offlineTemp.Assets {
|
||||
allItems = append(allItems, asset)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.16 - DO NOT EDIT.
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.18 - DO NOT EDIT.
|
||||
package testapi
|
||||
|
||||
import (
|
||||
@ -22,10 +22,14 @@ func (cc *ContentfulClient) GetAllBrand() (voMap map[string]*CfBrand, err error)
|
||||
if cc == nil {
|
||||
return nil, errors.New("GetAllBrand: No client available")
|
||||
}
|
||||
if cc.cacheInit {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
cacheInit := cc.cacheInit
|
||||
optimisticPageSize := cc.optimisticPageSize
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cacheInit {
|
||||
return cc.Cache.entryMaps.brand, nil
|
||||
}
|
||||
col, err := cc.optimisticPageSizeGetAll("brand", cc.optimisticPageSize)
|
||||
col, err := cc.optimisticPageSizeGetAll("brand", optimisticPageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -800,9 +804,9 @@ func (cc *ContentfulClient) cacheBrandByID(ctx context.Context, id string, entry
|
||||
// delete as child
|
||||
delete(cc.Cache.parentMap, id)
|
||||
// delete as parent
|
||||
for childID, child := range cc.Cache.parentMap {
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range child {
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
@ -821,7 +825,22 @@ func (cc *ContentfulClient) cacheBrandByID(ctx context.Context, id string, entry
|
||||
}
|
||||
cc.Cache.entryMaps.brand[id] = brand
|
||||
cc.Cache.idContentTypeMap[id] = brand.Sys.ContentType.Sys.ID
|
||||
allChildrensIds := map[string]bool{}
|
||||
|
||||
_ = allChildrensIds // safety net
|
||||
// clean up child-parents that don't exist anymore
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
if _, isCollectedChildID := allChildrensIds[childID]; isCollectedChildID {
|
||||
continue
|
||||
}
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
}
|
||||
cc.Cache.parentMap[childID] = newParents
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.16 - DO NOT EDIT.
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.18 - DO NOT EDIT.
|
||||
package testapi
|
||||
|
||||
import (
|
||||
@ -22,10 +22,14 @@ func (cc *ContentfulClient) GetAllCategory() (voMap map[string]*CfCategory, err
|
||||
if cc == nil {
|
||||
return nil, errors.New("GetAllCategory: No client available")
|
||||
}
|
||||
if cc.cacheInit {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
cacheInit := cc.cacheInit
|
||||
optimisticPageSize := cc.optimisticPageSize
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cacheInit {
|
||||
return cc.Cache.entryMaps.category, nil
|
||||
}
|
||||
col, err := cc.optimisticPageSizeGetAll("category", cc.optimisticPageSize)
|
||||
col, err := cc.optimisticPageSizeGetAll("category", optimisticPageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -564,9 +568,9 @@ func (cc *ContentfulClient) cacheCategoryByID(ctx context.Context, id string, en
|
||||
// delete as child
|
||||
delete(cc.Cache.parentMap, id)
|
||||
// delete as parent
|
||||
for childID, child := range cc.Cache.parentMap {
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range child {
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
@ -585,7 +589,22 @@ func (cc *ContentfulClient) cacheCategoryByID(ctx context.Context, id string, en
|
||||
}
|
||||
cc.Cache.entryMaps.category[id] = category
|
||||
cc.Cache.idContentTypeMap[id] = category.Sys.ContentType.Sys.ID
|
||||
allChildrensIds := map[string]bool{}
|
||||
|
||||
_ = allChildrensIds // safety net
|
||||
// clean up child-parents that don't exist anymore
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
if _, isCollectedChildID := allChildrensIds[childID]; isCollectedChildID {
|
||||
continue
|
||||
}
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
}
|
||||
cc.Cache.parentMap[childID] = newParents
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.16 - DO NOT EDIT.
|
||||
// Code generated by https://github.com/foomo/gocontentful v1.0.18 - DO NOT EDIT.
|
||||
package testapi
|
||||
|
||||
import (
|
||||
@ -22,10 +22,14 @@ func (cc *ContentfulClient) GetAllProduct() (voMap map[string]*CfProduct, err er
|
||||
if cc == nil {
|
||||
return nil, errors.New("GetAllProduct: No client available")
|
||||
}
|
||||
if cc.cacheInit {
|
||||
cc.cacheMutex.sharedDataGcLock.RLock()
|
||||
cacheInit := cc.cacheInit
|
||||
optimisticPageSize := cc.optimisticPageSize
|
||||
cc.cacheMutex.sharedDataGcLock.RUnlock()
|
||||
if cacheInit {
|
||||
return cc.Cache.entryMaps.product, nil
|
||||
}
|
||||
col, err := cc.optimisticPageSizeGetAll("product", cc.optimisticPageSize)
|
||||
col, err := cc.optimisticPageSizeGetAll("product", optimisticPageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1326,9 +1330,9 @@ func (cc *ContentfulClient) cacheProductByID(ctx context.Context, id string, ent
|
||||
// delete as child
|
||||
delete(cc.Cache.parentMap, id)
|
||||
// delete as parent
|
||||
for childID, child := range cc.Cache.parentMap {
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range child {
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
@ -1347,11 +1351,13 @@ func (cc *ContentfulClient) cacheProductByID(ctx context.Context, id string, ent
|
||||
}
|
||||
cc.Cache.entryMaps.product[id] = product
|
||||
cc.Cache.idContentTypeMap[id] = product.Sys.ContentType.Sys.ID
|
||||
allChildrensIds := map[string]bool{}
|
||||
|
||||
for _, loc := range cc.locales {
|
||||
children, okChildren := product.Fields.Categories[string(loc)]
|
||||
if okChildren {
|
||||
for _, child := range children {
|
||||
allChildrensIds[child.Sys.ID] = true
|
||||
if cc.Cache.parentMap[child.Sys.ID] == nil {
|
||||
cc.Cache.parentMap[child.Sys.ID] = []EntryReference{}
|
||||
}
|
||||
@ -1371,6 +1377,7 @@ func (cc *ContentfulClient) cacheProductByID(ctx context.Context, id string, ent
|
||||
for _, loc := range cc.locales {
|
||||
child, okChild := product.Fields.Brand[string(loc)]
|
||||
if okChild {
|
||||
allChildrensIds[child.Sys.ID] = true
|
||||
if cc.Cache.parentMap[child.Sys.ID] == nil {
|
||||
cc.Cache.parentMap[child.Sys.ID] = []EntryReference{}
|
||||
}
|
||||
@ -1386,6 +1393,20 @@ func (cc *ContentfulClient) cacheProductByID(ctx context.Context, id string, ent
|
||||
}
|
||||
}
|
||||
|
||||
_ = allChildrensIds // safety net
|
||||
// clean up child-parents that don't exist anymore
|
||||
for childID, parents := range cc.Cache.parentMap {
|
||||
if _, isCollectedChildID := allChildrensIds[childID]; isCollectedChildID {
|
||||
continue
|
||||
}
|
||||
newParents := []EntryReference{}
|
||||
for _, parent := range parents {
|
||||
if parent.ID != id {
|
||||
newParents = append(newParents, parent)
|
||||
}
|
||||
}
|
||||
cc.Cache.parentMap[childID] = newParents
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user