2026-10-15 13:15:49 -07:00
package store
import (
"context"
"database/sql"
"errors"
2026-10-18 15:32:07 -07:00
"g.fc.run/ai/byre/internal/api"
2026-10-15 13:15:49 -07:00
)
const previewColumns = `task_id, name, port, created_at`
func ( s * Store ) SetPreview ( ctx context . Context , p api . Preview , actor string ) ([] int , error ) {
dropped := [] int {}
err := s . write ( ctx , func ( tx * sql . Tx , emit emitFunc ) error {
projectID := ""
err := tx . QueryRowContext ( ctx , `SELECT project_id FROM tasks WHERE id = ? AND status = ?` , p . TaskId , string ( api . TaskStatusActive )). Scan ( & projectID )
if errors . Is ( err , sql . ErrNoRows ) {
return ErrNotFound
}
if err != nil {
return err
}
rows , err := tx . QueryContext ( ctx , `DELETE FROM previews WHERE task_id = ? AND (name = ? OR port = ?) RETURNING port` , p . TaskId , p . Name , p . Port )
if err != nil {
return err
}
for rows . Next () {
port := 0
err = rows . Scan ( & port )
if err != nil {
rows . Close ()
return err
}
if port != p . Port {
dropped = append ( dropped , port )
}
}
rows . Close ()
err = rows . Err ()
if err != nil {
return err
}
_ , err = tx . ExecContext ( ctx , `INSERT INTO previews (` + previewColumns + `) VALUES (?, ?, ?, ?)` , p . TaskId , p . Name , p . Port , formatTime ( p . CreatedAt ))
if err != nil {
return err
}
return emit ( api . Event { Kind : "preview.exposed" , ProjectId : & projectID , TaskId : & p . TaskId , Actor : actor , Payload : ToPayload ( p )})
})
return dropped , err
}
func ( s * Store ) ListPreviews ( ctx context . Context , taskID string ) ([] api . Preview , error ) {
rows , err := s . db . QueryContext ( ctx , `SELECT ` + previewColumns + ` FROM previews WHERE task_id = ? ORDER BY name` , taskID )
if err != nil {
return nil , err
}
2026-10-20 13:32:56 -07:00
return scanPreviews ( rows )
}
func ( s * Store ) ActivePreviews ( ctx context . Context ) ([] api . Preview , error ) {
rows , err := s . db . QueryContext ( ctx , `SELECT ` + previewColumns + ` FROM previews WHERE task_id IN (SELECT id FROM tasks WHERE status = ?)` , string ( api . TaskStatusActive ))
if err != nil {
return nil , err
}
return scanPreviews ( rows )
}
func scanPreviews ( rows * sql . Rows ) ([] api . Preview , error ) {
2026-10-15 13:15:49 -07:00
defer rows . Close ()
previews := [] api . Preview {}
for rows . Next () {
p := api . Preview {}
createdAt := ""
2026-10-20 13:32:56 -07:00
err := rows . Scan ( & p . TaskId , & p . Name , & p . Port , & createdAt )
2026-10-15 13:15:49 -07:00
if err != nil {
return nil , err
}
p . CreatedAt , err = parseTime ( createdAt )
if err != nil {
return nil , err
}
previews = append ( previews , p )
}
return previews , rows . Err ()
}