cache

package
v0.1.1 Latest Latest
Warning

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

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

Documentation

Overview

Package cache keeps Quantic's answers on disk (design §7): a fresh answer is used without asking again, a stale one is revalidated with its ETag, and when Quantic can't be reached, the last answer is used, marked stale.

Transport does all of that as an http.RoundTripper, under the client the api package builds, so nothing above it knows about files or ETags.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Key

func Key(req *http.Request) string

Key names the entry for req: a hash of the method, the URL, and the Authorization header. Each token gets its own entries, so two accounts on one machine never see each other's, and the token itself is never written: a SHA-256 can't be turned back into it.

Types

type Entry

type Entry struct {
	URL         string          `json:"url"` // for someone reading the file; the key is a hash
	FetchedAt   time.Time       `json:"fetched_at"`
	ETag        string          `json:"etag,omitempty"`
	ContentType string          `json:"content_type"`
	Body        json.RawMessage `json:"body"`
}

Entry is one answer, as kept on disk: the body of a 200, when it was fetched (or last confirmed unchanged), and the ETag to revalidate it with.

type Result

type Result struct {
	FetchedAt time.Time // when Quantic gave (or confirmed) this answer
	Stale     bool      // Quantic couldn't be reached; this is the last answer it gave
}

Result says where the last answer came from.

type Store

type Store struct {
	Dir string
}

Store is a directory of entries, one file per key, and a lock file beside each. It holds portfolio data, so the directory is 0700 and every file in it 0600 (privfile).

func (Store) Clear

func (s Store) Clear() error

Clear removes every entry and lock. The directory is the CLI's own, so it goes as a whole.

func (Store) Get

func (s Store) Get(key string) *Entry

Get returns the entry for key, or nil when there is none. An entry that can't be read as one (cut short, or from another version) is no entry: the cache is a copy, and Quantic has the original.

func (Store) Lock

func (s Store) Lock(ctx context.Context, key string) (unlock func(), err error)

Lock takes key's lock, waiting for another process (or goroutine) that holds it, until ctx is done. The status bar and a command in a terminal may want the same answer at once; one asks Quantic, and the other, once it gets the lock, finds the answer already stored.

The lock is an advisory lock on a file (flock on Unix), which the operating system releases when the process exits, even if it crashes, so a lock is never left behind. Taking it never blocks: a blocking flock can't be cancelled, and a wait must end at --timeout.

func (Store) Put

func (s Store) Put(key string, e *Entry) error

Put stores e under key, replacing what was there in one step.

type Transport

type Transport struct {
	Store Store

	// Next sends what the cache can't answer; nil means http.DefaultTransport.
	Next http.RoundTripper

	// MaxAge is how long an answer to req stays fresh. Zero means "always
	// ask", which still revalidates with the ETag and still falls back to
	// the entry when Quantic can't be reached.
	MaxAge func(req *http.Request) time.Duration

	// Now is the clock; nil means time.Now.
	Now func() time.Time
	// contains filtered or unexported fields
}

Transport is an http.RoundTripper that answers GET requests from the Store when it can:

  • an entry younger than MaxAge is the answer, and Quantic isn't asked;
  • an older one is revalidated: sent with If-None-Match, a 304 means it is still right, and it counts as fetched now;
  • when Quantic can't be reached (no connection, no answer in time, or a 502, 503 or 504 from what's in front of it), an entry of any age is the answer, marked stale.

Every other answer (a 401, a 404, a 429) passes through, not stored: the cache never hides what Quantic says.

func (*Transport) Last

func (t *Transport) Last() Result

Last is the Result of the most recent RoundTrip.

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

Jump to

Keyboard shortcuts

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