mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-08 01:16:45 +08:00
* MUL-6625: enforce prepaid member seat capacity
Co-authored-by: multica-agent <[email protected]>
* fix(seat-capacity): address review findings
Co-authored-by: multica-agent <[email protected]>
* fix(seat-capacity): close retry and worker races
Co-authored-by: multica-agent <[email protected]>
* fix(seat-capacity): bound lock waits during rollback
Co-authored-by: multica-agent <[email protected]>
* fix(seat-capacity): pin the cross-repo confirm settlement budget
Multica Cloud must wait longer than this worker's whole retry budget before it
treats a member row as one its ledger never recorded; adopting a member whose
confirm is still retrying counts one person as two seats, and an over-estimate
is what asks a customer to buy seats they do not owe.
That budget was only implicit here — 10 attempts of exponential backoff plus a
tick and a lock wait each — and Cloud's horizon had been set from a single
retry. Extract the backoff into retryBackoff, expose SettlementBudget, and
assert the worst case (29m15s) stays inside Cloud's 45m horizon, so raising
maxAttempts or the backoff cap fails review here instead of widening the window
in which Cloud cannot quantify a ledger.
Co-authored-by: multica-agent <[email protected]>
* Revert "fix(seat-capacity): pin the cross-repo confirm settlement budget"
This reverts commit d0ec36f647.
Co-authored-by: multica-agent <[email protected]>
---------
Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
227 lines
6.4 KiB
Go
227 lines
6.4 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: share_link.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const claimShareLinkByID = `-- name: ClaimShareLinkByID :one
|
|
UPDATE workspace_share_link
|
|
SET use_count = use_count + 1
|
|
WHERE id = $1
|
|
AND is_active = true
|
|
AND (expires_at IS NULL OR expires_at > now())
|
|
AND (max_uses IS NULL OR use_count < max_uses)
|
|
RETURNING id, workspace_id, code, created_by, role, expires_at, max_uses, use_count, is_active, created_at
|
|
`
|
|
|
|
// The caller first resolves the opaque code and then atomically consumes the
|
|
// non-secret row ID. The conditional UPDATE revalidates validity and the use
|
|
// limit so a join cannot race past revocation or expiry.
|
|
func (q *Queries) ClaimShareLinkByID(ctx context.Context, id pgtype.UUID) (WorkspaceShareLink, error) {
|
|
row := q.db.QueryRow(ctx, claimShareLinkByID, id)
|
|
var i WorkspaceShareLink
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.Code,
|
|
&i.CreatedBy,
|
|
&i.Role,
|
|
&i.ExpiresAt,
|
|
&i.MaxUses,
|
|
&i.UseCount,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const createShareLink = `-- name: CreateShareLink :one
|
|
INSERT INTO workspace_share_link (workspace_id, code, created_by, role, expires_at, max_uses)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
RETURNING id, workspace_id, code, created_by, role, expires_at, max_uses, use_count, is_active, created_at
|
|
`
|
|
|
|
type CreateShareLinkParams struct {
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
Code string `json:"code"`
|
|
CreatedBy pgtype.UUID `json:"created_by"`
|
|
Role string `json:"role"`
|
|
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
|
|
MaxUses pgtype.Int4 `json:"max_uses"`
|
|
}
|
|
|
|
func (q *Queries) CreateShareLink(ctx context.Context, arg CreateShareLinkParams) (WorkspaceShareLink, error) {
|
|
row := q.db.QueryRow(ctx, createShareLink,
|
|
arg.WorkspaceID,
|
|
arg.Code,
|
|
arg.CreatedBy,
|
|
arg.Role,
|
|
arg.ExpiresAt,
|
|
arg.MaxUses,
|
|
)
|
|
var i WorkspaceShareLink
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.Code,
|
|
&i.CreatedBy,
|
|
&i.Role,
|
|
&i.ExpiresAt,
|
|
&i.MaxUses,
|
|
&i.UseCount,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const deactivateWorkspaceShareLinks = `-- name: DeactivateWorkspaceShareLinks :exec
|
|
UPDATE workspace_share_link
|
|
SET is_active = false
|
|
WHERE workspace_id = $1 AND is_active = true
|
|
`
|
|
|
|
func (q *Queries) DeactivateWorkspaceShareLinks(ctx context.Context, workspaceID pgtype.UUID) error {
|
|
_, err := q.db.Exec(ctx, deactivateWorkspaceShareLinks, workspaceID)
|
|
return err
|
|
}
|
|
|
|
const getActiveShareLinkByCode = `-- name: GetActiveShareLinkByCode :one
|
|
SELECT id, workspace_id, code, created_by, role, expires_at, max_uses, use_count, is_active, created_at FROM workspace_share_link
|
|
WHERE code = $1
|
|
AND is_active = true
|
|
AND (expires_at IS NULL OR expires_at > now())
|
|
AND (max_uses IS NULL OR use_count < max_uses)
|
|
`
|
|
|
|
func (q *Queries) GetActiveShareLinkByCode(ctx context.Context, code string) (WorkspaceShareLink, error) {
|
|
row := q.db.QueryRow(ctx, getActiveShareLinkByCode, code)
|
|
var i WorkspaceShareLink
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.Code,
|
|
&i.CreatedBy,
|
|
&i.Role,
|
|
&i.ExpiresAt,
|
|
&i.MaxUses,
|
|
&i.UseCount,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getShareLinkInfoByCode = `-- name: GetShareLinkInfoByCode :one
|
|
SELECT wsl.role,
|
|
w.name AS workspace_name,
|
|
w.slug AS workspace_slug,
|
|
u.name AS creator_name
|
|
FROM workspace_share_link wsl
|
|
JOIN workspace w ON w.id = wsl.workspace_id
|
|
JOIN "user" u ON u.id = wsl.created_by
|
|
WHERE wsl.code = $1 AND wsl.is_active = true
|
|
AND (wsl.expires_at IS NULL OR wsl.expires_at > now())
|
|
AND (wsl.max_uses IS NULL OR wsl.use_count < wsl.max_uses)
|
|
`
|
|
|
|
type GetShareLinkInfoByCodeRow struct {
|
|
Role string `json:"role"`
|
|
WorkspaceName string `json:"workspace_name"`
|
|
WorkspaceSlug string `json:"workspace_slug"`
|
|
CreatorName string `json:"creator_name"`
|
|
}
|
|
|
|
func (q *Queries) GetShareLinkInfoByCode(ctx context.Context, code string) (GetShareLinkInfoByCodeRow, error) {
|
|
row := q.db.QueryRow(ctx, getShareLinkInfoByCode, code)
|
|
var i GetShareLinkInfoByCodeRow
|
|
err := row.Scan(
|
|
&i.Role,
|
|
&i.WorkspaceName,
|
|
&i.WorkspaceSlug,
|
|
&i.CreatorName,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listShareLinksByWorkspace = `-- name: ListShareLinksByWorkspace :many
|
|
SELECT wsl.id, wsl.workspace_id, wsl.code, wsl.created_by, wsl.role, wsl.expires_at, wsl.max_uses, wsl.use_count, wsl.is_active, wsl.created_at,
|
|
u.name AS creator_name,
|
|
u.email AS creator_email
|
|
FROM workspace_share_link wsl
|
|
JOIN "user" u ON u.id = wsl.created_by
|
|
WHERE wsl.workspace_id = $1 AND wsl.is_active = true
|
|
ORDER BY wsl.created_at DESC
|
|
`
|
|
|
|
type ListShareLinksByWorkspaceRow struct {
|
|
ID pgtype.UUID `json:"id"`
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
Code string `json:"code"`
|
|
CreatedBy pgtype.UUID `json:"created_by"`
|
|
Role string `json:"role"`
|
|
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
|
|
MaxUses pgtype.Int4 `json:"max_uses"`
|
|
UseCount int32 `json:"use_count"`
|
|
IsActive bool `json:"is_active"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
CreatorName string `json:"creator_name"`
|
|
CreatorEmail string `json:"creator_email"`
|
|
}
|
|
|
|
func (q *Queries) ListShareLinksByWorkspace(ctx context.Context, workspaceID pgtype.UUID) ([]ListShareLinksByWorkspaceRow, error) {
|
|
rows, err := q.db.Query(ctx, listShareLinksByWorkspace, workspaceID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListShareLinksByWorkspaceRow{}
|
|
for rows.Next() {
|
|
var i ListShareLinksByWorkspaceRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.Code,
|
|
&i.CreatedBy,
|
|
&i.Role,
|
|
&i.ExpiresAt,
|
|
&i.MaxUses,
|
|
&i.UseCount,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
&i.CreatorName,
|
|
&i.CreatorEmail,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const revokeShareLink = `-- name: RevokeShareLink :exec
|
|
UPDATE workspace_share_link
|
|
SET is_active = false
|
|
WHERE id = $1 AND workspace_id = $2
|
|
`
|
|
|
|
type RevokeShareLinkParams struct {
|
|
ID pgtype.UUID `json:"id"`
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
}
|
|
|
|
func (q *Queries) RevokeShareLink(ctx context.Context, arg RevokeShareLinkParams) error {
|
|
_, err := q.db.Exec(ctx, revokeShareLink, arg.ID, arg.WorkspaceID)
|
|
return err
|
|
}
|