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 ¶
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 ¶
Clear removes every entry and lock. The directory is the CLI's own, so it goes as a whole.
func (Store) Get ¶
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 ¶
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.
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.