feat: update ingest, registry, and UI flows

This commit is contained in:
2026-02-15 21:50:35 +03:00
parent e6eca7cd50
commit 5518c3b405
35 changed files with 2615 additions and 497 deletions

View File

@@ -102,3 +102,66 @@ func (r *EventRepository) List(ctx context.Context, subjectType string, subjectI
return events, nextCursor, nil
}
func (r *EventRepository) ListLatestBySubjects(ctx context.Context, subjectType string, ids []string) (map[string]domain.TimelineEvent, error) {
result := make(map[string]domain.TimelineEvent, len(ids))
if len(ids) == 0 {
return result, nil
}
placeholders := make([]string, len(ids))
args := make([]any, 0, len(ids)+1)
args = append(args, subjectType)
for i, id := range ids {
placeholders[i] = "?"
args = append(args, id)
}
query := `
SELECT t.id, t.subject_id, t.event_type, t.event_time, t.machine_id, t.part_id, t.firmware_version, t.created_at
FROM timeline_events t
WHERE t.subject_type = ? AND t.subject_id IN (` + strings.Join(placeholders, ",") + `)
AND NOT EXISTS (
SELECT 1
FROM timeline_events t2
WHERE t2.subject_type = t.subject_type
AND t2.subject_id = t.subject_id
AND (
t2.event_time > t.event_time
OR (t2.event_time = t.event_time AND t2.id > t.id)
)
)
`
rows, err := r.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var event domain.TimelineEvent
event.SubjectType = subjectType
var machineID sql.NullString
var partID sql.NullString
var firmware sql.NullString
if err := rows.Scan(&event.ID, &event.SubjectID, &event.EventType, &event.EventTime, &machineID, &partID, &firmware, &event.CreatedAt); err != nil {
return nil, err
}
if machineID.Valid {
event.MachineID = &machineID.String
}
if partID.Valid {
event.PartID = &partID.String
}
if firmware.Valid {
event.FirmwareVersion = &firmware.String
}
result[event.SubjectID] = event
}
if err := rows.Err(); err != nil {
return nil, err
}
return result, nil
}