More strings.Builder and io.Pipe

This commit is contained in:
Jan-Lukas Else 2023-01-24 14:30:53 +01:00
parent ffe7065621
commit e8a5e9eb0e
11 changed files with 68 additions and 96 deletions

View File

@ -13,7 +13,6 @@ import (
"github.com/samber/lo" "github.com/samber/lo"
"github.com/spf13/cast" "github.com/spf13/cast"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype" "go.goblog.app/app/pkgs/contenttype"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@ -76,14 +75,12 @@ func (a *goBlog) serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
a.serve404(w, r) a.serve404(w, r)
return return
} }
buf := bufferpool.Get() pr, pw := io.Pipe()
defer bufferpool.Put(buf) go func() {
if err := json.NewEncoder(buf).Encode(result); err != nil { _ = pw.CloseWithError(json.NewEncoder(pw).Encode(result))
a.serveError(w, r, "Failed to encode json", http.StatusInternalServerError) }()
return
}
w.Header().Set(contentType, contenttype.JSONUTF8) w.Header().Set(contentType, contenttype.JSONUTF8)
_ = a.min.Get().Minify(contenttype.JSON, w, buf) _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
} }
func (a *goBlog) getMicropubChannelsMap() []map[string]any { func (a *goBlog) getMicropubChannelsMap() []map[string]any {

View File

@ -5,29 +5,24 @@ import (
"io" "io"
"net/http" "net/http"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype" "go.goblog.app/app/pkgs/contenttype"
) )
func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) { func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) {
buf := bufferpool.Get() result := map[string]any{
defer bufferpool.Put(buf)
err := json.NewEncoder(buf).Encode(map[string]any{
"links": []map[string]any{ "links": []map[string]any{
{ {
"href": a.getFullAddress("/nodeinfo"), "href": a.getFullAddress("/nodeinfo"),
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.1", "rel": "http://nodeinfo.diaspora.software/ns/schema/2.1",
}, },
}, },
})
if err != nil {
a.serveError(w, r, "", http.StatusInternalServerError)
return
} }
pr, pw := io.Pipe()
go func() {
_ = pw.CloseWithError(json.NewEncoder(pw).Encode(result))
}()
w.Header().Set(contentType, contenttype.JSONUTF8) w.Header().Set(contentType, contenttype.JSONUTF8)
mw := a.min.Get().Writer(contenttype.JSON, w) _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
_, _ = io.Copy(mw, buf)
_ = mw.Close()
} }
func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) { func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
@ -35,9 +30,7 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
status: []postStatus{statusPublished}, status: []postStatus{statusPublished},
visibility: []postVisibility{visibilityPublic}, visibility: []postVisibility{visibilityPublic},
}) })
buf := bufferpool.Get() result := map[string]any{
defer bufferpool.Put(buf)
if err := json.NewEncoder(buf).Encode(map[string]any{
"version": "2.1", "version": "2.1",
"software": map[string]any{ "software": map[string]any{
"name": "goblog", "name": "goblog",
@ -55,10 +48,11 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
"webmention", "webmention",
}, },
"metadata": map[string]any{}, "metadata": map[string]any{},
}); err != nil {
a.serveError(w, r, "", http.StatusInternalServerError)
return
} }
pr, pw := io.Pipe()
go func() {
_ = pw.CloseWithError(json.NewEncoder(pw).Encode(result))
}()
w.Header().Set(contentType, contenttype.JSONUTF8) w.Header().Set(contentType, contenttype.JSONUTF8)
_ = a.min.Get().Minify(contenttype.JSON, w, buf) _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
} }

View File

@ -2,9 +2,9 @@ package main
import ( import (
"encoding/xml" "encoding/xml"
"io"
"net/http" "net/http"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype" "go.goblog.app/app/pkgs/contenttype"
) )
@ -49,15 +49,13 @@ func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
}, },
SearchForm: sURL, SearchForm: sURL,
} }
buf := bufferpool.Get() pr, pw := io.Pipe()
defer bufferpool.Put(buf) go func() {
_, _ = buf.WriteString(xml.Header) _, _ = io.WriteString(pw, xml.Header)
if err := xml.NewEncoder(buf).Encode(openSearch); err != nil { _ = pw.CloseWithError(xml.NewEncoder(pw).Encode(openSearch))
a.serveError(w, r, "", http.StatusInternalServerError) }()
return
}
w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix) w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix)
_ = a.min.Get().Minify(contenttype.XML, w, buf) _ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr))
} }
func openSearchUrl(b *configBlog) string { func openSearchUrl(b *configBlog) string {

View File

@ -2,13 +2,13 @@ package highlighting
import ( import (
"io" "io"
"strings"
"github.com/yuin/goldmark" "github.com/yuin/goldmark"
"github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer" "github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/renderer/html" "github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/util" "github.com/yuin/goldmark/util"
"go.goblog.app/app/pkgs/bufferpool"
"github.com/alecthomas/chroma/v2" "github.com/alecthomas/chroma/v2"
chromahtml "github.com/alecthomas/chroma/v2/formatters/html" chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
@ -60,8 +60,7 @@ func (r *htmlRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, no
n := node.(*ast.FencedCodeBlock) n := node.(*ast.FencedCodeBlock)
// Read code block content. // Read code block content.
buf := bufferpool.Get() var buf strings.Builder
defer bufferpool.Put(buf)
for _, line := range n.Lines().Sliced(0, n.Lines().Len()) { for _, line := range n.Lines().Sliced(0, n.Lines().Len()) {
buf.Write(line.Value(source)) buf.Write(line.Value(source))
} }
@ -70,7 +69,7 @@ func (r *htmlRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, no
if highlight(w, buf.String(), string(n.Language(source)), r.formatter) != nil { if highlight(w, buf.String(), string(n.Language(source)), r.formatter) != nil {
// Highlight failed, fallback to plain text. // Highlight failed, fallback to plain text.
_, _ = w.WriteString("<pre><code>") _, _ = w.WriteString("<pre><code>")
r.Writer.RawWrite(w, buf.Bytes()) r.Writer.RawWrite(w, []byte(buf.String()))
_, _ = w.WriteString("</code></pre>\n") _, _ = w.WriteString("</code></pre>\n")
} }

View File

@ -206,8 +206,7 @@ func (db *database) savePost(p *post, o *postCreationOptions) error {
db.pcm.Lock() db.pcm.Lock()
defer db.pcm.Unlock() defer db.pcm.Unlock()
// Build SQL // Build SQL
sqlBuilder := bufferpool.Get() var sqlBuilder strings.Builder
defer bufferpool.Put(sqlBuilder)
var sqlArgs = []any{dbNoCache} var sqlArgs = []any{dbNoCache}
// Start transaction // Start transaction
sqlBuilder.WriteString("begin;") sqlBuilder.WriteString("begin;")
@ -336,7 +335,7 @@ func (db *database) replacePostParam(path, param string, values []string) error
db.pcm.Lock() db.pcm.Lock()
defer db.pcm.Unlock() defer db.pcm.Unlock()
// Build SQL // Build SQL
sqlBuilder := bufferpool.Get() var sqlBuilder strings.Builder
var sqlArgs = []any{dbNoCache} var sqlArgs = []any{dbNoCache}
// Start transaction // Start transaction
sqlBuilder.WriteString("begin;") sqlBuilder.WriteString("begin;")
@ -352,7 +351,6 @@ func (db *database) replacePostParam(path, param string, values []string) error
sqlBuilder.WriteString("commit;") sqlBuilder.WriteString("commit;")
// Execute // Execute
_, err := db.Exec(sqlBuilder.String(), sqlArgs...) _, err := db.Exec(sqlBuilder.String(), sqlArgs...)
bufferpool.Put(sqlBuilder)
if err != nil { if err != nil {
return err return err
} }
@ -387,8 +385,7 @@ type postsRequestConfig struct {
} }
func buildPostsQuery(c *postsRequestConfig, selection string) (query string, args []any) { func buildPostsQuery(c *postsRequestConfig, selection string) (query string, args []any) {
queryBuilder := bufferpool.Get() var queryBuilder strings.Builder
defer bufferpool.Put(queryBuilder)
// Selection // Selection
queryBuilder.WriteString("select ") queryBuilder.WriteString("select ")
queryBuilder.WriteString(selection) queryBuilder.WriteString(selection)
@ -413,11 +410,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ") queryBuilder.WriteString(", ")
} }
named := "status" + strconv.Itoa(i) named := "status" + strconv.Itoa(i)
queryBuilder.WriteByte('@') queryBuilder.WriteString("@")
queryBuilder.WriteString(named) queryBuilder.WriteString(named)
args = append(args, sql.Named(named, status)) args = append(args, sql.Named(named, status))
} }
queryBuilder.WriteByte(')') queryBuilder.WriteString(")")
} }
if c.visibility != nil && len(c.visibility) > 0 { if c.visibility != nil && len(c.visibility) > 0 {
queryBuilder.WriteString(" and visibility in (") queryBuilder.WriteString(" and visibility in (")
@ -426,11 +423,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ") queryBuilder.WriteString(", ")
} }
named := "visibility" + strconv.Itoa(i) named := "visibility" + strconv.Itoa(i)
queryBuilder.WriteByte('@') queryBuilder.WriteString("@")
queryBuilder.WriteString(named) queryBuilder.WriteString(named)
args = append(args, sql.Named(named, visibility)) args = append(args, sql.Named(named, visibility))
} }
queryBuilder.WriteByte(')') queryBuilder.WriteString(")")
} }
if c.blog != "" { if c.blog != "" {
queryBuilder.WriteString(" and blog = @blog") queryBuilder.WriteString(" and blog = @blog")
@ -451,7 +448,7 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ") queryBuilder.WriteString(", ")
} }
named := "param" + strconv.Itoa(i) named := "param" + strconv.Itoa(i)
queryBuilder.WriteByte('@') queryBuilder.WriteString("@")
queryBuilder.WriteString(named) queryBuilder.WriteString(named)
args = append(args, param) args = append(args, param)
} }
@ -477,11 +474,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ") queryBuilder.WriteString(", ")
} }
named := "section" + strconv.Itoa(i) named := "section" + strconv.Itoa(i)
queryBuilder.WriteByte('@') queryBuilder.WriteString("@")
queryBuilder.WriteString(named) queryBuilder.WriteString(named)
args = append(args, sql.Named(named, section)) args = append(args, sql.Named(named, section))
} }
queryBuilder.WriteByte(')') queryBuilder.WriteString(")")
} }
if c.publishedYear != 0 { if c.publishedYear != 0 {
queryBuilder.WriteString(" and substr(tolocal(published), 1, 4) = @publishedyear") queryBuilder.WriteString(" and substr(tolocal(published), 1, 4) = @publishedyear")
@ -522,8 +519,7 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
} }
// Build query // Build query
sqlArgs := make([]any, 0) sqlArgs := make([]any, 0)
queryBuilder := bufferpool.Get() var queryBuilder strings.Builder
defer bufferpool.Put(queryBuilder)
queryBuilder.WriteString("select path, parameter, value from post_parameters where") queryBuilder.WriteString("select path, parameter, value from post_parameters where")
// Paths // Paths
queryBuilder.WriteString(" path in (") queryBuilder.WriteString(" path in (")
@ -532,11 +528,11 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
queryBuilder.WriteString(", ") queryBuilder.WriteString(", ")
} }
named := "path" + strconv.Itoa(i) named := "path" + strconv.Itoa(i)
queryBuilder.WriteByte('@') queryBuilder.WriteString("@")
queryBuilder.WriteString(named) queryBuilder.WriteString(named)
sqlArgs = append(sqlArgs, sql.Named(named, p.Path)) sqlArgs = append(sqlArgs, sql.Named(named, p.Path))
} }
queryBuilder.WriteByte(')') queryBuilder.WriteString(")")
// Parameters // Parameters
if len(parameters) > 0 { if len(parameters) > 0 {
queryBuilder.WriteString(" and parameter in (") queryBuilder.WriteString(" and parameter in (")
@ -545,11 +541,11 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
queryBuilder.WriteString(", ") queryBuilder.WriteString(", ")
} }
named := "param" + strconv.Itoa(i) named := "param" + strconv.Itoa(i)
queryBuilder.WriteByte('@') queryBuilder.WriteString("@")
queryBuilder.WriteString(named) queryBuilder.WriteString(named)
sqlArgs = append(sqlArgs, sql.Named(named, p)) sqlArgs = append(sqlArgs, sql.Named(named, p))
} }
queryBuilder.WriteByte(')') queryBuilder.WriteString(")")
} }
// Order // Order
queryBuilder.WriteString(" order by id") queryBuilder.WriteString(" order by id")
@ -695,7 +691,7 @@ group by name;
func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) { func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
sqlArgs := []any{dbNoCache} sqlArgs := []any{dbNoCache}
nameValues := bufferpool.Get() var nameValues strings.Builder
for i, n := range names { for i, n := range names {
if i > 0 { if i > 0 {
nameValues.WriteString(", ") nameValues.WriteString(", ")
@ -703,11 +699,10 @@ func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
named := "name" + strconv.Itoa(i) named := "name" + strconv.Itoa(i)
nameValues.WriteString("(@") nameValues.WriteString("(@")
nameValues.WriteString(named) nameValues.WriteString(named)
nameValues.WriteByte(')') nameValues.WriteString(")")
sqlArgs = append(sqlArgs, sql.Named(named, n)) sqlArgs = append(sqlArgs, sql.Named(named, n))
} }
rows, err := db.Query(fmt.Sprintf(mediaUseSql, nameValues.String()), sqlArgs...) rows, err := db.Query(fmt.Sprintf(mediaUseSql, nameValues.String()), sqlArgs...)
bufferpool.Put(nameValues)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,10 +5,10 @@ import (
"errors" "errors"
"io" "io"
"net/http" "net/http"
"strings"
"github.com/dgraph-io/ristretto" "github.com/dgraph-io/ristretto"
"github.com/samber/lo" "github.com/samber/lo"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype" "go.goblog.app/app/pkgs/contenttype"
) )
@ -88,15 +88,12 @@ func (a *goBlog) getReactions(w http.ResponseWriter, r *http.Request) {
a.serveError(w, r, "", http.StatusInternalServerError) a.serveError(w, r, "", http.StatusInternalServerError)
return return
} }
buf := bufferpool.Get() pr, pw := io.Pipe()
defer bufferpool.Put(buf) go func() {
err = json.NewEncoder(buf).Encode(reactions) _ = pw.CloseWithError(json.NewEncoder(pw).Encode(reactions))
if err != nil { }()
a.serveError(w, r, "", http.StatusInternalServerError)
return
}
w.Header().Set(contentType, contenttype.JSONUTF8) w.Header().Set(contentType, contenttype.JSONUTF8)
_, _ = io.Copy(w, buf) _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
} }
func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) { func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
@ -110,8 +107,7 @@ func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
// Get reactions // Get reactions
res, err, _ := a.reactionsSfg.Do(path, func() (any, error) { res, err, _ := a.reactionsSfg.Do(path, func() (any, error) {
// Build query // Build query
sqlBuf := bufferpool.Get() var sqlBuf strings.Builder
defer bufferpool.Put(sqlBuf)
sqlArgs := []any{} sqlArgs := []any{}
sqlBuf.WriteString("select reaction, count from reactions where path=? and reaction in (") sqlBuf.WriteString("select reaction, count from reactions where path=? and reaction in (")
sqlArgs = append(sqlArgs, path) sqlArgs = append(sqlArgs, path)

View File

@ -136,13 +136,13 @@ func Test_reactionsHighLevel(t *testing.T) {
rec = httptest.NewRecorder() rec = httptest.NewRecorder()
app.getReactions(rec, req) app.getReactions(rec, req)
assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, "{\"❤️\":1}\n", rec.Body.String()) assert.Equal(t, "{\"❤️\":1}", rec.Body.String())
// Get reactions for a non-existing post // Get reactions for a non-existing post
req = httptest.NewRequest(http.MethodGet, "/?path=/non-existing-post", nil) req = httptest.NewRequest(http.MethodGet, "/?path=/non-existing-post", nil)
rec = httptest.NewRecorder() rec = httptest.NewRecorder()
app.getReactions(rec, req) app.getReactions(rec, req)
assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, "{}\n", rec.Body.String()) assert.Equal(t, "{}", rec.Body.String())
} }

View File

@ -3,12 +3,12 @@ package main
import ( import (
"database/sql" "database/sql"
"encoding/xml" "encoding/xml"
"io"
"net/http" "net/http"
"time" "time"
"github.com/araddon/dateparse" "github.com/araddon/dateparse"
"github.com/snabb/sitemap" "github.com/snabb/sitemap"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype" "go.goblog.app/app/pkgs/contenttype"
) )
@ -174,18 +174,16 @@ func (a *goBlog) serveSitemapBlogPosts(w http.ResponseWriter, r *http.Request) {
} }
func (a *goBlog) writeSitemapXML(w http.ResponseWriter, r *http.Request, sm any) { func (a *goBlog) writeSitemapXML(w http.ResponseWriter, r *http.Request, sm any) {
buf := bufferpool.Get() pr, pw := io.Pipe()
defer bufferpool.Put(buf) go func() {
_, _ = buf.WriteString(xml.Header) _, _ = io.WriteString(pw, xml.Header)
_, _ = buf.WriteString(`<?xml-stylesheet type="text/xsl" href="`) _, _ = io.WriteString(pw, `<?xml-stylesheet type="text/xsl" href="`)
_, _ = buf.WriteString(a.assetFileName("sitemap.xsl")) _, _ = io.WriteString(pw, a.assetFileName("sitemap.xsl"))
_, _ = buf.WriteString(`" ?>`) _, _ = io.WriteString(pw, `" ?>`)
if err := xml.NewEncoder(buf).Encode(sm); err != nil { _ = pw.CloseWithError(xml.NewEncoder(pw).Encode(sm))
a.serveError(w, r, "Failed to encode sitemap", http.StatusInternalServerError) }()
return
}
w.Header().Set(contentType, contenttype.XMLUTF8) w.Header().Set(contentType, contenttype.XMLUTF8)
_ = a.min.Get().Minify(contenttype.XML, w, buf) _ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr))
} }
const sitemapDatePathsSql = ` const sitemapDatePathsSql = `

View File

@ -5,9 +5,9 @@ import (
"log" "log"
"net/url" "net/url"
"strconv" "strconv"
"strings"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"go.goblog.app/app/pkgs/bufferpool"
) )
func (a *goBlog) initTelegram() { func (a *goBlog) initTelegram() {
@ -135,8 +135,7 @@ func (tg *configTelegram) generateHTML(title, fullURL, shortURL string) (html st
if !tg.enabled() { if !tg.enabled() {
return "" return ""
} }
message := bufferpool.Get() var message strings.Builder
defer bufferpool.Put(message)
if title != "" { if title != "" {
message.WriteString(tgbotapi.EscapeText(tgbotapi.ModeHTML, title)) message.WriteString(tgbotapi.EscapeText(tgbotapi.ModeHTML, title))
message.WriteString("\n\n") message.WriteString("\n\n")

View File

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/samber/lo" "github.com/samber/lo"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/htmlbuilder" "go.goblog.app/app/pkgs/htmlbuilder"
) )
@ -65,7 +64,7 @@ func (a *goBlog) renderSummary(hb *htmlbuilder.HtmlBuilder, bc *configBlog, p *p
} }
// Show link to full post // Show link to full post
hb.WriteElementOpen("p") hb.WriteElementOpen("p")
prefix := bufferpool.Get() var prefix strings.Builder
if len(photos) > 0 { if len(photos) > 0 {
// Contains photos // Contains photos
prefix.WriteString("🖼️") prefix.WriteString("🖼️")
@ -75,10 +74,9 @@ func (a *goBlog) renderSummary(hb *htmlbuilder.HtmlBuilder, bc *configBlog, p *p
prefix.WriteString("🗺️") prefix.WriteString("🗺️")
} }
if prefix.Len() > 0 { if prefix.Len() > 0 {
prefix.WriteRune(' ') prefix.WriteString(" ")
hb.WriteEscaped(prefix.String()) hb.WriteEscaped(prefix.String())
} }
bufferpool.Put(prefix)
hb.WriteElementOpen("a", "class", "u-url", "href", p.Path) hb.WriteElementOpen("a", "class", "u-url", "href", p.Path)
hb.WriteEscaped(a.ts.GetTemplateStringVariant(bc.Lang, "view")) hb.WriteEscaped(a.ts.GetTemplateStringVariant(bc.Lang, "view"))
hb.WriteElementClose("a") hb.WriteElementClose("a")

View File

@ -8,7 +8,6 @@ import (
"strings" "strings"
"time" "time"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype" "go.goblog.app/app/pkgs/contenttype"
) )
@ -231,8 +230,7 @@ type webmentionsRequestConfig struct {
} }
func buildWebmentionsQuery(config *webmentionsRequestConfig) (query string, args []any) { func buildWebmentionsQuery(config *webmentionsRequestConfig) (query string, args []any) {
queryBuilder := bufferpool.Get() var queryBuilder strings.Builder
defer bufferpool.Put(queryBuilder)
queryBuilder.WriteString("select id, source, target, url, created, title, content, author, status from webmentions ") queryBuilder.WriteString("select id, source, target, url, created, title, content, author, status from webmentions ")
if config != nil { if config != nil {
queryBuilder.WriteString("where 1") queryBuilder.WriteString("where 1")