mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
a25d85631b
Not used in coderd yet, see stack. Adds two new packages: - `coderd/usage`: provides an interface for the "Collector" as well as a stub implementation for AGPL - `enterprise/coderd/usage`: provides an interface for the "Publisher" as well as a Tallyman implementation Relates to https://github.com/coder/internal/issues/814
87 lines
3.4 KiB
SQL
87 lines
3.4 KiB
SQL
-- name: InsertUsageEvent :exec
|
|
-- Duplicate events are ignored intentionally to allow for multiple replicas to
|
|
-- publish heartbeat events.
|
|
INSERT INTO
|
|
usage_events (
|
|
id,
|
|
event_type,
|
|
event_data,
|
|
created_at,
|
|
publish_started_at,
|
|
published_at,
|
|
failure_message
|
|
)
|
|
VALUES
|
|
(@id, @event_type, @event_data, @created_at, NULL, NULL, NULL)
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- name: SelectUsageEventsForPublishing :many
|
|
WITH usage_events AS (
|
|
UPDATE
|
|
usage_events
|
|
SET
|
|
publish_started_at = @now::timestamptz
|
|
WHERE
|
|
id IN (
|
|
SELECT
|
|
potential_event.id
|
|
FROM
|
|
usage_events potential_event
|
|
WHERE
|
|
-- Do not publish events that have already been published or
|
|
-- have permanently failed to publish.
|
|
potential_event.published_at IS NULL
|
|
-- Do not publish events that are already being published by
|
|
-- another replica.
|
|
AND (
|
|
potential_event.publish_started_at IS NULL
|
|
-- If the event has publish_started_at set, it must be older
|
|
-- than an hour ago. This is so we can retry publishing
|
|
-- events where the replica exited or couldn't update the
|
|
-- row.
|
|
-- The parenthesis around @now::timestamptz are necessary to
|
|
-- avoid sqlc from generating an extra argument.
|
|
OR potential_event.publish_started_at < (@now::timestamptz) - INTERVAL '1 hour'
|
|
)
|
|
-- Do not publish events older than 30 days. Tallyman will
|
|
-- always permanently reject these events anyways. This is to
|
|
-- avoid duplicate events being billed to customers, as
|
|
-- Metronome will only deduplicate events within 34 days.
|
|
-- Also, the same parenthesis thing here as above.
|
|
AND potential_event.created_at > (@now::timestamptz) - INTERVAL '30 days'
|
|
ORDER BY potential_event.created_at ASC
|
|
FOR UPDATE SKIP LOCKED
|
|
LIMIT 100
|
|
)
|
|
RETURNING *
|
|
)
|
|
SELECT *
|
|
-- Note that this selects from the CTE, not the original table. The CTE is named
|
|
-- the same as the original table to trick sqlc into reusing the existing struct
|
|
-- for the table.
|
|
FROM usage_events
|
|
-- The CTE and the reorder is required because UPDATE doesn't guarantee order.
|
|
ORDER BY created_at ASC;
|
|
|
|
-- name: UpdateUsageEventsPostPublish :exec
|
|
UPDATE
|
|
usage_events
|
|
SET
|
|
publish_started_at = NULL,
|
|
published_at = CASE WHEN input.set_published_at THEN @now::timestamptz ELSE NULL END,
|
|
failure_message = NULLIF(input.failure_message, '')
|
|
FROM (
|
|
SELECT
|
|
UNNEST(@ids::text[]) AS id,
|
|
UNNEST(@failure_messages::text[]) AS failure_message,
|
|
UNNEST(@set_published_ats::boolean[]) AS set_published_at
|
|
) input
|
|
WHERE
|
|
input.id = usage_events.id
|
|
-- If the number of ids, failure messages, and set published ats are not the
|
|
-- same, do not do anything. Unfortunately you can't really throw from a
|
|
-- query without writing a function or doing some jank like dividing by
|
|
-- zero, so this is the best we can do.
|
|
AND cardinality(@ids::text[]) = cardinality(@failure_messages::text[])
|
|
AND cardinality(@ids::text[]) = cardinality(@set_published_ats::boolean[]);
|