Agent seam: bulk ops (FillRegion/ClearObject/DescribeGarden) + DefineTool wrappers (#19)
Build image / build-and-push (push) Successful in 5s
Build image / build-and-push (push) Successful in 5s
Co-authored-by: Steve Dudenhoeffer <[email protected]>
This commit was merged in pull request #38.
This commit is contained in:
@@ -56,6 +56,53 @@ func (d *DB) ListActivePlantingsForGarden(ctx context.Context, gardenID int64) (
|
||||
return plantings, nil
|
||||
}
|
||||
|
||||
// ListActivePlantingsForObject returns an object's currently-planted plops
|
||||
// (removed_at IS NULL). Always a non-nil slice. Used by FillRegion to avoid
|
||||
// stacking new plops inside existing ones.
|
||||
func (d *DB) ListActivePlantingsForObject(ctx context.Context, objectID int64) ([]domain.Planting, error) {
|
||||
rows, err := d.sql.QueryContext(ctx,
|
||||
`SELECT `+plantingColumns+` FROM plantings WHERE object_id = ? AND removed_at IS NULL ORDER BY id`,
|
||||
objectID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: list object plantings: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
plantings := []domain.Planting{}
|
||||
for rows.Next() {
|
||||
p, err := scanPlanting(rows)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: scan planting: %w", err)
|
||||
}
|
||||
plantings = append(plantings, *p)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("store: iterate plantings: %w", err)
|
||||
}
|
||||
return plantings, nil
|
||||
}
|
||||
|
||||
// ClearObjectPlantings soft-removes every active plop in an object in one UPDATE
|
||||
// (sets removed_at=date, bumps version) and returns how many rows it affected.
|
||||
func (d *DB) ClearObjectPlantings(ctx context.Context, objectID int64, date string) (int, error) {
|
||||
res, err := d.sql.ExecContext(ctx,
|
||||
`UPDATE plantings
|
||||
SET removed_at = ?, version = version + 1,
|
||||
updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
|
||||
WHERE object_id = ? AND removed_at IS NULL`,
|
||||
date, objectID,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("store: clear object plantings: %w", err)
|
||||
}
|
||||
n, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("store: clear plantings rows: %w", err)
|
||||
}
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
// GetPlanting returns the planting with the given id, or domain.ErrNotFound.
|
||||
func (d *DB) GetPlanting(ctx context.Context, id int64) (*domain.Planting, error) {
|
||||
p, err := scanPlanting(d.sql.QueryRowContext(ctx,
|
||||
@@ -85,6 +132,36 @@ func (d *DB) CreatePlanting(ctx context.Context, p *domain.Planting) (*domain.Pl
|
||||
return created, nil
|
||||
}
|
||||
|
||||
// CreatePlantings inserts many plops in a single transaction (one commit), for
|
||||
// bulk fills. Returns the stored rows in order. An empty input is a no-op.
|
||||
func (d *DB) CreatePlantings(ctx context.Context, plantings []*domain.Planting) ([]domain.Planting, error) {
|
||||
if len(plantings) == 0 {
|
||||
return []domain.Planting{}, nil
|
||||
}
|
||||
tx, err := d.sql.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: begin plantings tx: %w", err)
|
||||
}
|
||||
defer tx.Rollback() //nolint:errcheck // no-op after a successful commit
|
||||
|
||||
const stmt = `INSERT INTO plantings (object_id, plant_id, x_cm, y_cm, radius_cm, count, label, planted_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING ` + plantingColumns
|
||||
out := make([]domain.Planting, 0, len(plantings))
|
||||
for _, p := range plantings {
|
||||
created, err := scanPlanting(tx.QueryRowContext(ctx, stmt,
|
||||
p.ObjectID, p.PlantID, p.XCM, p.YCM, p.RadiusCM, p.Count, p.Label, p.PlantedAt))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: insert planting (batch): %w", err)
|
||||
}
|
||||
out = append(out, *created)
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("store: commit plantings: %w", err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UpdatePlanting applies a version-guarded update of all mutable columns (the
|
||||
// service merges partial patches first). Returns the updated row, or
|
||||
// (current row, ErrVersionConflict) / ErrNotFound — the same contract as the
|
||||
|
||||
Reference in New Issue
Block a user