Complete implementation of signal-aware context propagation for graceful cancellation across all commands and storage operations. Key changes: 1. Signal-aware contexts (bd-rtp): - Added rootCtx/rootCancel in main.go using signal.NotifyContext() - Set up in PersistentPreRun, cancelled in PersistentPostRun - Daemon uses same pattern in runDaemonLoop() - Handles SIGINT/SIGTERM for graceful shutdown 2. Context propagation (bd-yb8): - All commands now use rootCtx instead of context.Background() - sqlite.New() receives context for cancellable operations - Database operations respect context cancellation - Storage layer propagates context through all queries 3. Cancellation tests (bd-2o2): - Added import_cancellation_test.go with comprehensive tests - Added export cancellation test in export_test.go - Tests verify database integrity after cancellation - All cancellation tests passing Fixes applied during review: - Fixed rootCtx lifecycle (removed premature defer from PersistentPreRun) - Fixed test context contamination (reset rootCtx in test cleanup) - Fixed export tests missing context setup Impact: - Pressing Ctrl+C during import/export now cancels gracefully - No database corruption or hanging transactions - Clean shutdown of all operations Tested: - go build ./cmd/bd ✓ - go test ./cmd/bd -run TestImportCancellation ✓ - go test ./cmd/bd -run TestExportCommand ✓ - Manual Ctrl+C testing verified 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
117 lines
3.5 KiB
Go
117 lines
3.5 KiB
Go
// Package beads provides a minimal public API for extending bd with custom orchestration.
|
|
//
|
|
// Most extensions should use direct SQL queries against bd's database.
|
|
// This package exports only the essential types and functions needed for
|
|
// Go-based extensions that want to use bd's storage layer programmatically.
|
|
//
|
|
// For detailed guidance on extending bd, see docs/EXTENDING.md.
|
|
package beads
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/steveyegge/beads/internal/beads"
|
|
"github.com/steveyegge/beads/internal/types"
|
|
)
|
|
|
|
// Storage is the interface for beads storage operations
|
|
type Storage = beads.Storage
|
|
|
|
// NewSQLiteStorage creates a new SQLite storage instance at the given path
|
|
func NewSQLiteStorage(ctx context.Context, dbPath string) (Storage, error) {
|
|
return beads.NewSQLiteStorage(ctx, dbPath)
|
|
}
|
|
|
|
// FindDatabasePath finds the beads database in the current directory tree
|
|
func FindDatabasePath() string {
|
|
return beads.FindDatabasePath()
|
|
}
|
|
|
|
// FindBeadsDir finds the .beads/ directory in the current directory tree
|
|
// Returns empty string if not found. Supports both database and JSONL-only mode.
|
|
func FindBeadsDir() string {
|
|
return beads.FindBeadsDir()
|
|
}
|
|
|
|
// FindJSONLPath finds the JSONL file corresponding to a database path
|
|
func FindJSONLPath(dbPath string) string {
|
|
return beads.FindJSONLPath(dbPath)
|
|
}
|
|
|
|
// DatabaseInfo contains information about a beads database
|
|
type DatabaseInfo = beads.DatabaseInfo
|
|
|
|
// FindAllDatabases finds all beads databases in the system
|
|
func FindAllDatabases() []DatabaseInfo {
|
|
return beads.FindAllDatabases()
|
|
}
|
|
|
|
// Core types from internal/types
|
|
type (
|
|
Issue = types.Issue
|
|
Status = types.Status
|
|
IssueType = types.IssueType
|
|
Dependency = types.Dependency
|
|
DependencyType = types.DependencyType
|
|
Label = types.Label
|
|
Comment = types.Comment
|
|
Event = types.Event
|
|
EventType = types.EventType
|
|
BlockedIssue = types.BlockedIssue
|
|
TreeNode = types.TreeNode
|
|
IssueFilter = types.IssueFilter
|
|
WorkFilter = types.WorkFilter
|
|
StaleFilter = types.StaleFilter
|
|
DependencyCounts = types.DependencyCounts
|
|
IssueWithCounts = types.IssueWithCounts
|
|
SortPolicy = types.SortPolicy
|
|
EpicStatus = types.EpicStatus
|
|
)
|
|
|
|
// Status constants
|
|
const (
|
|
StatusOpen = types.StatusOpen
|
|
StatusInProgress = types.StatusInProgress
|
|
StatusBlocked = types.StatusBlocked
|
|
StatusClosed = types.StatusClosed
|
|
)
|
|
|
|
// IssueType constants
|
|
const (
|
|
TypeBug = types.TypeBug
|
|
TypeFeature = types.TypeFeature
|
|
TypeTask = types.TypeTask
|
|
TypeEpic = types.TypeEpic
|
|
TypeChore = types.TypeChore
|
|
)
|
|
|
|
// DependencyType constants
|
|
const (
|
|
DepBlocks = types.DepBlocks
|
|
DepRelated = types.DepRelated
|
|
DepParentChild = types.DepParentChild
|
|
DepDiscoveredFrom = types.DepDiscoveredFrom
|
|
)
|
|
|
|
// SortPolicy constants
|
|
const (
|
|
SortPolicyHybrid = types.SortPolicyHybrid
|
|
SortPolicyPriority = types.SortPolicyPriority
|
|
SortPolicyOldest = types.SortPolicyOldest
|
|
)
|
|
|
|
// EventType constants
|
|
const (
|
|
EventCreated = types.EventCreated
|
|
EventUpdated = types.EventUpdated
|
|
EventStatusChanged = types.EventStatusChanged
|
|
EventCommented = types.EventCommented
|
|
EventClosed = types.EventClosed
|
|
EventReopened = types.EventReopened
|
|
EventDependencyAdded = types.EventDependencyAdded
|
|
EventDependencyRemoved = types.EventDependencyRemoved
|
|
EventLabelAdded = types.EventLabelAdded
|
|
EventLabelRemoved = types.EventLabelRemoved
|
|
EventCompacted = types.EventCompacted
|
|
)
|