Skip to content

Commit

Permalink
only reload/re-index changed posts
Browse files Browse the repository at this point in the history
  • Loading branch information
quantonganh committed Dec 22, 2023
1 parent b42502a commit 3bc8e90
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 27 deletions.
146 changes: 124 additions & 22 deletions http/webhook.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
package http

import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"path"
"strings"

"github.com/quantonganh/blog"
"github.com/quantonganh/blog/markdown"
)

type webhookPayload struct {
Commits []struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp string `json:"timestamp"`
Added []string `json:"added"`
Removed []string `json:"removed"`
Modified []string `json:"modified"`
} `json:"commits"`
}

func (s *Server) webhookHandler(config *blog.Config) appHandler {
return func(w http.ResponseWriter, r *http.Request) error {
body, err := io.ReadAll(r.Body)
Expand All @@ -33,41 +45,31 @@ func (s *Server) webhookHandler(config *blog.Config) appHandler {
}
}

var payload webhookPayload
if err := json.Unmarshal(body, &payload); err != nil {
return err
}

addedPosts, removedFiles, modifiedPosts, err := getChangedPosts(config, payload)
if err != nil {
return err
}

cmd := exec.Command("git", "-C", config.Posts.Dir, "pull")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return err
}

posts, err := markdown.GetAllPosts(config.Posts.Dir)
if err != nil {
if err := s.reload(config, addedPosts, removedFiles, modifiedPosts); err != nil {
return err
}
s.reload(config, posts)

return nil
}
}

func (s *Server) reload(config *blog.Config, posts []*blog.Post) {
if s.PostService != nil {
s.PostService = markdown.NewPostService(posts)
}

if s.SearchService != nil {
indexPath := path.Join(path.Dir(config.Posts.Dir), path.Base(config.Posts.Dir)+".bleve")
searchService, err := markdown.NewSearchService(indexPath, posts)
if err != nil {
log.Printf("Failed to reload search service: %v\n", err)
return
}
s.SearchService = searchService
}

log.Println("Content reloaded successfully.")
}

func verifySignature(signature string, payload []byte, secret string) error {
parts := strings.SplitN(signature, "=", 2)
if len(parts) != 2 {
Expand All @@ -92,3 +94,103 @@ func verifySignature(signature string, payload []byte, secret string) error {

return nil
}

func getChangedPosts(config *blog.Config, payload webhookPayload) ([]*blog.Post, []string, []*blog.Post, error) {
var (
addedFiles []string
removedFiles []string
modifiedFiles []string
)
for _, commit := range payload.Commits {
addedFiles = append(addedFiles, commit.Added...)
removedFiles = append(removedFiles, commit.Removed...)
modifiedFiles = append(modifiedFiles, commit.Modified...)
}

var (
addedPosts []*blog.Post
modifiedPosts []*blog.Post
)
for _, name := range addedFiles {
f, err := os.Open(name)
if err != nil {
return nil, nil, nil, err
}

newPost, err := markdown.Parse(context.Background(), config.Posts.Dir, f)
if err != nil {
return nil, nil, nil, err
}

addedPosts = append(addedPosts, newPost)
}

for _, name := range modifiedFiles {
f, err := os.Open(name)
if err != nil {
return nil, nil, nil, err
}

modifiedPost, err := markdown.Parse(context.Background(), config.Posts.Dir, f)
if err != nil {
return nil, nil, nil, err
}

modifiedPosts = append(modifiedPosts, modifiedPost)
}

return addedPosts, removedFiles, modifiedPosts, nil
}

func (s *Server) reload(config *blog.Config, addedPosts []*blog.Post, removedFiles []string, modifiedPosts []*blog.Post) error {
if s.PostService != nil {
posts := s.PostService.GetAllPosts()
updatedPosts, err := updatePosts(config, posts, addedPosts, removedFiles, modifiedPosts)
if err != nil {
return err
}
s.PostService = markdown.NewPostService(updatedPosts)
}

if s.SearchService != nil {
index := s.SearchService.GetIndex()
batch := index.NewBatch()

for _, name := range removedFiles {
if err := index.Delete(name); err != nil {
return err
}
}

for _, post := range append(addedPosts, modifiedPosts...) {
if err := s.SearchService.Index(post, batch); err != nil {
return err
}
}
}

log.Println("Content reloaded successfully.")
return nil
}

func updatePosts(config *blog.Config, posts []*blog.Post, addedPosts []*blog.Post, removedFiles []string, modifiedPosts []*blog.Post) ([]*blog.Post, error) {
posts = append(posts, addedPosts...)

for _, name := range removedFiles {
for i, post := range posts {
if post.URI == name {
posts = append(posts[:i], posts[i+1:]...)
}
}
}

for _, p := range modifiedPosts {
for i, post := range posts {
if post.URI == p.URI {
posts[i] = p
}
}
}

return posts, nil
}
15 changes: 10 additions & 5 deletions markdown/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@ func NewSearchService(indexPath string, posts []*blog.Post) (blog.SearchService,
}
}

ss := &searchService{
index: index,
}
batch := index.NewBatch()
for i, post := range posts {
post.ID = i

if err := indexPost(post, batch); err != nil {
if err := ss.Index(post, batch); err != nil {
return nil, err
}
}
Expand All @@ -50,12 +53,14 @@ func NewSearchService(indexPath string, posts []*blog.Post) (blog.SearchService,
return nil, errors.Wrapf(err, "failed to index batch")
}

return &searchService{
index: index,
}, nil
return ss, nil
}

func (ss *searchService) GetIndex() bleve.Index {
return ss.index
}

func indexPost(post *blog.Post, batch *bleve.Batch) error {
func (ss *searchService) Index(post *blog.Post, batch *bleve.Batch) error {
doc := document.Document{
ID: post.URI,
}
Expand Down
3 changes: 3 additions & 0 deletions post.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strconv"
"time"

"github.com/blevesearch/bleve"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -36,6 +37,8 @@ type PostService interface {

// SearchService is the interface that wraps methods related to search
type SearchService interface {
GetIndex() bleve.Index
Index(*Post, *bleve.Batch) error
Search(value string) ([]*Post, error)
CloseIndex() error
}
Expand Down

0 comments on commit 3bc8e90

Please sign in to comment.