Fix monitoring PF project list deadlock
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 37s

This commit is contained in:
Grendgi
2026-06-05 11:56:47 +03:00
parent 54cc9372af
commit 76975c3c6c

View File

@@ -270,7 +270,7 @@ func (a *App) ListProjects(ctx context.Context, ownerID int64) ([]Project, error
defer rows.Close()
items := []Project{}
for rows.Next() {
p, err := a.scanProject(rows, false)
p, err := a.scanProject(ctx, rows, false)
if err != nil {
return nil, err
}
@@ -281,7 +281,7 @@ func (a *App) ListProjects(ctx context.Context, ownerID int64) ([]Project, error
func (a *App) ProjectByID(ctx context.Context, ownerID, projectID int64, detail bool) (*Project, error) {
row := a.DB.QueryRowContext(ctx, projectSelect()+` WHERE p.id = ? AND p.owner_id = ?`, projectID, ownerID)
p, err := a.scanProject(row, detail)
p, err := a.scanProject(ctx, row, detail)
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
}
@@ -435,19 +435,25 @@ func projectSelect() string {
(SELECT count(*) FROM competitor_listings l WHERE l.project_id = p.id),
(SELECT count(*) FROM competitor_listings l WHERE l.project_id = p.id AND l.status IN ('ACTIVE','active')),
(SELECT count(*) FROM competitor_listings l WHERE l.project_id = p.id AND l.status IN ('REMOVED','removed')),
(SELECT min(l.current_price) FROM competitor_listings l WHERE l.project_id = p.id AND l.status IN ('ACTIVE','active') AND l.current_price IS NOT NULL)
FROM projects p`
(SELECT min(l.current_price) FROM competitor_listings l WHERE l.project_id = p.id AND l.status IN ('ACTIVE','active') AND l.current_price IS NOT NULL),
e.id, e.name, e.portal_user_id, e.tg_chat_id, e.tg_username, e.created_at,
(SELECT count(*) FROM projects owner_p WHERE owner_p.owner_id = e.id) AS owner_projects_total
FROM projects p
LEFT JOIN employees e ON e.id = p.owner_id`
}
func (a *App) scanProject(row rowScanner, detail bool) (*Project, error) {
func (a *App) scanProject(ctx context.Context, row rowScanner, detail bool) (*Project, error) {
var p Project
var deal string
var price, size, minPrice sql.NullFloat64
var notes, permit, building, ourURL, created, checked sql.NullString
var bedrooms sql.NullInt64
var ownerID, ownerProjectsTotal sql.NullInt64
var ownerName, ownerPortalID, ownerChatID, ownerUsername, ownerCreated sql.NullString
if err := row.Scan(
&p.ID, &p.Title, &deal, &price, &notes, &permit, &building, &bedrooms, &size, &ourURL,
&p.OwnerID, &created, &checked, &p.ListingsTotal, &p.ListingsActive, &p.ListingsRemoved, &minPrice,
&ownerID, &ownerName, &ownerPortalID, &ownerChatID, &ownerUsername, &ownerCreated, &ownerProjectsTotal,
); err != nil {
return nil, err
}
@@ -462,11 +468,19 @@ func (a *App) scanProject(row rowScanner, detail bool) (*Project, error) {
p.CreatedAt = timeOut(created)
p.LastCheckedAt = timeOut(checked)
p.MinCompetitorPrice = nullableFloat(minPrice)
if owner, err := a.EmployeeByID(context.Background(), p.OwnerID); err == nil {
p.Owner = owner
if ownerID.Valid {
p.Owner = &Employee{
ID: ownerID.Int64,
Name: ownerName.String,
PortalUserID: nullableString(ownerPortalID),
TGChatID: nullableString(ownerChatID),
TGUsername: nullableString(ownerUsername),
ProjectsTotal: nullIntValue(ownerProjectsTotal),
CreatedAt: timeOut(ownerCreated),
}
}
if detail {
listings, err := a.ListingsForProject(context.Background(), p.ID, true)
listings, err := a.ListingsForProject(ctx, p.ID, true)
if err != nil {
return nil, err
}
@@ -480,22 +494,29 @@ func (a *App) ListingsForProject(ctx context.Context, projectID int64, withHisto
if err != nil {
return nil, err
}
defer rows.Close()
items := []Listing{}
for rows.Next() {
item, err := scanListing(rows, false)
if err != nil {
return nil, err
}
if withHistory {
item.PriceHistory, err = a.PriceHistory(ctx, item.ID)
items = append(items, *item)
}
if err := rows.Err(); err != nil {
rows.Close()
return nil, err
}
rows.Close()
if withHistory {
for i := range items {
history, err := a.PriceHistory(ctx, items[i].ID)
if err != nil {
return nil, err
}
items[i].PriceHistory = history
}
items = append(items, *item)
}
return items, rows.Err()
return items, nil
}
func (a *App) PriceHistory(ctx context.Context, listingID int64) ([]PricePoint, error) {