Documentation
¶
Overview ¶
Package store persists an awp peer's state in SQLite: the outbox of unacked messages, the per-thread "last seen" ids that resume needs, a log of every message sent and received, thread state, blobs and grants.
Section 4.3 requires this to be on disk, because the process can be killed together with its sandbox at any moment. Every function that changes state is safe to interrupt: either the transaction commits or it never happened.
Index ¶
- Constants
- Variables
- func AckOutbox(q Q, peer, id string, now time.Time) (th, t string, found bool, err error)
- func AddAddr(q Q, peer, addr, source string, now time.Time) error
- func Append(q Q, r *Record) (inserted bool, err error)
- func BumpSeen(q Q, peer, th, id string, now time.Time) error
- func DeleteMirrored(q Q, sharer, th, of string) (int64, error)
- func DropRef(q Q, peer, ref string) error
- func DropThread(q Q, peer, th string) error
- func Enqueue(q Q, r *OutboxRow) error
- func EnsurePeer(q Q, key string, now time.Time) error
- func HasLog(q Q, peer, dir, id string) (bool, error)
- func IsPrivate(q Q, peer, th string) (bool, error)
- func PruneSeen(q Q, peer string, seen map[string]string, now time.Time) (int64, error)
- func PutBlob(q Q, b *Blob) error
- func PutGrant(q Q, g *GrantRow) error
- func SetAcked(q Q, peer, id string) error
- func SetPrivate(q Q, peer, th string, now time.Time) (bool, error)
- func SetThreadState(q Q, peer, th string, mine bool, state, note string, now time.Time) error
- func Terminal(state string) bool
- func TouchPeer(q Q, key, name, about string, caps []string, now time.Time) error
- func TouchThread(q Q, peer, th, subject, origin string, now time.Time) error
- type Addr
- type Blob
- type Filter
- type GrantQuery
- type GrantRow
- type MirroredThread
- type OutboxRow
- type Peer
- type PresenceRow
- type Q
- type Record
- type Store
- func (s *Store) AddrResult(peer, addr string, dialErr error, now time.Time) error
- func (s *Store) Blobs(peer string) ([]*Blob, error)
- func (s *Store) Close() error
- func (s *Store) DB() Q
- func (s *Store) DeleteGrant(hash string) (int64, error)
- func (s *Store) ExpireOutbox(cutoff time.Time) (int64, error)
- func (s *Store) ExpirePresence(cutoff time.Time) ([]*PresenceRow, error)
- func (s *Store) GetKV(k string) (string, bool, error)
- func (s *Store) Grants(gq GrantQuery) ([]*GrantRow, error)
- func (s *Store) MarkRead(seqs []int64) error
- func (s *Store) MaxOwnID() (string, error)
- func (s *Store) MaxSeq() (int64, error)
- func (s *Store) MirroredThreads() ([]MirroredThread, error)
- func (s *Store) OpenThreads(peer string, cutoff time.Time) (int, error)
- func (s *Store) OutboxAfter(peer string, after int64, limit int) ([]OutboxRow, error)
- func (s *Store) OutboxCount(peer string) (int, error)
- func (s *Store) Peers() ([]*Peer, error)
- func (s *Store) PeersWithOutbox() ([]string, error)
- func (s *Store) PresenceSince(cutoff time.Time) ([]*PresenceRow, error)
- func (s *Store) PutPresence(r *PresenceRow) (stored, isNew bool, err error)
- func (s *Store) Query(f Filter) ([]Record, error)
- func (s *Store) SeenMap(peer string, cutoff time.Time) (map[string]string, error)
- func (s *Store) SetAlias(key, alias string) error
- func (s *Store) SetKV(k, v string) error
- func (s *Store) SetMeta(seq int64, add map[string]any) error
- func (s *Store) SetParked(key string, parked bool) error
- func (s *Store) Threads(peer, th string) ([]*Thread, error)
- func (s *Store) TrimPresence(max int) error
- func (s *Store) Tx(fn func(q Q) error) error
- type Thread
Constants ¶
const ( RoleIssued = "issued" // we signed it RoleHeld = "held" // someone granted it to us RolePresented = "presented" // a peer showed it to us about itself )
Grant roles.
Variables ¶
var InboxSys = []string{"blob", "bye", "refused", "shares", "private"}
InboxSys lists the local (sys) event types that belong in an inbox.
Functions ¶
func AckOutbox ¶
AckOutbox removes the acked message from the outbox, together with any earlier never-acked lines in the same thread, and marks the outgoing blobs those lines carried as sent. It reports the row's thread and type, and whether it was found.
func AddAddr ¶
AddAddr records an address hint. A hint from a more authoritative source upgrades the stored source.
func Append ¶
Append adds a record, unless one with the same (peer, dir, id) exists, in which case it reports inserted == false. That is the receive-side dedup that section 9.5 requires.
func DeleteMirrored ¶
DeleteMirrored forgets what sharer mirrored of its thread th with of.
func DropThread ¶
DropThread removes everything queued for a thread.
func EnsurePeer ¶
EnsurePeer creates a peer row if it does not exist.
func PruneSeen ¶
PruneSeen drops outbox rows the peer's resume says it already has: in each listed thread, everything up to and including the seen id. The matching log rows are marked acked, since "seen" means durably received, and blobs whose chunks are all seen are sent.
func PutGrant ¶
PutGrant stores a grant under a role. Storing the same grant twice under the same role is a no-op.
func SetPrivate ¶
SetPrivate keeps a thread out of conversation sharing. It reports whether the thread was not private before.
func SetThreadState ¶
SetThreadState records a state change, ours (mine) or the peer's. The side's since timestamp moves only when its state or note differs from what it was, so it says how long the side has been in that state.
Types ¶
type Addr ¶
type Addr struct {
Addr string `json:"addr"`
Source string `json:"source"`
Added time.Time `json:"added"`
LastOK time.Time `json:"last_ok,omitzero"`
LastErr string `json:"last_err,omitempty"`
}
Addr is an address hint for a peer. Sources, from most to least authoritative: "connect" (given to us out of band), "introduce" and "hello" (the peer's own advertised address).
type Blob ¶
type Blob struct {
Peer string `json:"peer"`
Dir string `json:"dir"`
Ref string `json:"ref"`
Th string `json:"th,omitempty"`
Name string `json:"name,omitempty"`
Mime string `json:"mime,omitempty"`
Size int64 `json:"size"` // declared size, -1 if not yet known
Received int64 `json:"received"`
NextN int `json:"next_n"`
Path string `json:"path,omitempty"`
Status string `json:"status"` // in: pending; received (data in, awaiting the msg that names it); complete; refused. out: queued; sent (the msg that carries it was acked); refused
Updated time.Time `json:"updated"`
}
Blob tracks one blob transfer in either direction.
type Filter ¶
type Filter struct {
Peer string
Th string
Dirs []string // default: all
Types []string // default: all
AfterSeq int64
UnreadOnly bool
Inbox bool // received records plus local events worth a reader's attention
Limit int // default 1000
Last bool // with Limit: the last N records, still returned in order
// Mirrors includes mirrored lines (dir "mirror"), which are left out
// unless asked for by this or by Dirs: they are other agents' threads,
// not this agent's business.
Mirrors bool
}
Filter selects log records.
type GrantQuery ¶
type GrantQuery struct {
Role string
Iss string
Sub string
Audience string
ValidAt time.Time // if set, only grants not expired at this time
}
GrantQuery selects grants. Empty fields match anything.
type GrantRow ¶
type GrantRow struct {
Hash string `json:"hash"`
Role string `json:"role"`
Iss string `json:"iss"`
Sub string `json:"sub"`
Caps []string `json:"caps"`
Exp time.Time `json:"exp"`
Raw []byte `json:"-"`
Audience string `json:"audience,omitempty"`
Created time.Time `json:"created"`
}
GrantRow is a stored grant.
type MirroredThread ¶
type MirroredThread struct {
Of string `json:"of"` // the other party
Th string `json:"th"`
Subject string `json:"subject,omitempty"`
Lines int `json:"lines"`
Updated time.Time `json:"updated"`
}
MirroredThread is a thread another agent shares with this host.
type OutboxRow ¶
type OutboxRow struct {
Seq int64
Peer string
ID string
T string
Th string
Ref string
Line []byte
Created time.Time
}
OutboxRow is a sent line that the peer has not yet confirmed.
type Peer ¶
type Peer struct {
Key string `json:"key"`
Name string `json:"name,omitempty"`
About string `json:"about,omitempty"`
Caps []string `json:"caps,omitempty"`
Alias string `json:"alias,omitempty"`
FirstSeen time.Time `json:"first_seen"`
LastSeen time.Time `json:"last_seen,omitzero"`
Parked bool `json:"parked,omitempty"`
Addrs []Addr `json:"addrs,omitempty"`
}
Peer is what we know about a remote key.
type PresenceRow ¶
type PresenceRow struct {
Origin string
Seq int64
Name string
TS time.Time // the origin's timestamp
Received time.Time
Via string // the peer it arrived from
Hops int
Doc []byte // exactly as signed
}
PresenceRow is the newest signed presence document from one origin.
type Q ¶
type Q interface {
Exec(query string, args ...any) (sql.Result, error)
Query(query string, args ...any) (*sql.Rows, error)
QueryRow(query string, args ...any) *sql.Row
}
Q is implemented by *sql.DB and *sql.Tx.
type Record ¶
type Record struct {
Seq int64 `json:"seq"`
Peer string `json:"peer"`
Dir string `json:"dir"`
ID string `json:"id"`
T string `json:"t"`
Th string `json:"th,omitempty"`
Line []byte `json:"-"`
At time.Time `json:"at"`
Acked bool `json:"acked,omitempty"`
Read bool `json:"read,omitempty"`
Meta map[string]any `json:"meta,omitempty"`
}
Record is one entry in the message log. Dir is "in" (received), "out" (sent), "sys" (a local event such as a connection coming up) or "mirror" (a line of another agent's thread that it shares with this host; Peer is that agent, ID the original line's id, Meta says who the other party is).
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the database handle.
func (*Store) AddrResult ¶
AddrResult records the outcome of dialing an address.
func (*Store) DeleteGrant ¶
DeleteGrant removes a grant in every role (local revocation).
func (*Store) ExpireOutbox ¶
ExpireOutbox drops outbox rows created before cutoff (open question 2 proposes seven days) and returns how many went.
func (*Store) ExpirePresence ¶
func (s *Store) ExpirePresence(cutoff time.Time) ([]*PresenceRow, error)
ExpirePresence deletes documents older than cutoff and returns them.
func (*Store) Grants ¶
func (s *Store) Grants(gq GrantQuery) ([]*GrantRow, error)
Grants returns matching grants, newest first.
func (*Store) MaxOwnID ¶
MaxOwnID returns the largest id this peer ever sent, so the id generator can keep increasing across restarts.
func (*Store) MirroredThreads ¶
func (s *Store) MirroredThreads() ([]MirroredThread, error)
MirroredThreads lists the threads other agents share with this host.
func (*Store) OpenThreads ¶
OpenThreads counts a peer's threads that are neither done, failed nor closed on either side and were active since cutoff.
func (*Store) OutboxAfter ¶
OutboxAfter returns up to limit outbox rows for peer with seq > after, in order.
func (*Store) OutboxCount ¶
OutboxCount returns how many lines are waiting for peer ("" for all).
func (*Store) PeersWithOutbox ¶
PeersWithOutbox lists peers that have queued lines.
func (*Store) PresenceSince ¶
func (s *Store) PresenceSince(cutoff time.Time) ([]*PresenceRow, error)
PresenceSince lists documents whose origin timestamp is at or after cutoff, most recent first.
func (*Store) PutPresence ¶
func (s *Store) PutPresence(r *PresenceRow) (stored, isNew bool, err error)
PutPresence stores a document if it is newer (by seq) than what we have. It reports whether it was stored and whether the origin is new to us.
func (*Store) SeenMap ¶
SeenMap returns the per-thread last seen ids for peer, for threads touched since cutoff (zero for all).
func (*Store) SetParked ¶
SetParked marks a peer as parked (it said bye, or we did): no automatic reconnection until there is new outbound traffic.
func (*Store) Threads ¶
Threads lists threads, most recently updated first. peer and th filter when non-empty.
func (*Store) TrimPresence ¶
TrimPresence keeps at most max origins, dropping the least recent. It bounds what a peer can make us store by inventing origins.
type Thread ¶
type Thread struct {
Peer string `json:"peer"`
Th string `json:"th"`
Subject string `json:"subject,omitempty"`
Origin string `json:"origin"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
MyState string `json:"my_state"`
MyNote string `json:"my_note,omitempty"`
MySince time.Time `json:"my_since"` // when my state or note last changed
TheirState string `json:"their_state"`
TheirNote string `json:"their_note,omitempty"`
TheirSince time.Time `json:"their_since"`
Unread int `json:"unread,omitempty"`
}
Thread is a conversation with one peer.