Documentation
¶
Overview ¶
Package registry holds the set of repositories served by the stackit server, keyed by a stable repoID. Each entry owns the per-repository engine, GitHub client, event broadcaster, and ref watcher — so multiple repositories can be served from one process without leaking events between them.
Index ¶
- type Broadcaster
- type EntryConfig
- type Registry
- func (r *Registry) Add(e *RepoEntry) error
- func (r *Registry) Close() error
- func (r *Registry) FindManaged(repo RepoRef) (*RepoEntry, bool)
- func (r *Registry) Get(id string) (*RepoEntry, bool)
- func (r *Registry) GetByOwnerRepo(owner, repo string) (*RepoEntry, bool)
- func (r *Registry) Len() int
- func (r *Registry) List() []*RepoEntry
- type RepoEntry
- type RepoRef
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Broadcaster ¶
type Broadcaster struct {
// contains filtered or unexported fields
}
Broadcaster fans out SSE messages to subscribed clients. Each RepoEntry owns one so events stay scoped to a single repo — a client subscribed to /repos/A/events never receives B's refresh notifications.
func NewBroadcaster ¶
func NewBroadcaster() *Broadcaster
NewBroadcaster creates a new event broadcaster.
func (*Broadcaster) Broadcast ¶
func (b *Broadcaster) Broadcast(event, data string)
Broadcast sends an SSE event to every subscribed client. Slow clients drop the message rather than blocking the broadcast.
func (*Broadcaster) Close ¶
func (b *Broadcaster) Close()
Close notifies all subscribers to exit and prevents future broadcasts. It closes every active client channel so SSE handlers blocked on a receive unblock immediately. Safe to call multiple times.
func (*Broadcaster) Done ¶
func (b *Broadcaster) Done() <-chan struct{}
Done returns a channel that closes when the broadcaster is shutting down. SSE handlers select on this to exit promptly during server shutdown.
func (*Broadcaster) Subscribe ¶
func (b *Broadcaster) Subscribe() (chan string, bool)
Subscribe returns a buffered channel that receives every broadcast message until Unsubscribe is called or the broadcaster is closed. The bool is false when the broadcaster is already shut down.
func (*Broadcaster) Unsubscribe ¶
func (b *Broadcaster) Unsubscribe(ch chan string)
Unsubscribe removes ch from the broadcast set and closes it. Safe to call from a defer even if ch was already removed (e.g. by Close).
type EntryConfig ¶
type EntryConfig struct {
ID string
DisplayName string
RepoRoot string
Remote string
// AddedBy is the GitHub login of the user who onboarded this repo, or
// empty for operator-seeded repos. Handlers use it to scope per-user
// visibility so a user only sees repos they added.
AddedBy string
// Managed marks a server-owned mirror checkout (DB-backed / onboarded under
// the repos root) that the sync loop may mirror-fetch. The -cwd dev repo is
// the operator's own working tree and is left unmanaged.
Managed bool
// RepoRef carries the GitHub coordinates, set for managed repos. The
// sync loop uses them to resolve a GitHub App installation token for the
// fetch.
RepoRef
Engine engine.Engine
GitHub github.Client
}
EntryConfig is the input to NewEntry. It captures the per-repo state the constructor needs to wire up the broadcaster + watcher.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is a goroutine-safe collection of RepoEntries keyed by ID, with a secondary index keyed by owner/repo so handlers can resolve the GitHub-style /repos/{owner}/{repo} routes.
func (*Registry) Add ¶
Add inserts an entry. The entry's ID must be non-empty, match the allowed pattern, and be unique within the registry. When the entry carries GitHub coordinates (Owner and Name), they must also be unique so the owner/repo index stays unambiguous.
func (*Registry) Close ¶
Close runs every entry's closers and returns the joined error. The registry is unusable afterwards.
func (*Registry) FindManaged ¶ added in v0.20.0
FindManaged returns the managed entry whose GitHub coordinates match repo case-insensitively, or false when none does. The interval sync loop and the webhook receiver use it to map a remote-change signal (a push for owner/name) onto the local checkout to refresh.
Only managed mirrors are considered: the unmanaged -cwd working repo must never be selected here, because the sync path mirror-fetches into a detached HEAD and would corrupt a real working tree (see safety-invariants.md).
func (*Registry) Get ¶
Get returns the entry for id. The bool is false when no such entry exists, matching the comma-ok idiom of map access.
func (*Registry) GetByOwnerRepo ¶ added in v0.20.0
GetByOwnerRepo returns the entry for owner/repo, matched case-insensitively. The bool is false when no such entry exists or the coordinates are empty.
type RepoEntry ¶
type RepoEntry struct {
ID string
DisplayName string
RepoRoot string
Remote string
// AddedBy is the GitHub login of the user who onboarded this repo, or
// empty for operator-seeded repos visible to everyone.
AddedBy string
// Managed marks a server-owned mirror checkout the sync loop may
// mirror-fetch (see EntryConfig.Managed).
Managed bool
// RepoRef carries the GitHub coordinates, set for managed repos; the
// sync loop resolves an installation token from them.
RepoRef
Engine engine.Engine
GitHub github.Client
Broadcaster *Broadcaster
Watcher *watcher.RefWatcher
// contains filtered or unexported fields
}
RepoEntry is the per-repository state required to serve API requests for one repo. Constructed via NewEntry so the watcher + broadcaster lifecycle stays consistent across call sites; raw struct literals are still usable in tests where neither is needed.
func NewEntry ¶
func NewEntry(cfg EntryConfig) *RepoEntry
NewEntry constructs a ready-to-use entry with a broadcaster, a ref watcher (when RepoRoot is set), and closers that cleanly tear down both when registry.Close is called. The watcher goroutine starts immediately.
func (*RepoEntry) AddCloser ¶
AddCloser registers a teardown function that Registry.Close will invoke in reverse-registration order. Use it to attach lifecycle hooks (logger closers, etc.) when constructing an entry.
func (*RepoEntry) Refresh ¶ added in v0.20.0
func (e *RepoEntry) Refresh()
Refresh rebuilds the engine from current refs and broadcasts a "refresh" event (plus "branch_switched" when the served HEAD changed) so connected SSE clients refetch. It is the shared post-change path invoked by both the ref watcher (local changes) and the sync loop (remote changes); refreshMu serializes the two so the engine isn't rebuilt concurrently.
type RepoRef ¶ added in v0.22.0
RepoRef identifies a GitHub repository by its owner/name coordinates.