diff options
author | Bjørn Erik Pedersen <[email protected]> | 2024-05-03 11:04:57 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2024-05-04 19:45:43 +0200 |
commit | 503d20954f10507b9b43c6ee1c38001e53cf0b14 (patch) | |
tree | 06e1aeddd995c2b8ff2fb48c0879187b2b819e4b /hugolib | |
parent | 68e95327f7be941c44c256d2dac74ea96e731674 (diff) | |
download | hugo-503d20954f10507b9b43c6ee1c38001e53cf0b14.tar.gz hugo-503d20954f10507b9b43c6ee1c38001e53cf0b14.zip |
Make the cache eviction logic for stale entities more robust
Fixes #12458
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/content_map_page.go | 12 | ||||
-rw-r--r-- | hugolib/page__content.go | 29 | ||||
-rw-r--r-- | hugolib/page__per_output.go | 4 | ||||
-rw-r--r-- | hugolib/rebuild_test.go | 28 | ||||
-rw-r--r-- | hugolib/rendershortcodes_test.go | 37 | ||||
-rw-r--r-- | hugolib/site_benchmark_new_test.go | 2 |
6 files changed, 88 insertions, 24 deletions
diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go index 5a6b49c55..a0bff7472 100644 --- a/hugolib/content_map_page.go +++ b/hugolib/content_map_page.go @@ -824,10 +824,10 @@ func (s *contentNodeShifter) Insert(old, new contentNodeI) contentNodeI { if !ok { panic(fmt.Sprintf("unknown type %T", new)) } - if newp != old { - resource.MarkStale(old) - } if vv.s.languagei == newp.s.languagei { + if newp != old { + resource.MarkStale(old) + } return new } is := make(contentNodeIs, s.numLanguages) @@ -843,7 +843,6 @@ func (s *contentNodeShifter) Insert(old, new contentNodeI) contentNodeI { if oldp != newp { resource.MarkStale(oldp) } - vv[newp.s.languagei] = new return vv case *resourceSource: @@ -852,6 +851,9 @@ func (s *contentNodeShifter) Insert(old, new contentNodeI) contentNodeI { panic(fmt.Sprintf("unknown type %T", new)) } if vv.LangIndex() == newp.LangIndex() { + if vv != newp { + resource.MarkStale(vv) + } return new } rs := make(resourceSources, s.numLanguages) @@ -1064,7 +1066,7 @@ func (h *HugoSites) resolveAndClearStateForIdentities( ) for _, id := range changes { - if staler, ok := id.(resource.Staler); ok && !staler.IsStale() { + if staler, ok := id.(resource.Staler); ok { var msgDetail string if p, ok := id.(*pageState); ok && p.File() != nil { msgDetail = fmt.Sprintf(" (%s)", p.File().Filename()) diff --git a/hugolib/page__content.go b/hugolib/page__content.go index f10c25d7b..99ed824cd 100644 --- a/hugolib/page__content.go +++ b/hugolib/page__content.go @@ -418,6 +418,8 @@ func (c *cachedContent) mustSource() []byte { func (c *contentParseInfo) contentSource(s resource.StaleInfo) ([]byte, error) { key := c.sourceKey + versionv := s.StaleVersion() + v, err := c.h.cacheContentSource.GetOrCreate(key, func(string) (*resources.StaleValue[[]byte], error) { b, err := c.readSourceAll() if err != nil { @@ -426,8 +428,8 @@ func (c *contentParseInfo) contentSource(s resource.StaleInfo) ([]byte, error) { return &resources.StaleValue[[]byte]{ Value: b, - IsStaleFunc: func() bool { - return s.IsStale() + StaleVersionFunc: func() uint32 { + return s.StaleVersion() - versionv }, }, nil }) @@ -487,7 +489,7 @@ type contentPlainPlainWords struct { func (c *cachedContent) contentRendered(ctx context.Context, cp *pageContentOutput) (contentSummary, error) { ctx = tpl.Context.DependencyScope.Set(ctx, pageDependencyScopeGlobal) key := c.pi.sourceKey + "/" + cp.po.f.Name - versionv := cp.contentRenderedVersion + versionv := c.version(cp) v, err := c.pm.cacheContentRendered.GetOrCreate(key, func(string) (*resources.StaleValue[contentSummary], error) { cp.po.p.s.Log.Trace(logg.StringFunc(func() string { @@ -504,8 +506,8 @@ func (c *cachedContent) contentRendered(ctx context.Context, cp *pageContentOutp } rs := &resources.StaleValue[contentSummary]{ - IsStaleFunc: func() bool { - return c.IsStale() || cp.contentRenderedVersion != versionv + StaleVersionFunc: func() uint32 { + return c.version(cp) - versionv }, } @@ -607,7 +609,7 @@ var setGetContentCallbackInContext = hcontext.NewContextDispatcher[func(*pageCon func (c *cachedContent) contentToC(ctx context.Context, cp *pageContentOutput) (contentTableOfContents, error) { key := c.pi.sourceKey + "/" + cp.po.f.Name - versionv := cp.contentRenderedVersion + versionv := c.version(cp) v, err := c.pm.contentTableOfContents.GetOrCreate(key, func(string) (*resources.StaleValue[contentTableOfContents], error) { source, err := c.pi.contentSource(c) @@ -713,8 +715,8 @@ func (c *cachedContent) contentToC(ctx context.Context, cp *pageContentOutput) ( return &resources.StaleValue[contentTableOfContents]{ Value: ct, - IsStaleFunc: func() bool { - return c.IsStale() || cp.contentRenderedVersion != versionv + StaleVersionFunc: func() uint32 { + return c.version(cp) - versionv }, }, nil }) @@ -725,16 +727,21 @@ func (c *cachedContent) contentToC(ctx context.Context, cp *pageContentOutput) ( return v.Value, nil } +func (c *cachedContent) version(cp *pageContentOutput) uint32 { + // Both of these gets incremented on change. + return c.StaleVersion() + cp.contentRenderedVersion +} + func (c *cachedContent) contentPlain(ctx context.Context, cp *pageContentOutput) (contentPlainPlainWords, error) { key := c.pi.sourceKey + "/" + cp.po.f.Name - versionv := cp.contentRenderedVersion + versionv := c.version(cp) v, err := c.pm.cacheContentPlain.GetOrCreateWitTimeout(key, cp.po.p.s.Conf.Timeout(), func(string) (*resources.StaleValue[contentPlainPlainWords], error) { var result contentPlainPlainWords rs := &resources.StaleValue[contentPlainPlainWords]{ - IsStaleFunc: func() bool { - return c.IsStale() || cp.contentRenderedVersion != versionv + StaleVersionFunc: func() uint32 { + return c.version(cp) - versionv }, } diff --git a/hugolib/page__per_output.go b/hugolib/page__per_output.go index 2adb5cbb7..6b4b8f55e 100644 --- a/hugolib/page__per_output.go +++ b/hugolib/page__per_output.go @@ -89,8 +89,8 @@ type pageContentOutput struct { // typically included with .RenderShortcodes. otherOutputs map[uint64]*pageContentOutput - contentRenderedVersion int // Incremented on reset. - contentRendered bool // Set on content render. + contentRenderedVersion uint32 // Incremented on reset. + contentRendered bool // Set on content render. // Renders Markdown hooks. renderHooks *renderHooks diff --git a/hugolib/rebuild_test.go b/hugolib/rebuild_test.go index 542810b64..0db418ee1 100644 --- a/hugolib/rebuild_test.go +++ b/hugolib/rebuild_test.go @@ -53,6 +53,11 @@ title: "Home" Home Content. -- content/hometext.txt -- Home Text Content. +-- content/myothersection/myothersectionpage.md -- +--- +title: "myothersectionpage" +--- +myothersectionpage Content. -- layouts/_default/single.html -- Single: {{ .Title }}|{{ .Content }}$ Resources: {{ range $i, $e := .Resources }}{{ $i }}:{{ .RelPermalink }}|{{ .Content }}|{{ end }}$ @@ -135,8 +140,8 @@ func TestRebuildRenameTextFileInLeafBundle(t *testing.T) { b.RenameFile("content/mysection/mysectionbundle/mysectionbundletext.txt", "content/mysection/mysectionbundle/mysectionbundletext2.txt").Build() b.AssertFileContent("public/mysection/mysectionbundle/index.html", "mysectionbundletext2", "My Section Bundle Text 2 Content.", "Len Resources: 2|") - b.AssertRenderCountPage(3) - b.AssertRenderCountContent(3) + b.AssertRenderCountPage(5) + b.AssertRenderCountContent(6) }) } @@ -147,6 +152,19 @@ func TestRebuilEditContentFileInLeafBundle(t *testing.T) { b.AssertFileContent("public/mysection/mysectionbundle/index.html", "My Section Bundle Content Content Edited.") } +func TestRebuilEditContentFileThenAnother(t *testing.T) { + b := TestRunning(t, rebuildFilesSimple) + b.EditFileReplaceAll("content/mysection/mysectionbundle/mysectionbundlecontent.md", "Content Content.", "Content Content Edited.").Build() + b.AssertFileContent("public/mysection/mysectionbundle/index.html", "My Section Bundle Content Content Edited.") + b.AssertRenderCountPage(1) + b.AssertRenderCountContent(2) + + b.EditFileReplaceAll("content/myothersection/myothersectionpage.md", "myothersectionpage Content.", "myothersectionpage Content Edited.").Build() + b.AssertFileContent("public/myothersection/myothersectionpage/index.html", "myothersectionpage Content Edited") + b.AssertRenderCountPage(1) + b.AssertRenderCountContent(1) +} + func TestRebuildRenameTextFileInBranchBundle(t *testing.T) { b := TestRunning(t, rebuildFilesSimple) b.AssertFileContent("public/mysection/index.html", "My Section") @@ -163,7 +181,7 @@ func TestRebuildRenameTextFileInHomeBundle(t *testing.T) { b.RenameFile("content/hometext.txt", "content/hometext2.txt").Build() b.AssertFileContent("public/index.html", "hometext2", "Home Text Content.") - b.AssertRenderCountPage(2) + b.AssertRenderCountPage(3) } func TestRebuildRenameDirectoryWithLeafBundle(t *testing.T) { @@ -179,7 +197,7 @@ func TestRebuildRenameDirectoryWithBranchBundle(t *testing.T) { b.AssertFileContent("public/mysectionrenamed/index.html", "My Section") b.AssertFileContent("public/mysectionrenamed/mysectionbundle/index.html", "My Section Bundle") b.AssertFileContent("public/mysectionrenamed/mysectionbundle/mysectionbundletext.txt", "My Section Bundle Text 2 Content.") - b.AssertRenderCountPage(2) + b.AssertRenderCountPage(3) } func TestRebuildRenameDirectoryWithRegularPageUsedInHome(t *testing.T) { @@ -278,7 +296,7 @@ func TestRebuildRenameDirectoryWithBranchBundleFastRender(t *testing.T) { b.AssertFileContent("public/mysectionrenamed/index.html", "My Section") b.AssertFileContent("public/mysectionrenamed/mysectionbundle/index.html", "My Section Bundle") b.AssertFileContent("public/mysectionrenamed/mysectionbundle/mysectionbundletext.txt", "My Section Bundle Text 2 Content.") - b.AssertRenderCountPage(2) + b.AssertRenderCountPage(3) } func TestRebuilErrorRecovery(t *testing.T) { diff --git a/hugolib/rendershortcodes_test.go b/hugolib/rendershortcodes_test.go index 67b1a85ef..313c80a73 100644 --- a/hugolib/rendershortcodes_test.go +++ b/hugolib/rendershortcodes_test.go @@ -201,6 +201,43 @@ Myshort Original. b.AssertFileContent("public/p1/index.html", "Edited") } +func TestRenderShortcodesEditSectionContentWithShortcodeInIncludedPageIssue12458(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +disableLiveReload = true +disableKinds = ["home", "taxonomy", "term", "rss", "sitemap", "robotsTXT", "404"] +-- content/mysection/_index.md -- +--- +title: "My Section" +--- +## p1-h1 +{{% include "p2" %}} +-- content/mysection/p2.md -- +--- +title: "p2" +--- +### Original +{{% myshort %}} +-- layouts/shortcodes/include.html -- +{{ $p := .Page.GetPage (.Get 0) }} +{{ $p.RenderShortcodes }} +-- layouts/shortcodes/myshort.html -- +Myshort Original. +-- layouts/_default/list.html -- + {{ .Content }} + + + +` + b := TestRunning(t, files) + + b.AssertFileContent("public/mysection/index.html", "p1-h1") + b.EditFileReplaceAll("content/mysection/_index.md", "p1-h1", "p1-h1 Edited").Build() + b.AssertFileContent("public/mysection/index.html", "p1-h1 Edited") +} + func TestRenderShortcodesNestedPageContextIssue12356(t *testing.T) { t.Parallel() diff --git a/hugolib/site_benchmark_new_test.go b/hugolib/site_benchmark_new_test.go index c028ca526..023d8e4d5 100644 --- a/hugolib/site_benchmark_new_test.go +++ b/hugolib/site_benchmark_new_test.go @@ -487,7 +487,7 @@ Edited!!`, p.Title())) // We currently rebuild all the language versions of the same content file. // We could probably optimize that case, but it's not trivial. - b.Assert(int(counters.contentRenderCounter.Load()), qt.Equals, 33) + b.Assert(int(counters.contentRenderCounter.Load()), qt.Equals, 4) b.AssertFileContent("public"+p.RelPermalink()+"index.html", "Edited!!") } |