forked from wrenn/wrenn
v0.2.0 (#50)
Co-authored-by: Tasnim Kabir Sadik <tksadik@omukk.dev> Reviewed-on: wrenn/wrenn#50
This commit is contained in:
@ -172,8 +172,6 @@ SELECT
|
||||
h.created_by,
|
||||
h.created_at,
|
||||
h.updated_at,
|
||||
h.cert_fingerprint,
|
||||
h.cert_expires_at,
|
||||
COALESCE(SUM(s.vcpus) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_vcpus,
|
||||
COALESCE(SUM(s.memory_mb) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_memory_mb,
|
||||
COALESCE(SUM(s.disk_size_mb) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_disk_mb,
|
||||
@ -205,8 +203,6 @@ type GetHostsWithLoadRow struct {
|
||||
CreatedBy pgtype.UUID `json:"created_by"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
CertFingerprint string `json:"cert_fingerprint"`
|
||||
CertExpiresAt pgtype.Timestamptz `json:"cert_expires_at"`
|
||||
RunningVcpus int32 `json:"running_vcpus"`
|
||||
RunningMemoryMb int32 `json:"running_memory_mb"`
|
||||
RunningDiskMb int32 `json:"running_disk_mb"`
|
||||
@ -242,8 +238,6 @@ func (q *Queries) GetHostsWithLoad(ctx context.Context) ([]GetHostsWithLoadRow,
|
||||
&i.CreatedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CertFingerprint,
|
||||
&i.CertExpiresAt,
|
||||
&i.RunningVcpus,
|
||||
&i.RunningMemoryMb,
|
||||
&i.RunningDiskMb,
|
||||
@ -427,6 +421,105 @@ func (q *Queries) ListHosts(ctx context.Context) ([]Host, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listHostsAdmin = `-- name: ListHostsAdmin :many
|
||||
SELECT
|
||||
h.id,
|
||||
h.type,
|
||||
h.team_id,
|
||||
h.provider,
|
||||
h.availability_zone,
|
||||
h.arch,
|
||||
h.cpu_cores,
|
||||
h.memory_mb,
|
||||
h.disk_gb,
|
||||
h.address,
|
||||
h.status,
|
||||
h.last_heartbeat_at,
|
||||
h.metadata,
|
||||
h.created_by,
|
||||
h.created_at,
|
||||
h.updated_at,
|
||||
COALESCE(SUM(s.vcpus) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_vcpus,
|
||||
COALESCE(SUM(s.memory_mb) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_memory_mb,
|
||||
COALESCE(SUM(s.disk_size_mb) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_disk_mb,
|
||||
COALESCE(SUM(s.memory_mb) FILTER (WHERE s.status = 'paused'), 0)::int AS paused_memory_mb,
|
||||
COALESCE(SUM(s.disk_size_mb) FILTER (WHERE s.status = 'paused'), 0)::int AS paused_disk_mb
|
||||
FROM hosts h
|
||||
LEFT JOIN sandboxes s ON s.host_id = h.id
|
||||
AND s.status IN ('running', 'paused', 'starting', 'pending')
|
||||
GROUP BY h.id
|
||||
ORDER BY h.created_at DESC
|
||||
`
|
||||
|
||||
type ListHostsAdminRow struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Type string `json:"type"`
|
||||
TeamID pgtype.UUID `json:"team_id"`
|
||||
Provider string `json:"provider"`
|
||||
AvailabilityZone string `json:"availability_zone"`
|
||||
Arch string `json:"arch"`
|
||||
CpuCores int32 `json:"cpu_cores"`
|
||||
MemoryMb int32 `json:"memory_mb"`
|
||||
DiskGb int32 `json:"disk_gb"`
|
||||
Address string `json:"address"`
|
||||
Status string `json:"status"`
|
||||
LastHeartbeatAt pgtype.Timestamptz `json:"last_heartbeat_at"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
CreatedBy pgtype.UUID `json:"created_by"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
RunningVcpus int32 `json:"running_vcpus"`
|
||||
RunningMemoryMb int32 `json:"running_memory_mb"`
|
||||
RunningDiskMb int32 `json:"running_disk_mb"`
|
||||
PausedMemoryMb int32 `json:"paused_memory_mb"`
|
||||
PausedDiskMb int32 `json:"paused_disk_mb"`
|
||||
}
|
||||
|
||||
// Returns all hosts with per-host sandbox resource consumption aggregated.
|
||||
// Unlike GetHostsWithLoad, this returns ALL hosts (not just online) so admins
|
||||
// can see resource usage across the entire fleet including offline/pending hosts.
|
||||
func (q *Queries) ListHostsAdmin(ctx context.Context) ([]ListHostsAdminRow, error) {
|
||||
rows, err := q.db.Query(ctx, listHostsAdmin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListHostsAdminRow
|
||||
for rows.Next() {
|
||||
var i ListHostsAdminRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.TeamID,
|
||||
&i.Provider,
|
||||
&i.AvailabilityZone,
|
||||
&i.Arch,
|
||||
&i.CpuCores,
|
||||
&i.MemoryMb,
|
||||
&i.DiskGb,
|
||||
&i.Address,
|
||||
&i.Status,
|
||||
&i.LastHeartbeatAt,
|
||||
&i.Metadata,
|
||||
&i.CreatedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.RunningVcpus,
|
||||
&i.RunningMemoryMb,
|
||||
&i.RunningDiskMb,
|
||||
&i.PausedMemoryMb,
|
||||
&i.PausedDiskMb,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listHostsByStatus = `-- name: ListHostsByStatus :many
|
||||
SELECT id, type, team_id, provider, availability_zone, arch, cpu_cores, memory_mb, disk_gb, address, status, last_heartbeat_at, metadata, created_by, created_at, updated_at, cert_fingerprint, cert_expires_at FROM hosts WHERE status = $1 ORDER BY created_at DESC
|
||||
`
|
||||
@ -517,18 +610,71 @@ func (q *Queries) ListHostsByTag(ctx context.Context, tag string) ([]Host, error
|
||||
}
|
||||
|
||||
const listHostsByTeam = `-- name: ListHostsByTeam :many
|
||||
SELECT id, type, team_id, provider, availability_zone, arch, cpu_cores, memory_mb, disk_gb, address, status, last_heartbeat_at, metadata, created_by, created_at, updated_at, cert_fingerprint, cert_expires_at FROM hosts WHERE team_id = $1 AND type = 'byoc' ORDER BY created_at DESC
|
||||
SELECT
|
||||
h.id,
|
||||
h.type,
|
||||
h.team_id,
|
||||
h.provider,
|
||||
h.availability_zone,
|
||||
h.arch,
|
||||
h.cpu_cores,
|
||||
h.memory_mb,
|
||||
h.disk_gb,
|
||||
h.address,
|
||||
h.status,
|
||||
h.last_heartbeat_at,
|
||||
h.metadata,
|
||||
h.created_by,
|
||||
h.created_at,
|
||||
h.updated_at,
|
||||
COALESCE(SUM(s.vcpus) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_vcpus,
|
||||
COALESCE(SUM(s.memory_mb) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_memory_mb,
|
||||
COALESCE(SUM(s.disk_size_mb) FILTER (WHERE s.status IN ('running', 'starting', 'pending')), 0)::int AS running_disk_mb,
|
||||
COALESCE(SUM(s.memory_mb) FILTER (WHERE s.status = 'paused'), 0)::int AS paused_memory_mb,
|
||||
COALESCE(SUM(s.disk_size_mb) FILTER (WHERE s.status = 'paused'), 0)::int AS paused_disk_mb
|
||||
FROM hosts h
|
||||
LEFT JOIN sandboxes s ON s.host_id = h.id
|
||||
AND s.status IN ('running', 'paused', 'starting', 'pending')
|
||||
WHERE h.team_id = $1 AND h.type = 'byoc'
|
||||
GROUP BY h.id
|
||||
ORDER BY h.created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListHostsByTeam(ctx context.Context, teamID pgtype.UUID) ([]Host, error) {
|
||||
type ListHostsByTeamRow struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Type string `json:"type"`
|
||||
TeamID pgtype.UUID `json:"team_id"`
|
||||
Provider string `json:"provider"`
|
||||
AvailabilityZone string `json:"availability_zone"`
|
||||
Arch string `json:"arch"`
|
||||
CpuCores int32 `json:"cpu_cores"`
|
||||
MemoryMb int32 `json:"memory_mb"`
|
||||
DiskGb int32 `json:"disk_gb"`
|
||||
Address string `json:"address"`
|
||||
Status string `json:"status"`
|
||||
LastHeartbeatAt pgtype.Timestamptz `json:"last_heartbeat_at"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
CreatedBy pgtype.UUID `json:"created_by"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
RunningVcpus int32 `json:"running_vcpus"`
|
||||
RunningMemoryMb int32 `json:"running_memory_mb"`
|
||||
RunningDiskMb int32 `json:"running_disk_mb"`
|
||||
PausedMemoryMb int32 `json:"paused_memory_mb"`
|
||||
PausedDiskMb int32 `json:"paused_disk_mb"`
|
||||
}
|
||||
|
||||
// Returns hosts by team with per-host sandbox resource consumption aggregated.
|
||||
// Follows the same aggregation pattern as ListHostsAdmin and GetHostsWithLoad.
|
||||
func (q *Queries) ListHostsByTeam(ctx context.Context, teamID pgtype.UUID) ([]ListHostsByTeamRow, error) {
|
||||
rows, err := q.db.Query(ctx, listHostsByTeam, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Host
|
||||
var items []ListHostsByTeamRow
|
||||
for rows.Next() {
|
||||
var i Host
|
||||
var i ListHostsByTeamRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
@ -546,8 +692,11 @@ func (q *Queries) ListHostsByTeam(ctx context.Context, teamID pgtype.UUID) ([]Ho
|
||||
&i.CreatedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CertFingerprint,
|
||||
&i.CertExpiresAt,
|
||||
&i.RunningVcpus,
|
||||
&i.RunningMemoryMb,
|
||||
&i.RunningDiskMb,
|
||||
&i.PausedMemoryMb,
|
||||
&i.PausedDiskMb,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -133,6 +133,33 @@ func (q *Queries) GetDailyUsage(ctx context.Context, arg GetDailyUsageParams) ([
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getLatestSandboxMetricPoint = `-- name: GetLatestSandboxMetricPoint :one
|
||||
SELECT ts, cpu_pct, mem_bytes, disk_bytes
|
||||
FROM sandbox_metric_points
|
||||
WHERE sandbox_id = $1
|
||||
ORDER BY ts DESC
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetLatestSandboxMetricPointRow struct {
|
||||
Ts int64 `json:"ts"`
|
||||
CpuPct float64 `json:"cpu_pct"`
|
||||
MemBytes int64 `json:"mem_bytes"`
|
||||
DiskBytes int64 `json:"disk_bytes"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetLatestSandboxMetricPoint(ctx context.Context, sandboxID pgtype.UUID) (GetLatestSandboxMetricPointRow, error) {
|
||||
row := q.db.QueryRow(ctx, getLatestSandboxMetricPoint, sandboxID)
|
||||
var i GetLatestSandboxMetricPointRow
|
||||
err := row.Scan(
|
||||
&i.Ts,
|
||||
&i.CpuPct,
|
||||
&i.MemBytes,
|
||||
&i.DiskBytes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getLiveMetrics = `-- name: GetLiveMetrics :one
|
||||
SELECT
|
||||
(COUNT(*) FILTER (WHERE status IN ('running', 'starting')))::INTEGER AS running_count,
|
||||
|
||||
@ -139,6 +139,18 @@ type SandboxMetricsSnapshot struct {
|
||||
MemoryMbReserved int32 `json:"memory_mb_reserved"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
ID string `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
TeamID pgtype.UUID `json:"team_id"`
|
||||
CsrfToken string `json:"csrf_token"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
IpAddress string `json:"ip_address"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
LastSeenAt pgtype.Timestamptz `json:"last_seen_at"`
|
||||
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
|
||||
}
|
||||
|
||||
type Team struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
||||
@ -11,17 +11,24 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const bulkRestoreRunning = `-- name: BulkRestoreRunning :exec
|
||||
const bulkRestoreMissingToStatus = `-- name: BulkRestoreMissingToStatus :exec
|
||||
UPDATE sandboxes
|
||||
SET status = 'running',
|
||||
SET status = $2,
|
||||
last_updated = NOW()
|
||||
WHERE id = ANY($1::uuid[]) AND status = 'missing'
|
||||
`
|
||||
|
||||
type BulkRestoreMissingToStatusParams struct {
|
||||
Column1 []pgtype.UUID `json:"column_1"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// Called by the reconciler when a host comes back online and its sandboxes are
|
||||
// confirmed alive. Restores only sandboxes that are in 'missing' state.
|
||||
func (q *Queries) BulkRestoreRunning(ctx context.Context, dollar_1 []pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, bulkRestoreRunning, dollar_1)
|
||||
// confirmed alive. Restores only sandboxes currently in 'missing' state to the
|
||||
// given target status (typically 'running' or 'paused' based on the live state
|
||||
// reported by the host agent's ListSandboxes RPC).
|
||||
func (q *Queries) BulkRestoreMissingToStatus(ctx context.Context, arg BulkRestoreMissingToStatusParams) error {
|
||||
_, err := q.db.Exec(ctx, bulkRestoreMissingToStatus, arg.Column1, arg.Status)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -375,7 +382,7 @@ const markSandboxesMissingByHost = `-- name: MarkSandboxesMissingByHost :exec
|
||||
UPDATE sandboxes
|
||||
SET status = 'missing',
|
||||
last_updated = NOW()
|
||||
WHERE host_id = $1 AND status IN ('running', 'starting', 'pending')
|
||||
WHERE host_id = $1 AND status IN ('running', 'starting', 'pending', 'pausing', 'resuming', 'stopping')
|
||||
`
|
||||
|
||||
// Called when the host monitor marks a host unreachable.
|
||||
@ -403,6 +410,23 @@ func (q *Queries) UpdateLastActive(ctx context.Context, arg UpdateLastActivePara
|
||||
return err
|
||||
}
|
||||
|
||||
const updateSandboxDiskSize = `-- name: UpdateSandboxDiskSize :exec
|
||||
UPDATE sandboxes
|
||||
SET disk_size_mb = $2,
|
||||
last_updated = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateSandboxDiskSizeParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
DiskSizeMb int32 `json:"disk_size_mb"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSandboxDiskSize(ctx context.Context, arg UpdateSandboxDiskSizeParams) error {
|
||||
_, err := q.db.Exec(ctx, updateSandboxDiskSize, arg.ID, arg.DiskSizeMb)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateSandboxMetadata = `-- name: UpdateSandboxMetadata :exec
|
||||
UPDATE sandboxes
|
||||
SET metadata = $2,
|
||||
@ -470,6 +494,61 @@ func (q *Queries) UpdateSandboxRunning(ctx context.Context, arg UpdateSandboxRun
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateSandboxRunningIf = `-- name: UpdateSandboxRunningIf :one
|
||||
UPDATE sandboxes
|
||||
SET status = 'running',
|
||||
host_ip = $3,
|
||||
guest_ip = $4,
|
||||
started_at = $5,
|
||||
last_active_at = $5,
|
||||
last_updated = NOW()
|
||||
WHERE id = $1 AND status = $2
|
||||
RETURNING id, team_id, host_id, template, status, vcpus, memory_mb, timeout_sec, disk_size_mb, guest_ip, host_ip, created_at, started_at, last_active_at, last_updated, template_id, template_team_id, metadata
|
||||
`
|
||||
|
||||
type UpdateSandboxRunningIfParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Status string `json:"status"`
|
||||
HostIp string `json:"host_ip"`
|
||||
GuestIp string `json:"guest_ip"`
|
||||
StartedAt pgtype.Timestamptz `json:"started_at"`
|
||||
}
|
||||
|
||||
// Conditionally transition a sandbox to running only if the current status
|
||||
// matches the expected value. Prevents races where a user destroys a sandbox
|
||||
// while the create/resume goroutine is still in-flight.
|
||||
func (q *Queries) UpdateSandboxRunningIf(ctx context.Context, arg UpdateSandboxRunningIfParams) (Sandbox, error) {
|
||||
row := q.db.QueryRow(ctx, updateSandboxRunningIf,
|
||||
arg.ID,
|
||||
arg.Status,
|
||||
arg.HostIp,
|
||||
arg.GuestIp,
|
||||
arg.StartedAt,
|
||||
)
|
||||
var i Sandbox
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TeamID,
|
||||
&i.HostID,
|
||||
&i.Template,
|
||||
&i.Status,
|
||||
&i.Vcpus,
|
||||
&i.MemoryMb,
|
||||
&i.TimeoutSec,
|
||||
&i.DiskSizeMb,
|
||||
&i.GuestIp,
|
||||
&i.HostIp,
|
||||
&i.CreatedAt,
|
||||
&i.StartedAt,
|
||||
&i.LastActiveAt,
|
||||
&i.LastUpdated,
|
||||
&i.TemplateID,
|
||||
&i.TemplateTeamID,
|
||||
&i.Metadata,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateSandboxStatus = `-- name: UpdateSandboxStatus :one
|
||||
UPDATE sandboxes
|
||||
SET status = $2,
|
||||
@ -508,3 +587,46 @@ func (q *Queries) UpdateSandboxStatus(ctx context.Context, arg UpdateSandboxStat
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateSandboxStatusIf = `-- name: UpdateSandboxStatusIf :one
|
||||
UPDATE sandboxes
|
||||
SET status = $3,
|
||||
last_updated = NOW()
|
||||
WHERE id = $1 AND status = $2
|
||||
RETURNING id, team_id, host_id, template, status, vcpus, memory_mb, timeout_sec, disk_size_mb, guest_ip, host_ip, created_at, started_at, last_active_at, last_updated, template_id, template_team_id, metadata
|
||||
`
|
||||
|
||||
type UpdateSandboxStatusIfParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Status string `json:"status"`
|
||||
Status_2 string `json:"status_2"`
|
||||
}
|
||||
|
||||
// Atomically update status only when the current status matches the expected value.
|
||||
// Prevents background goroutines from overwriting a status that has since changed
|
||||
// (e.g. user destroyed a sandbox while Create was in-flight).
|
||||
func (q *Queries) UpdateSandboxStatusIf(ctx context.Context, arg UpdateSandboxStatusIfParams) (Sandbox, error) {
|
||||
row := q.db.QueryRow(ctx, updateSandboxStatusIf, arg.ID, arg.Status, arg.Status_2)
|
||||
var i Sandbox
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TeamID,
|
||||
&i.HostID,
|
||||
&i.Template,
|
||||
&i.Status,
|
||||
&i.Vcpus,
|
||||
&i.MemoryMb,
|
||||
&i.TimeoutSec,
|
||||
&i.DiskSizeMb,
|
||||
&i.GuestIp,
|
||||
&i.HostIp,
|
||||
&i.CreatedAt,
|
||||
&i.StartedAt,
|
||||
&i.LastActiveAt,
|
||||
&i.LastUpdated,
|
||||
&i.TemplateID,
|
||||
&i.TemplateTeamID,
|
||||
&i.Metadata,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
187
pkg/db/sessions.sql.go
Normal file
187
pkg/db/sessions.sql.go
Normal file
@ -0,0 +1,187 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: sessions.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const deleteExpiredSessions = `-- name: DeleteExpiredSessions :exec
|
||||
DELETE FROM sessions WHERE expires_at < NOW()
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteExpiredSessions(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, deleteExpiredSessions)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSession = `-- name: DeleteSession :exec
|
||||
DELETE FROM sessions WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSession(ctx context.Context, id string) error {
|
||||
_, err := q.db.Exec(ctx, deleteSession, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSessionForUser = `-- name: DeleteSessionForUser :exec
|
||||
DELETE FROM sessions WHERE id = $1 AND user_id = $2
|
||||
`
|
||||
|
||||
type DeleteSessionForUserParams struct {
|
||||
ID string `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteSessionForUser(ctx context.Context, arg DeleteSessionForUserParams) error {
|
||||
_, err := q.db.Exec(ctx, deleteSessionForUser, arg.ID, arg.UserID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSessionsByUserID = `-- name: DeleteSessionsByUserID :many
|
||||
DELETE FROM sessions WHERE user_id = $1 RETURNING id
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSessionsByUserID(ctx context.Context, userID pgtype.UUID) ([]string, error) {
|
||||
rows, err := q.db.Query(ctx, deleteSessionsByUserID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []string
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSession = `-- name: GetSession :one
|
||||
SELECT id, user_id, team_id, csrf_token, user_agent, ip_address, created_at, last_seen_at, expires_at FROM sessions WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSession(ctx context.Context, id string) (Session, error) {
|
||||
row := q.db.QueryRow(ctx, getSession, id)
|
||||
var i Session
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.TeamID,
|
||||
&i.CsrfToken,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.ExpiresAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertSession = `-- name: InsertSession :one
|
||||
INSERT INTO sessions (id, user_id, team_id, csrf_token, user_agent, ip_address, expires_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id, user_id, team_id, csrf_token, user_agent, ip_address, created_at, last_seen_at, expires_at
|
||||
`
|
||||
|
||||
type InsertSessionParams struct {
|
||||
ID string `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
TeamID pgtype.UUID `json:"team_id"`
|
||||
CsrfToken string `json:"csrf_token"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
IpAddress string `json:"ip_address"`
|
||||
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertSession(ctx context.Context, arg InsertSessionParams) (Session, error) {
|
||||
row := q.db.QueryRow(ctx, insertSession,
|
||||
arg.ID,
|
||||
arg.UserID,
|
||||
arg.TeamID,
|
||||
arg.CsrfToken,
|
||||
arg.UserAgent,
|
||||
arg.IpAddress,
|
||||
arg.ExpiresAt,
|
||||
)
|
||||
var i Session
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.TeamID,
|
||||
&i.CsrfToken,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.ExpiresAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listSessionsByUserID = `-- name: ListSessionsByUserID :many
|
||||
SELECT id, user_id, team_id, csrf_token, user_agent, ip_address, created_at, last_seen_at, expires_at FROM sessions WHERE user_id = $1 ORDER BY last_seen_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListSessionsByUserID(ctx context.Context, userID pgtype.UUID) ([]Session, error) {
|
||||
rows, err := q.db.Query(ctx, listSessionsByUserID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Session
|
||||
for rows.Next() {
|
||||
var i Session
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.TeamID,
|
||||
&i.CsrfToken,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.ExpiresAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const touchSession = `-- name: TouchSession :exec
|
||||
UPDATE sessions SET last_seen_at = NOW() WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) TouchSession(ctx context.Context, id string) error {
|
||||
_, err := q.db.Exec(ctx, touchSession, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateSessionTeam = `-- name: UpdateSessionTeam :exec
|
||||
UPDATE sessions SET team_id = $2 WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateSessionTeamParams struct {
|
||||
ID string `json:"id"`
|
||||
TeamID pgtype.UUID `json:"team_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSessionTeam(ctx context.Context, arg UpdateSessionTeamParams) error {
|
||||
_, err := q.db.Exec(ctx, updateSessionTeam, arg.ID, arg.TeamID)
|
||||
return err
|
||||
}
|
||||
@ -358,7 +358,9 @@ SELECT
|
||||
COALESCE(owner_u.name, '') AS owner_name,
|
||||
COALESCE(owner_u.email, '') AS owner_email,
|
||||
(SELECT COUNT(*) FROM sandboxes s WHERE s.team_id = t.id AND s.status IN ('running', 'paused', 'starting'))::int AS active_sandbox_count,
|
||||
(SELECT COUNT(*) FROM channels c WHERE c.team_id = t.id)::int AS channel_count
|
||||
(SELECT COUNT(*) FROM channels c WHERE c.team_id = t.id)::int AS channel_count,
|
||||
COALESCE((SELECT SUM(s.vcpus) FROM sandboxes s WHERE s.team_id = t.id AND s.status IN ('running', 'paused', 'starting')), 0)::int AS running_vcpus,
|
||||
COALESCE((SELECT SUM(s.memory_mb) FROM sandboxes s WHERE s.team_id = t.id AND s.status IN ('running', 'paused', 'starting')), 0)::int AS running_memory_mb
|
||||
FROM teams t
|
||||
LEFT JOIN users_teams owner_ut ON owner_ut.team_id = t.id AND owner_ut.role = 'owner'
|
||||
LEFT JOIN users owner_u ON owner_u.id = owner_ut.user_id
|
||||
@ -384,6 +386,8 @@ type ListTeamsAdminRow struct {
|
||||
OwnerEmail string `json:"owner_email"`
|
||||
ActiveSandboxCount int32 `json:"active_sandbox_count"`
|
||||
ChannelCount int32 `json:"channel_count"`
|
||||
RunningVcpus int32 `json:"running_vcpus"`
|
||||
RunningMemoryMb int32 `json:"running_memory_mb"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListTeamsAdmin(ctx context.Context, arg ListTeamsAdminParams) ([]ListTeamsAdminRow, error) {
|
||||
@ -407,6 +411,8 @@ func (q *Queries) ListTeamsAdmin(ctx context.Context, arg ListTeamsAdminParams)
|
||||
&i.OwnerEmail,
|
||||
&i.ActiveSandboxCount,
|
||||
&i.ChannelCount,
|
||||
&i.RunningVcpus,
|
||||
&i.RunningMemoryMb,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -385,3 +385,17 @@ func (q *Queries) ListTemplatesByType(ctx context.Context, type_ string) ([]Temp
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateTemplateSize = `-- name: UpdateTemplateSize :exec
|
||||
UPDATE templates SET size_bytes = $2 WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateTemplateSizeParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
SizeBytes int64 `json:"size_bytes"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTemplateSize(ctx context.Context, arg UpdateTemplateSizeParams) error {
|
||||
_, err := q.db.Exec(ctx, updateTemplateSize, arg.ID, arg.SizeBytes)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user