feat(19.3-04): cooler site-cache purge service with site_cache.purge_url and purge_token
- cooler.SiteCachePurger moved from the Journal plugin: loopback-only http, 32-character token, 2 s detached request, no token in logs or errors - NewSiteCachePurgerFor names caller keys (for plugin alias keys) - PurgeSiteCacheAfterCommit through lagoon.AfterCommit, one POST per save - SiteCacheFromApp for hooks outside serve; Install publishes the purger unless a plugin already did, and fails boot on an invalid config - caching docs section, cooler README, configuration row
This commit is contained in:
@@ -4,10 +4,17 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/backpack"
|
||||
"git.golem15.com/golem15/summercms/modules/cabana"
|
||||
"git.golem15.com/golem15/summercms/modules/compass"
|
||||
"git.golem15.com/golem15/summercms/modules/cooler"
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
)
|
||||
|
||||
func ExampleFromApp() {
|
||||
@@ -40,3 +47,79 @@ func ExampleFromApp() {
|
||||
fmt.Println(titles, loads)
|
||||
// Output: [Hello Summer] 1
|
||||
}
|
||||
|
||||
// Article is a blog's article model.
|
||||
type Article struct {
|
||||
Slug string
|
||||
}
|
||||
|
||||
// articlesController is a blog's admin controller (its pact.AdminController
|
||||
// methods are left out here).
|
||||
type articlesController struct {
|
||||
app func() *backpack.App
|
||||
}
|
||||
|
||||
// purge registers one site-cache purge for the saved article, sent after the
|
||||
// save transaction commits (at once outside one). Without a purge configured
|
||||
// the purger is nil and nothing is sent.
|
||||
func (c articlesController) purge(ctx context.Context, model any) error {
|
||||
article, ok := model.(*Article)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
tx, _ := cabana.TxFromContext(ctx)
|
||||
cooler.PurgeSiteCacheAfterCommit(ctx, tx, cooler.SiteCacheFromApp(c.app()), "article", article.Slug)
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormAfterCreate runs inside the create's transaction.
|
||||
func (c articlesController) FormAfterCreate(ctx context.Context, model any) error {
|
||||
return c.purge(ctx, model)
|
||||
}
|
||||
|
||||
// FormAfterUpdate runs inside the update's transaction.
|
||||
func (c articlesController) FormAfterUpdate(ctx context.Context, model any) error {
|
||||
return c.purge(ctx, model)
|
||||
}
|
||||
|
||||
// FormAfterDelete runs inside the delete's transaction.
|
||||
func (c articlesController) FormAfterDelete(ctx context.Context, model any) error {
|
||||
return c.purge(ctx, model)
|
||||
}
|
||||
|
||||
var (
|
||||
_ pact.FormAfterCreate = articlesController{}
|
||||
_ pact.FormAfterUpdate = articlesController{}
|
||||
_ pact.FormAfterDelete = articlesController{}
|
||||
)
|
||||
|
||||
func ExampleSiteCacheFromApp() {
|
||||
// The host site's purge route, standing in on loopback.
|
||||
site := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
fmt.Println(r.Method, r.URL.Path, string(body))
|
||||
_, _ = w.Write([]byte(`{"purged":3}`))
|
||||
}))
|
||||
defer site.Close()
|
||||
|
||||
dir, err := os.MkdirTemp("", "cooler-example")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
cfg, err := compass.Open(compass.Options{Dir: dir, Environ: []string{
|
||||
"SUMMER_SITE_CACHE__PURGE_URL=" + site.URL + "/api/__site__/cache/purge",
|
||||
"SUMMER_SITE_CACHE__PURGE_TOKEN=example-purge-token-0123456789abcdef",
|
||||
}})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
app := backpack.New(cfg)
|
||||
c := articlesController{app: func() *backpack.App { return app }}
|
||||
if err := c.FormAfterUpdate(context.Background(), &Article{Slug: "hello-summer"}); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output: POST /api/__site__/cache/purge {"kind":"article","slug":"hello-summer"}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user