package postgres import ( "context" "strings" "git.cin.su/m/Assistant/contracts/identity" "git.cin.su/m/Assistant/contracts/situation" "github.com/jackc/pgx/v5/pgxpool" ) type SituationRepository struct{ pool *pgxpool.Pool } func OpenSituation(ctx context.Context, config ContinuityConfig) (*SituationRepository, error) { pool, err := openPool(ctx, config) if err != nil { return nil, err } return &SituationRepository{pool: pool}, nil } func (r *SituationRepository) Close() { r.pool.Close() } func (r *SituationRepository) Save(ctx context.Context, binding situation.FocusBinding) error { _, err := r.pool.Exec(ctx, `INSERT INTO situation.focus_bindings (focus_binding_id, actor_id, session_id, workspace_id, project_id, goal_id, scope_id, active) VALUES ($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT (focus_binding_id) DO UPDATE SET active=EXCLUDED.active`, binding.ID, binding.ActorID, binding.SessionID, binding.Workspace, binding.ProjectID, binding.GoalID, binding.ScopeID, binding.Active) return err } func (r *SituationRepository) ByRuntime(ctx context.Context, runtime situation.RuntimeBinding) ([]situation.FocusBinding, error) { rows, err := r.pool.Query(ctx, `SELECT focus_binding_id, actor_id, session_id, workspace_id, project_id, goal_id, scope_id, active FROM situation.focus_bindings WHERE session_id=$1 AND workspace_id=$2`, runtime.SessionID, runtime.Workspace) if err != nil { return nil, err } defer rows.Close() var bindings []situation.FocusBinding for rows.Next() { var binding situation.FocusBinding if err := rows.Scan(&binding.ID, &binding.ActorID, &binding.SessionID, &binding.Workspace, &binding.ProjectID, &binding.GoalID, &binding.ScopeID, &binding.Active); err != nil { return nil, err } bindings = append(bindings, binding) } return bindings, rows.Err() } func (r *SituationRepository) ListProjects(ctx context.Context) ([]situation.ProjectDescriptor, error) { rows, err := r.pool.Query(ctx, `SELECT p.project_id, p.display_name, p.recorded_at_unix_millis, COALESCE(array_agg(a.alias ORDER BY a.alias) FILTER (WHERE a.alias IS NOT NULL), '{}') FROM situation.projects p LEFT JOIN situation.project_aliases a ON a.project_id=p.project_id GROUP BY p.project_id, p.display_name, p.recorded_at_unix_millis ORDER BY p.display_name`) if err != nil { return nil, err } defer rows.Close() var projects []situation.ProjectDescriptor for rows.Next() { var project situation.ProjectDescriptor var aliases []string if err := rows.Scan(&project.ID, &project.DisplayName, &project.RecordedAtUnixMillis, &aliases); err != nil { return nil, err } for _, alias := range aliases { project.Aliases = append(project.Aliases, situation.ProjectAlias(strings.ToLower(alias))) } projects = append(projects, project) } return projects, rows.Err() } func (r *SituationRepository) ActiveProjectFocus(ctx context.Context, actorID identity.ActorID, principalID identity.PrincipalID) (situation.ActiveProjectFocus, error) { var focus situation.ActiveProjectFocus err := r.pool.QueryRow(ctx, `SELECT actor_id,principal_id,project_id,project_display_name,provenance,confidence_millis,source_utterance_id,updated_at_unix_millis FROM situation.active_project_focus WHERE actor_id=$1 AND principal_id=$2`, actorID, principalID).Scan(&focus.ActorID, &focus.PrincipalID, &focus.ProjectID, &focus.ProjectDisplayName, &focus.Provenance, &focus.ConfidenceMillis, &focus.SourceUtteranceID, &focus.UpdatedAtUnixMillis) return focus, err } func (r *SituationRepository) SaveActiveProjectFocus(ctx context.Context, focus situation.ActiveProjectFocus) error { _, err := r.pool.Exec(ctx, `INSERT INTO situation.active_project_focus(actor_id,principal_id,project_id,project_display_name,provenance,confidence_millis,source_utterance_id,updated_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT(actor_id,principal_id) DO UPDATE SET project_id=EXCLUDED.project_id, project_display_name=EXCLUDED.project_display_name, provenance=EXCLUDED.provenance, confidence_millis=EXCLUDED.confidence_millis, source_utterance_id=EXCLUDED.source_utterance_id, updated_at_unix_millis=EXCLUDED.updated_at_unix_millis`, focus.ActorID, focus.PrincipalID, focus.ProjectID, focus.ProjectDisplayName, focus.Provenance, focus.ConfidenceMillis, focus.SourceUtteranceID, focus.UpdatedAtUnixMillis) return err }