state

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const CurrentVersion = 1

CurrentVersion is the schema version Save stamps into the state file. Bump it when an entry field changes meaning (not when one is merely added — additions unmarshal cleanly from older files). Past migrations (UpdatedAt backfill, Price int→float64) had to be inferred from data shape; an explicit version makes the next one a comparison.

View Source
const FileName = "_state.json"

FileName is the name of the state file in each blog directory.

Variables

This section is empty.

Functions

This section is empty.

Types

type PostEntry

type PostEntry struct {
	Title         string  `json:"title"`
	DirName       string  `json:"dirName"`
	DownloadedAt  string  `json:"downloadedAt"`
	UpdatedAt     int64   `json:"updatedAt,omitempty"`
	CommentsCount int     `json:"commentsCount"`
	Price         float64 `json:"price"`
	Tier          string  `json:"tier,omitempty"`
	Locked        bool    `json:"locked,omitempty"`
	HasComments   bool    `json:"hasComments"`
	HasMd         bool    `json:"hasMd"`
	// CommentsCapped records that this post hit the comments-fetch ceiling
	// the last time it was saved. The ceiling is our choice forced by a
	// broken offset query param on Boosty's comments endpoint (offset>0
	// returns data=[] with isLast=true), so we cannot paginate past the
	// first page and we cap at commentsPageLimit-1 top-level threads or
	// defaultReplyLimit inlined replies per thread — see
	// pkg/syncer/save.go commentsPageLimit and pkg/boosty/client.go
	// defaultReplyLimit. Without this flag, classifyPost would re-fire
	// NewComments on every sync forever because disk count can never catch
	// up to API count. With it, classify skips the disk<API trigger
	// (suppression is one-directional — see pkg/syncer/classify.go).
	CommentsCapped bool `json:"commentsCapped,omitempty"`
}

PostEntry records metadata about a downloaded post.

type State

type State struct {
	// Version is the schema version of the file on disk. 0 means a legacy
	// file written before the field existed — loaded fine, upgraded to
	// CurrentVersion on the next Save.
	Version  int                  `json:"version"`
	Posts    map[string]PostEntry `json:"posts"`
	LastSync string               `json:"lastSync"`
	// contains filtered or unexported fields
}

State tracks which posts have been downloaded for a blog.

State is NOT safe for concurrent use; callers that mutate it from multiple goroutines (e.g. the --workers > 1 download pool) must serialise access through their own mutex. The in-memory operations (Has, Get, Add, Count) are plain map access and never lock on their own.

func Load

func Load(dir string) (*State, error)

Load reads the state file from the given directory. A missing state file is reported as a fresh, empty state (nil error). Read or parse errors are returned so callers can refuse to overwrite a partially-recoverable `_state.json` with a freshly-initialised one — which would discard every previously tracked post.

The Posts map is always non-nil on a successful return so callers can use it directly. The JSON nil-check after Unmarshal is intentional — a payload of `{"posts": null}` would otherwise leave the map nil and panic on the first Add.

func (*State) Add

func (s *State) Add(postID string, entry PostEntry)

Add records a downloaded post in the state.

func (*State) Count

func (s *State) Count() int

Count returns the number of tracked posts.

func (*State) Get

func (s *State) Get(postID string) (PostEntry, bool)

Get returns the post entry for the given ID.

func (*State) Has

func (s *State) Has(postID string) bool

Has reports whether a post ID exists in the state.

func (*State) Save

func (s *State) Save() error

Save writes the state to disk atomically (write to temp file then rename), so an interrupted write cannot truncate the existing state file.

Jump to

Keyboard shortcuts

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