123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- package dbstore
- import (
- "context"
- "database/sql"
- "fmt"
- "git.linuxforward.com/byop/byop-engine/models"
- "github.com/pkg/errors"
- )
- // CreatePreview creates a new preview record
- func (s *SQLiteStore) CreatePreview(ctx context.Context, preview *models.Preview) (int, error) {
- query := `
- INSERT INTO previews (app_id, status, expires_at)
- VALUES (?, ?, ?)
- `
- result, err := s.db.ExecContext(ctx, query, preview.AppID, preview.Status, preview.ExpiresAt)
- if err != nil {
- return 0, models.NewErrInternalServer("failed to create preview", err)
- }
- id, err := result.LastInsertId()
- if err != nil {
- return 0, models.NewErrInternalServer("failed to get preview ID after creation", err)
- }
- return int(id), nil
- }
- // GetPreviewByID retrieves a preview by ID
- func (s *SQLiteStore) GetPreviewByID(ctx context.Context, id int) (*models.Preview, error) {
- preview := &models.Preview{}
- query := `
- SELECT id, app_id, status, url, vps_id, ip_address, error_msg,
- build_logs, deploy_logs, expires_at, created_at, updated_at
- FROM previews
- WHERE id = ?
- `
- err := s.db.QueryRowContext(ctx, query, id).Scan(
- &preview.ID, &preview.AppID, &preview.Status, &preview.URL,
- &preview.VPSID, &preview.IPAddress, &preview.ErrorMsg,
- &preview.BuildLogs, &preview.DeployLogs, &preview.ExpiresAt,
- &preview.CreatedAt, &preview.UpdatedAt,
- )
- if err != nil {
- if errors.Is(err, sql.ErrNoRows) {
- return nil, models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found", id), err)
- }
- return nil, models.NewErrInternalServer(fmt.Sprintf("failed to get preview with ID %d", id), err)
- }
- return preview, nil
- }
- // GetPreviewsByAppID retrieves all previews for an app
- func (s *SQLiteStore) GetPreviewsByAppID(ctx context.Context, appID int) ([]*models.Preview, error) {
- query := `
- SELECT id, app_id, status, url, vps_id, ip_address, error_msg,
- build_logs, deploy_logs, expires_at, created_at, updated_at
- FROM previews
- WHERE app_id = ?
- ORDER BY created_at DESC
- `
- rows, err := s.db.QueryContext(ctx, query, appID)
- if err != nil {
- return nil, models.NewErrInternalServer(fmt.Sprintf("failed to get previews for app ID %d", appID), err)
- }
- defer rows.Close()
- var previews []*models.Preview
- for rows.Next() {
- var preview models.Preview
- err := rows.Scan(
- &preview.ID, &preview.AppID, &preview.Status, &preview.URL,
- &preview.VPSID, &preview.IPAddress, &preview.ErrorMsg,
- &preview.BuildLogs, &preview.DeployLogs, &preview.ExpiresAt,
- &preview.CreatedAt, &preview.UpdatedAt,
- )
- if err != nil {
- return nil, models.NewErrInternalServer("failed to scan preview row", err)
- }
- previews = append(previews, &preview)
- }
- if err = rows.Err(); err != nil {
- return nil, models.NewErrInternalServer(fmt.Sprintf("error iterating preview rows for app ID %d", appID), err)
- }
- return previews, nil
- }
- // GetAllPreviews retrieves all previews (for admin purposes)
- func (s *SQLiteStore) GetAllPreviews(ctx context.Context) ([]*models.Preview, error) {
- query := `
- SELECT id, app_id, status, url, vps_id, ip_address, error_msg,
- build_logs, deploy_logs, expires_at, created_at, updated_at
- FROM previews
- ORDER BY created_at DESC
- `
- rows, err := s.db.QueryContext(ctx, query)
- if err != nil {
- return nil, models.NewErrInternalServer("failed to get all previews", err)
- }
- defer rows.Close()
- var previews []*models.Preview
- for rows.Next() {
- var preview models.Preview
- err := rows.Scan(
- &preview.ID, &preview.AppID, &preview.Status, &preview.URL,
- &preview.VPSID, &preview.IPAddress, &preview.ErrorMsg,
- &preview.BuildLogs, &preview.DeployLogs, &preview.ExpiresAt,
- &preview.CreatedAt, &preview.UpdatedAt,
- )
- if err != nil {
- return nil, models.NewErrInternalServer("failed to scan preview row", err)
- }
- previews = append(previews, &preview)
- }
- if err = rows.Err(); err != nil {
- return nil, models.NewErrInternalServer("error iterating all preview rows", err)
- }
- return previews, nil
- }
- // UpdatePreviewStatus updates the status and error message of a preview
- func (s *SQLiteStore) UpdatePreviewStatus(ctx context.Context, previewID int, status, errorMsg string) error {
- query := `
- UPDATE previews
- SET status = ?, error_msg = ?, updated_at = CURRENT_TIMESTAMP
- WHERE id = ?
- `
- result, err := s.db.ExecContext(ctx, query, status, errorMsg, previewID)
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to update preview status for ID %d", previewID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for preview status update ID %d", previewID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for status update", previewID), nil)
- }
- return nil
- }
- // UpdatePreviewVPS updates the VPS information for a preview
- func (s *SQLiteStore) UpdatePreviewVPS(ctx context.Context, previewID int, vpsID, ipAddress, url string) error {
- query := `
- UPDATE previews
- SET vps_id = ?, ip_address = ?, url = ?, updated_at = CURRENT_TIMESTAMP
- WHERE id = ?
- `
- result, err := s.db.ExecContext(ctx, query, vpsID, ipAddress, url, previewID)
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to update preview VPS info for ID %d", previewID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for preview VPS update ID %d", previewID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for VPS update", previewID), nil)
- }
- return nil
- }
- // UpdatePreviewBuildLogs updates the build logs for a preview
- func (s *SQLiteStore) UpdatePreviewBuildLogs(ctx context.Context, previewID int, buildLogs string) error {
- query := `
- UPDATE previews
- SET build_logs = ?, updated_at = CURRENT_TIMESTAMP
- WHERE id = ?
- `
- result, err := s.db.ExecContext(ctx, query, buildLogs, previewID)
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to update preview build logs for ID %d", previewID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for preview build logs update ID %d", previewID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for build logs update", previewID), nil)
- }
- return nil
- }
- // UpdatePreviewDeployLogs updates the deploy logs for a preview
- func (s *SQLiteStore) UpdatePreviewDeployLogs(ctx context.Context, previewID int, deployLogs string) error {
- query := `
- UPDATE previews
- SET deploy_logs = ?, updated_at = CURRENT_TIMESTAMP
- WHERE id = ?
- `
- result, err := s.db.ExecContext(ctx, query, deployLogs, previewID)
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to update preview deploy logs for ID %d", previewID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for preview deploy logs update ID %d", previewID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for deploy logs update", previewID), nil)
- }
- return nil
- }
- // UpdatePreview updates a preview record
- func (s *SQLiteStore) UpdatePreview(ctx context.Context, preview models.Preview) error {
- query := `
- UPDATE previews
- SET app_id = ?, status = ?, url = ?, vps_id = ?, ip_address = ?,
- error_msg = ?, build_logs = ?, deploy_logs = ?, expires_at = ?,
- updated_at = CURRENT_TIMESTAMP
- WHERE id = ?
- `
- result, err := s.db.ExecContext(ctx, query,
- preview.AppID, preview.Status, preview.URL, preview.VPSID,
- preview.IPAddress, preview.ErrorMsg, preview.BuildLogs,
- preview.DeployLogs, preview.ExpiresAt, preview.ID,
- )
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to update preview with ID %d", preview.ID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for preview update ID %d", preview.ID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for update", preview.ID), nil)
- }
- return nil
- }
- // DeletePreview deletes a preview record
- func (s *SQLiteStore) DeletePreview(ctx context.Context, previewID int) error {
- query := `DELETE FROM previews WHERE id = ?`
- result, err := s.db.ExecContext(ctx, query, previewID)
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to delete preview with ID %d", previewID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for preview deletion ID %d", previewID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for deletion", previewID), nil)
- }
- return nil
- }
- // GetExpiredPreviews gets all previews that have expired (for cleanup jobs)
- func (s *SQLiteStore) GetExpiredPreviews(ctx context.Context) ([]*models.Preview, error) {
- query := `
- SELECT id, app_id, status, url, vps_id, ip_address, error_msg,
- build_logs, deploy_logs, expires_at, created_at, updated_at
- FROM previews
- WHERE expires_at < datetime('now') AND status != 'stopped'
- ORDER BY expires_at ASC
- `
- rows, err := s.db.QueryContext(ctx, query)
- if err != nil {
- return nil, models.NewErrInternalServer("failed to get expired previews", err)
- }
- defer rows.Close()
- var previews []*models.Preview
- for rows.Next() {
- var preview models.Preview
- err := rows.Scan(
- &preview.ID, &preview.AppID, &preview.Status, &preview.URL,
- &preview.VPSID, &preview.IPAddress, &preview.ErrorMsg,
- &preview.BuildLogs, &preview.DeployLogs, &preview.ExpiresAt,
- &preview.CreatedAt, &preview.UpdatedAt,
- )
- if err != nil {
- return nil, models.NewErrInternalServer("failed to scan expired preview row", err)
- }
- previews = append(previews, &preview)
- }
- if err = rows.Err(); err != nil {
- return nil, models.NewErrInternalServer("error iterating expired preview rows", err)
- }
- return previews, nil
- }
- // GetPreviewsByStatus retrieves all previews with a specific status
- func (s *SQLiteStore) GetPreviewsByStatus(ctx context.Context, status string) ([]*models.Preview, error) {
- query := `SELECT id, app_id, status, vps_id, ip_address, url, build_logs, deploy_logs, error_msg, expires_at, created_at, updated_at FROM previews WHERE status = ?`
- rows, err := s.db.QueryContext(ctx, query, status)
- if err != nil {
- return nil, models.NewErrInternalServer(fmt.Sprintf("failed to get previews with status %s", status), err)
- }
- defer rows.Close()
- var previews []*models.Preview
- for rows.Next() {
- var preview models.Preview
- err := rows.Scan(
- &preview.ID,
- &preview.AppID,
- &preview.Status,
- &preview.VPSID,
- &preview.IPAddress,
- &preview.URL,
- &preview.BuildLogs,
- &preview.DeployLogs,
- &preview.ErrorMsg,
- &preview.ExpiresAt,
- &preview.CreatedAt,
- &preview.UpdatedAt,
- )
- if err != nil {
- return nil, models.NewErrInternalServer("failed to scan preview row", err)
- }
- previews = append(previews, &preview)
- }
- if err = rows.Err(); err != nil {
- return nil, models.NewErrInternalServer(fmt.Sprintf("error iterating preview rows with status %s", status), err)
- }
- return previews, nil
- }
- // UpdateAppPreview updates the app with preview information
- func (s *SQLiteStore) UpdateAppPreview(ctx context.Context, appID, previewID int, previewURL string) error {
- query := `
- UPDATE apps
- SET preview_id = ?, preview_url = ?, status = 'ready', updated_at = CURRENT_TIMESTAMP
- WHERE id = ?
- `
- result, err := s.db.ExecContext(ctx, query, previewID, previewURL, appID)
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to update app preview info for app ID %d", appID), err)
- }
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- return models.NewErrInternalServer(fmt.Sprintf("failed to get rows affected for app preview update, app ID %d", appID), err)
- }
- if rowsAffected == 0 {
- return models.NewErrNotFound(fmt.Sprintf("app with ID %d not found for preview update", appID), nil)
- }
- return nil
- }
- // GetPreviewByAppID retrieves the latest preview for an app
- func (s *SQLiteStore) GetPreviewByAppID(ctx context.Context, appID int) (*models.Preview, error) {
- query := `
- SELECT id, app_id, status, url, vps_id, ip_address, error_msg,
- build_logs, deploy_logs, expires_at, created_at, updated_at
- FROM previews
- WHERE app_id = ?
- ORDER BY created_at DESC
- LIMIT 1
- `
- preview := &models.Preview{}
- err := s.db.QueryRowContext(ctx, query, appID).Scan(
- &preview.ID, &preview.AppID, &preview.Status, &preview.URL,
- &preview.VPSID, &preview.IPAddress, &preview.ErrorMsg,
- &preview.BuildLogs, &preview.DeployLogs, &preview.ExpiresAt,
- &preview.CreatedAt, &preview.UpdatedAt,
- )
- if err != nil {
- if errors.Is(err, sql.ErrNoRows) {
- return nil, nil
- }
- return nil, models.NewErrInternalServer(fmt.Sprintf("failed to get latest preview for app ID %d", appID), err)
- }
- return preview, nil
- }
|