Add EventCompacted to event system (bd-262)
- Add EventCompacted event type constant - Add compaction fields to Issue struct (CompactionLevel, CompactedAt, OriginalSize) - Update ApplyCompaction to record compaction events with JSON metadata - Update bd show to display compaction status with emoji indicators - Update GetIssue query to load compaction fields - All tests passing Amp-Thread-ID: https://ampcode.com/threads/T-3f7946c6-8f5e-4a81-9527-1217041c7b39 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -114,7 +114,7 @@ func (c *Compactor) CompactTier1(ctx context.Context, issueID string) error {
|
||||
return fmt.Errorf("failed to update issue: %w", err)
|
||||
}
|
||||
|
||||
if err := c.store.ApplyCompaction(ctx, issueID, 1, originalSize); err != nil {
|
||||
if err := c.store.ApplyCompaction(ctx, issueID, 1, originalSize, compactedSize); err != nil {
|
||||
return fmt.Errorf("failed to set compaction level: %w", err)
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ func (c *Compactor) compactSingleWithResult(ctx context.Context, issueID string,
|
||||
return fmt.Errorf("failed to update issue: %w", err)
|
||||
}
|
||||
|
||||
if err := c.store.ApplyCompaction(ctx, issueID, 1, result.OriginalSize); err != nil {
|
||||
if err := c.store.ApplyCompaction(ctx, issueID, 1, result.OriginalSize, result.CompactedSize); err != nil {
|
||||
return fmt.Errorf("failed to set compaction level: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
)
|
||||
|
||||
// CompactionCandidate represents an issue eligible for compaction
|
||||
@@ -278,10 +280,16 @@ func (s *SQLiteStorage) CheckEligibility(ctx context.Context, issueID string, ti
|
||||
|
||||
// ApplyCompaction updates the compaction metadata for an issue after successfully compacting it.
|
||||
// This sets compaction_level, compacted_at, and original_size fields.
|
||||
func (s *SQLiteStorage) ApplyCompaction(ctx context.Context, issueID string, level int, originalSize int) error {
|
||||
func (s *SQLiteStorage) ApplyCompaction(ctx context.Context, issueID string, level int, originalSize int, compressedSize int) error {
|
||||
now := time.Now().UTC()
|
||||
|
||||
_, err := s.db.ExecContext(ctx, `
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to begin transaction: %w", err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
_, err = tx.ExecContext(ctx, `
|
||||
UPDATE issues
|
||||
SET compaction_level = ?,
|
||||
compacted_at = ?,
|
||||
@@ -294,5 +302,26 @@ func (s *SQLiteStorage) ApplyCompaction(ctx context.Context, issueID string, lev
|
||||
return fmt.Errorf("failed to apply compaction metadata: %w", err)
|
||||
}
|
||||
|
||||
reductionPct := 0.0
|
||||
if originalSize > 0 {
|
||||
reductionPct = (1.0 - float64(compressedSize)/float64(originalSize)) * 100
|
||||
}
|
||||
|
||||
eventData := fmt.Sprintf(`{"tier":%d,"original_size":%d,"compressed_size":%d,"reduction_pct":%.1f}`,
|
||||
level, originalSize, compressedSize, reductionPct)
|
||||
|
||||
_, err = tx.ExecContext(ctx, `
|
||||
INSERT INTO events (issue_id, event_type, actor, comment)
|
||||
VALUES (?, ?, 'compactor', ?)
|
||||
`, issueID, types.EventCompacted, eventData)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to record compaction event: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ func TestApplyCompaction(t *testing.T) {
|
||||
}
|
||||
|
||||
originalSize := len(issue.Description)
|
||||
err := store.ApplyCompaction(ctx, issue.ID, 1, originalSize)
|
||||
err := store.ApplyCompaction(ctx, issue.ID, 1, originalSize, 500)
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyCompaction failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -843,11 +843,14 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
|
||||
var estimatedMinutes sql.NullInt64
|
||||
var assignee sql.NullString
|
||||
var externalRef sql.NullString
|
||||
var compactedAt sql.NullTime
|
||||
var originalSize sql.NullInt64
|
||||
|
||||
err := s.db.QueryRowContext(ctx, `
|
||||
SELECT id, title, description, design, acceptance_criteria, notes,
|
||||
status, priority, issue_type, assignee, estimated_minutes,
|
||||
created_at, updated_at, closed_at, external_ref
|
||||
created_at, updated_at, closed_at, external_ref,
|
||||
compaction_level, compacted_at, original_size
|
||||
FROM issues
|
||||
WHERE id = ?
|
||||
`, id).Scan(
|
||||
@@ -855,6 +858,7 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
|
||||
&issue.AcceptanceCriteria, &issue.Notes, &issue.Status,
|
||||
&issue.Priority, &issue.IssueType, &assignee, &estimatedMinutes,
|
||||
&issue.CreatedAt, &issue.UpdatedAt, &closedAt, &externalRef,
|
||||
&issue.CompactionLevel, &compactedAt, &originalSize,
|
||||
)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -877,6 +881,12 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
|
||||
if externalRef.Valid {
|
||||
issue.ExternalRef = &externalRef.String
|
||||
}
|
||||
if compactedAt.Valid {
|
||||
issue.CompactedAt = &compactedAt.Time
|
||||
}
|
||||
if originalSize.Valid {
|
||||
issue.OriginalSize = int(originalSize.Int64)
|
||||
}
|
||||
|
||||
return &issue, nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ type Issue struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ClosedAt *time.Time `json:"closed_at,omitempty"`
|
||||
ExternalRef *string `json:"external_ref,omitempty"` // e.g., "gh-9", "jira-ABC"
|
||||
CompactionLevel int `json:"compaction_level,omitempty"`
|
||||
CompactedAt *time.Time `json:"compacted_at,omitempty"`
|
||||
OriginalSize int `json:"original_size,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"` // Populated only for export/import
|
||||
Dependencies []*Dependency `json:"dependencies,omitempty"` // Populated only for export/import
|
||||
}
|
||||
@@ -160,6 +163,7 @@ const (
|
||||
EventDependencyRemoved EventType = "dependency_removed"
|
||||
EventLabelAdded EventType = "label_added"
|
||||
EventLabelRemoved EventType = "label_removed"
|
||||
EventCompacted EventType = "compacted"
|
||||
)
|
||||
|
||||
// BlockedIssue extends Issue with blocking information
|
||||
|
||||
Reference in New Issue
Block a user