Compare commits

..

5 Commits

Author SHA1 Message Date
da11811e2d Problem: indexing search objects is slow
All checks were successful
continuous-integration/drone/push Build is passing
Solution: batch indexing search objects
2022-05-26 21:18:19 +02:00
19183da0f8 Problem: block repo did not serialize writes
Solution: serialize writes
2022-05-26 21:17:51 +02:00
1acd0e5f0f Problem: gitRevision does not handle errors
Solution: handle errors in gitRevision
2022-05-01 22:11:58 +02:00
3ee280a124 Problem: can't fetch a block with the API
Solution: add route to fetch a single with the API
2022-05-01 22:01:53 +02:00
726f3c944b Problem: negative branch was first
Solution: positive branch is first
2022-05-01 22:01:27 +02:00
4 changed files with 103 additions and 18 deletions

View File

@ -25,23 +25,56 @@ import (
) )
type BlockRepository interface { type BlockRepository interface {
Save(block Block) error Save(id string, block Block) error
Load(id string) (Block, error) Load(id string) (Block, error)
} }
type blockSaveMessage struct {
id string
block Block
}
type blockRepo struct { type blockRepo struct {
dirname string dirname string
saveC chan blockSaveMessage
errC chan error
} }
func (br *blockRepo) Save(id string, block Block) error { func saveBlock(dirname, id string, block Block) error {
f, err := os.OpenFile(filepath.Join(br.dirname, BlocksDirectory, id), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) f, err := os.OpenFile(filepath.Join(dirname, BlocksDirectory, id), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
defer f.Close()
if err != nil { if err != nil {
return err return err
} }
defer f.Close()
enc := json.NewEncoder(f) enc := json.NewEncoder(f)
enc.SetIndent("", " ") enc.SetIndent("", " ")
return enc.Encode(&block) err = enc.Encode(&block)
if err != nil {
return err
}
return nil
}
func NewBlockRepo(dirname string) BlockRepository {
saveC := make(chan blockSaveMessage, 1)
errC := make(chan error)
go func() {
for msg := range saveC {
err := saveBlock(dirname, msg.id, msg.block)
errC <- err
}
}()
return &blockRepo{
dirname: dirname,
saveC: saveC,
errC: errC,
}
}
func (br *blockRepo) Save(id string, block Block) error {
br.saveC <- blockSaveMessage{id, block}
err := <-br.errC
return err
} }
func (br *blockRepo) Load(id string) (Block, error) { func (br *blockRepo) Load(id string) (Block, error) {

20
file.go
View File

@ -337,14 +337,19 @@ func (fp *FilePages) save(msg saveMessage) error {
if err != nil { if err != nil {
return fmt.Errorf("while creating search object %s: %w", page.Name, err) return fmt.Errorf("while creating search object %s: %w", page.Name, err)
} }
batch := fp.index.NewBatch()
for _, so := range searchObjects { for _, so := range searchObjects {
if fp.index != nil { if fp.index != nil {
err = fp.index.Index(so.ID, so) err = batch.Index(so.ID, so)
if err != nil { if err != nil {
return fmt.Errorf("while indexing %s: %w", page.Name, err) return fmt.Errorf("while indexing %s: %w", page.Name, err)
} }
} }
} }
err = fp.index.Batch(batch)
if err != nil {
return fmt.Errorf("while indexing %s: %w", page.Name, err)
}
sw.Stop() sw.Stop()
sw.Start("links") sw.Start("links")
err = saveLinksIncremental(fp.dirname, page.Title) err = saveLinksIncremental(fp.dirname, page.Title)
@ -699,6 +704,9 @@ func (fp *FilePages) PageHistory(p string) ([]Revision, error) {
commitId := line[0:start] commitId := line[0:start]
rest := line[start+1:] rest := line[start+1:]
pageText := gitRevision(fp.dirname, page, commitId) pageText := gitRevision(fp.dirname, page, commitId)
if pageText == "" {
return nil, errors.New("git revision failed")
}
revisions = append(revisions, Revision{ revisions = append(revisions, Revision{
Version: commitId, Version: commitId,
Page: DiffPage{Content: pageText}, Page: DiffPage{Content: pageText},
@ -727,8 +735,14 @@ func gitRevision(dirname, page, version string) string {
cmd.Dir = dirname cmd.Dir = dirname
buf := bytes.Buffer{} buf := bytes.Buffer{}
cmd.Stdout = &buf cmd.Stdout = &buf
cmd.Start() err := cmd.Start()
cmd.Wait() if err != nil {
return ""
}
err = cmd.Wait()
if err != nil {
return ""
}
return buf.String() return buf.String()
} }

View File

@ -203,10 +203,10 @@ function Store(inputData) {
function updateFold(id, open) { function updateFold(id, open) {
let closedFolds = JSON.parse(localStorage.getItem("closed-folds") || '{}') || {} let closedFolds = JSON.parse(localStorage.getItem("closed-folds") || '{}') || {}
if (!open) { if (open) {
closedFolds[id] = true
} else {
delete closedFolds[id] delete closedFolds[id]
} else {
closedFolds[id] = true
} }
localStorage.setItem('closed-folds', JSON.stringify(closedFolds)) localStorage.setItem('closed-folds', JSON.stringify(closedFolds))
} }

52
main.go
View File

@ -37,7 +37,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/davecgh/go-spew/spew"
"p83.nl/go/ekster/pkg/util" "p83.nl/go/ekster/pkg/util"
"p83.nl/go/indieauth" "p83.nl/go/indieauth"
"p83.nl/go/wiki/link" "p83.nl/go/wiki/link"
@ -1064,8 +1063,39 @@ func main() {
} }
mp = NewFilePages(dataDir, searchIndex) mp = NewFilePages(dataDir, searchIndex)
repo := NewBlockRepo("data")
http.Handle("/auth/", &authHandler{}) http.Handle("/auth/", &authHandler{})
http.HandleFunc("/api/block/view", wrapAuth(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if !r.Context().Value(authKey).(bool) {
http.Error(w, "Unauthorized", 401)
return
}
if r.Method != "GET" {
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
return
}
id := r.URL.Query().Get("id")
block, err := repo.Load(id)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "no-store")
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
err = enc.Encode(block)
if err != nil {
http.Error(w, err.Error(), 500)
}
}))
http.HandleFunc("/api/block/", wrapAuth(func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/api/block/", wrapAuth(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close() defer r.Body.Close()
@ -1134,7 +1164,6 @@ func main() {
http.Error(w, "missing id", 400) http.Error(w, "missing id", 400)
return return
} }
repo := blockRepo{dirname: "data"}
block, err := repo.Load(id) block, err := repo.Load(id)
block.Text = r.Form.Get("text") block.Text = r.Form.Get("text")
err = repo.Save(id, block) err = repo.Save(id, block)
@ -1165,9 +1194,6 @@ func main() {
http.Error(w, "missing id", 400) http.Error(w, "missing id", 400)
return return
} }
repo := blockRepo{
dirname: "data",
}
newBlock := Block{ newBlock := Block{
Text: r.Form.Get("text"), Text: r.Form.Get("text"),
Children: []string{}, Children: []string{},
@ -1181,13 +1207,25 @@ func main() {
err = repo.Save(id, block) err = repo.Save(id, block)
// update search index // update search index
sw := stopwatch{}
sw.Start("createSearchObjects")
searchObjects, err := createSearchObjects(id) searchObjects, err := createSearchObjects(id)
spew.Dump("searchObjects", searchObjects)
batch := searchIndex.NewBatch()
for _, so := range searchObjects { for _, so := range searchObjects {
searchIndex.Index(so.ID, so) err = batch.Index(so.ID, so)
if err != nil {
log.Println(err)
}
} }
err = searchIndex.Batch(batch)
if err != nil {
log.Println(err)
}
sw.Stop()
return return
})) }))
http.HandleFunc("/links.json", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/links.json", func(w http.ResponseWriter, r *http.Request) {