cache

package
v0.0.0-...-1a9902f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2020 License: AGPL-3.0, AGPL-3.0-or-later Imports: 10 Imported by: 0

Documentation

Overview

Package cache provides an in-memory LRU cache for reducing the duplicate workload of database requests and post HTML and JSON generation

Index

Constants

This section is empty.

Variables

View Source
var BoardFE = FrontEnd{
	GetCounter: func(k Key) (uint64, error) {
		if k.Board == "all" {
			return db.AllBoardCounter()
		}
		return db.BoardCounter(k.Board)
	},

	GetFresh: func(k Key) (interface{}, error) {
		// Get thread IDs in the right order
		var (
			ids []uint64
			err error
		)
		if k.Board == "all" {
			ids, err = db.GetAllThreadsIDs()
		} else {
			ids, err = db.GetThreadIDs(k.Board)
		}
		if err != nil {
			return nil, err
		}

		if len(ids) == 0 {
			data := common.Board{Threads: []common.Thread{}}
			buf, err := json.Marshal(data)
			if err != nil {
				return nil, err
			}
			return []PageStore{
				{
					PageNumber: 1,
					JSON:       buf,
					Data:       data,
				},
			}, nil
		}

		// Get data and JSON for these views and paginate
		var (
			pages = make([]PageStore, 0, len(ids)/15+1)
			page  PageStore
		)
		closePage := func() {
			if page.Data.Threads != nil {
				pages = append(pages, page)
			}
		}

		// Hide threads from NSFW boards, if enabled
		var (
			confs    map[string]config.BoardConfContainer
			hideNSFW bool
		)
		if k.Board == "all" && config.Get().HideNSFW {
			hideNSFW = true
			confs = config.GetAllBoardConfigs()
		}

		for i, id := range ids {

			if i%15 == 0 {
				closePage()
				page = PageStore{
					PageNumber: len(pages),
					Data: common.Board{
						Threads: make([]common.Thread, 0, 15),
					},
				}
			}

			k := ThreadKey(id, 5)
			_, data, _, err := GetJSONAndData(k, ThreadFE)
			if err != nil {
				return nil, err
			}
			t := data.(common.Thread)

			if hideNSFW && confs[t.Board].NSFW {
				continue
			}

			page.Data.Threads = append(page.Data.Threads, t)
		}
		closePage()

		l := len(pages)
		if l == 0 {
			l = 1
			pages = []PageStore{
				{
					JSON: []byte(`{"threads":[],"pages":1}`),
				},
			}
		}
		for i := range pages {
			p := &pages[i]
			p.Data.Pages = l
			p.JSON, err = json.Marshal(p.Data)
			if err != nil {
				return nil, err
			}
		}

		return pages, nil
	},

	Size: func(data interface{}, _, _ []byte) (s int) {
		for _, p := range data.([]PageStore) {
			s += len(p.JSON) * 2
		}
		return
	},
}

BoardFE is for accessing cached board pages

View Source
var BoardPageFE = FrontEnd{
	GetCounter: func(k Key) (uint64, error) {

		k.Page = -1
		_, _, ctr, err := GetJSONAndData(k, BoardFE)
		return ctr, err
	},

	GetFresh: func(k Key) (interface{}, error) {
		i := int(k.Page)
		k.Page = -1
		_, data, _, err := GetJSONAndData(k, BoardFE)
		if err != nil {
			return nil, err
		}

		pages := data.([]PageStore)
		if i > len(pages)-1 {
			return nil, ErrPageOverflow
		}
		return pages[i], nil
	},

	EncodeJSON: func(data interface{}) ([]byte, error) {
		return data.(PageStore).JSON, nil
	},

	RenderHTML: func(data interface{}, json []byte) []byte {
		var b bytes.Buffer
		templates.WriteIndexThreads(&b, data.(PageStore).Data.Threads, json)
		return b.Bytes()
	},

	Size: func(_ interface{}, _, html []byte) int {

		return len(html)
	},
}

BoardPageFE is for individual pages of a board index page

View Source
var CatalogFE = FrontEnd{
	GetCounter: func(k Key) (uint64, error) {
		if k.Board == "all" {
			return db.AllBoardCounter()
		}
		return db.BoardCounter(k.Board)
	},

	GetFresh: func(k Key) (interface{}, error) {
		if k.Board == "all" {
			return db.GetAllBoardCatalog()
		}
		return db.GetBoardCatalog(k.Board)
	},

	RenderHTML: func(data interface{}, json []byte) []byte {
		var b bytes.Buffer
		templates.WriteCatalogThreads(&b, data.(common.Board).Threads, json)
		return b.Bytes()
	},
}

CatalogFE is for accessing cached catalog pages

View Source
var ErrPageOverflow = errors.New("page not found")

ErrPageOverflow is an error detailing that the page was not found

View Source
var ThreadFE = FrontEnd{
	GetCounter: func(k Key) (uint64, error) {
		return db.ThreadCounter(k.ID)
	},

	GetFresh: func(k Key) (interface{}, error) {
		return db.GetThread(k.ID, int(k.LastN))
	},

	RenderHTML: func(data interface{}, json []byte) []byte {
		var b bytes.Buffer
		templates.WriteThreadPosts(&b, data.(common.Thread), json)
		return b.Bytes()
	},
}

ThreadFE is for accessing cached thread pages

Functions

func Clear

func Clear()

Clear the cache. Only used for testing.

func Delete

func Delete(k Key)

Delete an entry by key. If no entry found, this is a NOP.

func DeleteByBoard

func DeleteByBoard(board string)

DeleteByBoard deletes all entries by the board property of Key. If no entries found, this is a NOP.

func GetHTML

func GetHTML(k Key, f FrontEnd) ([]byte, interface{}, uint64, error)

GetHTML retrieves post HTML from the cache or generates fresh HTML as needed

func GetJSONAndData

func GetJSONAndData(k Key, f FrontEnd) ([]byte, interface{}, uint64, error)

GetJSONAndData GetJSON retrieves JSON from the cache along with unencoded post data, validates, if is still fresh, or retrieves fresh data, if needed

Types

type FrontEnd

type FrontEnd struct {
	// GetCounter retrieves a new update counter for a resource
	GetCounter func(Key) (uint64, error)

	// GetFresh retrieves new post data from the database
	GetFresh func(Key) (interface{}, error)

	// Encode data into JSON. If null, default encoder is used.
	EncodeJSON func(data interface{}) ([]byte, error)

	// RenderHTML produces HTML from the passed in data and JSON
	RenderHTML func(interface{}, []byte) []byte

	// Calculates the size taken by the store.
	// If nil, the default function is used.
	Size func(data interface{}, json, html []byte) int
}

FrontEnd provides functions for fetching, validating and generating the cache. GetCounter and GetFresh are mandatory, but you may omit RenderHTML, if you don't plan to call GetHTML with this FrontEnd.

type Key

type Key struct {
	LastN uint8
	Board string
	ID    uint64
	Page  int64
}

Key stores the ID of either a thread or board page

func BoardKey

func BoardKey(b string, page int64, index bool) Key

BoardKey encodes a key for a board page resource

func ThreadKey

func ThreadKey(id uint64, lastN int) Key

ThreadKey encodes a Key from a thread's ID and last N posts to show setting

type PageStore

type PageStore struct {
	PageNumber int
	JSON       []byte
	Data       common.Board
}

PageStore contains data of a board page

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL