Documentation
¶
Overview ¶
Package archive implements the chat archive lifecycle: move to archive, list, restore, update summary, delete, and age-based purge. Separated from the core chat store to give the archive subsystem its own package boundary and make the purge scheduler independently testable.
Index ¶
- Constants
- func OldestArchiveMTime(ctx context.Context, storeDir string) (time.Time, bool)
- type IDInUseError
- type Option
- type PurgeScheduler
- type Service
- func (s *Service) Archive(ctx context.Context, chatID api.ChatID) error
- func (s *Service) DeleteArchived(ctx context.Context, chatID api.ChatID) error
- func (s *Service) ListArchived(ctx context.Context) []api.ChatHeader
- func (s *Service) LoadArchived(ctx context.Context, chatID api.ChatID) (*api.Chat, error)
- func (s *Service) Purge(ctx context.Context, maxAge time.Duration)
- func (s *Service) RestoreArchived(ctx context.Context, chatID api.ChatID) error
- func (s *Service) UpdateArchivedSummary(ctx context.Context, chatID api.ChatID, summary string) error
- type StoreAccess
Constants ¶
const Subdir = "archive"
Subdir is the subdirectory name under the chats directory where archived chats are stored. Exported so composition-layer code can reference it without hardcoding the literal.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type IDInUseError ¶
type IDInUseError struct {
ID string
}
IDInUseError indicates the target chat ID is already used by an active (non-archived) chat.
func (*IDInUseError) Error ¶
func (e *IDInUseError) Error() string
type Option ¶
type Option func(*Service)
Option configures the archive Service.
func WithOnArchive ¶
WithOnArchive registers a callback fired after a chat is archived.
func WithOnPurge ¶
WithOnPurge registers a callback fired after an archived chat is purged.
func WithPreArchive ¶ added in v0.1.165
WithPreArchive registers a callback fired BEFORE a chat's file is moved to the archive dir. Used to run the hub's in-memory teardown (close the bridge, kill terminals, clear pending state, remove the .partial) while the chat record is still active, so archiving can't orphan a live bridge or leave a ghost .partial.
type PurgeScheduler ¶
type PurgeScheduler struct {
// contains filtered or unexported fields
}
PurgeScheduler owns the archive-purge lifecycle. Uses a dedicated goroutine with a trigger channel for true collapse semantics.
func NewPurgeScheduler ¶
func NewPurgeScheduler(ctx context.Context, svc *Service, retention func() time.Duration) *PurgeScheduler
NewPurgeScheduler builds a scheduler that runs purges based on the retention value returned by `retention`.
func (*PurgeScheduler) Done ¶
func (p *PurgeScheduler) Done() <-chan struct{}
Done returns a channel that is closed when the scheduler goroutine exits.
func (*PurgeScheduler) Start ¶
func (p *PurgeScheduler) Start()
Start launches the scheduler goroutine and runs an initial evaluation.
func (*PurgeScheduler) Stop ¶
func (p *PurgeScheduler) Stop()
Stop signals the scheduler goroutine to exit and waits for it to finish.
func (*PurgeScheduler) Trigger ¶
func (p *PurgeScheduler) Trigger()
Trigger requests a purge evaluation. Safe to call from any goroutine; concurrent calls collapse into a single pending evaluation.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service implements the archive lifecycle operations.
func New ¶
func New(store StoreAccess, opts ...Option) *Service
New creates an archive Service backed by the given StoreAccess.
func (*Service) Archive ¶
Archive moves a chat from the active directory to the archive subdirectory. Takes the per-chat mutex so a concurrent Mutate / AppendMessage can't race the rename. Broadcasts chat_deleted so all connected clients see the entry disappear without a manual refresh.
func (*Service) DeleteArchived ¶
DeleteArchived permanently removes a single archived chat file and its plan draft. Fires onPurge so checkpoint data is cleaned up.
func (*Service) ListArchived ¶
func (s *Service) ListArchived(ctx context.Context) []api.ChatHeader
ListArchived returns headers for all archived chats, sorted by UpdatedAt desc. Files that fail to read or parse are logged and skipped. Always returns a non-nil slice.
func (*Service) LoadArchived ¶
LoadArchived reads the archived chat and returns the parsed *api.Chat.
func (*Service) RestoreArchived ¶
RestoreArchived moves a chat from the archive back to the active directory. Refuses with error if an active chat already exists at the target id.
func (*Service) UpdateArchivedSummary ¶
func (s *Service) UpdateArchivedSummary(ctx context.Context, chatID api.ChatID, summary string) error
UpdateArchivedSummary rewrites an archived chat's Summary field in place. Used by the hub to populate the one-line summary produced by the utility bridge after archiving.
type StoreAccess ¶
type StoreAccess interface {
// Lock returns the per-chat mutex for serialization.
Lock(chatID api.ChatID) *sync.Mutex
// Dir returns the store's base directory.
Dir() string
// PathFor returns the path to the active chat file.
PathFor(chatID api.ChatID) (string, error)
// Load reads a chat from the active directory.
Load(chatID api.ChatID) (*api.Chat, error)
// Header builds a ChatHeader from a Chat.
Header(ctx context.Context, c *api.Chat) api.ChatHeader
// MarkDeleted records a tombstone for the chat ID.
MarkDeleted(chatID api.ChatID)
// ClearTombstone removes the tombstone for a restored chat.
ClearTombstone(chatID api.ChatID)
// Broadcast returns the broadcaster (may be nil).
Broadcast() api.Broadcaster
// OldestCheckpoint returns the checkpoint lookup function (may be nil).
OldestCheckpoint() func(ctx context.Context, chatID api.ChatID) string
}
StoreAccess is the narrow interface the archive subsystem requires from the chat store. Keeps the dependency minimal and testable.