// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: notifications.sql package db import ( "context" "database/sql" ) const claimDueNotification = `-- name: ClaimDueNotification :one UPDATE notification_outbox SET next_attempt_at = ?1, updated_at = ?2 WHERE id = ( SELECT id FROM notification_outbox WHERE status = 'pending' AND next_attempt_at <= ?2 ORDER BY next_attempt_at, id LIMIT 1 ) RETURNING id, event_key, channel, payload, status, attempts, next_attempt_at, last_error, created_at, updated_at ` type ClaimDueNotificationParams struct { LeaseUntil sql.NullString Now string } // Leases the pending notification due longest ago by moving its // next_attempt_at to lease_until, and returns it. A claimed row is not due // again until the lease ends, so no other claim takes it while it is being // delivered. Returns sql.ErrNoRows when none is due. func (q *Queries) ClaimDueNotification(ctx context.Context, arg ClaimDueNotificationParams) (NotificationOutbox, error) { row := q.db.QueryRowContext(ctx, claimDueNotification, arg.LeaseUntil, arg.Now) var i NotificationOutbox err := row.Scan( &i.ID, &i.EventKey, &i.Channel, &i.Payload, &i.Status, &i.Attempts, &i.NextAttemptAt, &i.LastError, &i.CreatedAt, &i.UpdatedAt, ) return i, err } const failNotification = `-- name: FailNotification :execrows UPDATE notification_outbox SET status = 'failed', attempts = attempts + ?1, next_attempt_at = NULL, last_error = ?2, updated_at = ?3 WHERE id = ?4 AND status = 'pending' AND next_attempt_at = ?5 ` type FailNotificationParams struct { Attempted int64 LastError sql.NullString Now string ID string LeaseUntil sql.NullString } // Gives up on a notification. attempts counts the delivery attempt that // failed, if one was made. The lease must still be the claim's. func (q *Queries) FailNotification(ctx context.Context, arg FailNotificationParams) (int64, error) { result, err := q.db.ExecContext(ctx, failNotification, arg.Attempted, arg.LastError, arg.Now, arg.ID, arg.LeaseUntil, ) if err != nil { return 0, err } return result.RowsAffected() } const getNotificationPref = `-- name: GetNotificationPref :one SELECT event, push, chat, created_at, updated_at FROM notification_prefs WHERE event = ? ` func (q *Queries) GetNotificationPref(ctx context.Context, event string) (NotificationPref, error) { row := q.db.QueryRowContext(ctx, getNotificationPref, event) var i NotificationPref err := row.Scan( &i.Event, &i.Push, &i.Chat, &i.CreatedAt, &i.UpdatedAt, ) return i, err } const hasNotificationSince = `-- name: HasNotificationSince :one SELECT EXISTS ( SELECT 1 FROM notification_outbox WHERE CAST(?1 AS TEXT) IS NULL OR created_at > CAST(?1 AS TEXT) ) AS found ` // Reports whether a notification was stored after since, or at all when // since is NULL. func (q *Queries) HasNotificationSince(ctx context.Context, since sql.NullString) (bool, error) { row := q.db.QueryRowContext(ctx, hasNotificationSince, since) var found bool err := row.Scan(&found) return found, err } const insertNotification = `-- name: InsertNotification :execrows INSERT INTO notification_outbox ( id, event_key, channel, payload, status, attempts, next_attempt_at, created_at, updated_at ) VALUES ( ?1, ?2, ?3, ?4, 'pending', 0, ?5, ?6, ?6 ) ON CONFLICT (event_key, channel) DO NOTHING ` type InsertNotificationParams struct { ID string EventKey string Channel string Payload string NextAttemptAt sql.NullString Now string } // Stores a pending notification for one channel, due at once. A row already // stored for the event key and channel, in any status, is left unchanged and // no row is inserted. func (q *Queries) InsertNotification(ctx context.Context, arg InsertNotificationParams) (int64, error) { result, err := q.db.ExecContext(ctx, insertNotification, arg.ID, arg.EventKey, arg.Channel, arg.Payload, arg.NextAttemptAt, arg.Now, ) if err != nil { return 0, err } return result.RowsAffected() } const listNotificationPrefs = `-- name: ListNotificationPrefs :many SELECT event, push, chat, created_at, updated_at FROM notification_prefs ` func (q *Queries) ListNotificationPrefs(ctx context.Context) ([]NotificationPref, error) { rows, err := q.db.QueryContext(ctx, listNotificationPrefs) if err != nil { return nil, err } defer rows.Close() var items []NotificationPref for rows.Next() { var i NotificationPref if err := rows.Scan( &i.Event, &i.Push, &i.Chat, &i.CreatedAt, &i.UpdatedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listRecentNotifications = `-- name: ListRecentNotifications :many SELECT o.event_key, o.payload, o.created_at FROM notification_outbox o WHERE o.id = ( SELECT i.id FROM notification_outbox i WHERE i.event_key = o.event_key ORDER BY i.created_at DESC, i.id DESC LIMIT 1 ) ORDER BY o.created_at DESC, o.event_key DESC LIMIT ?1 ` type ListRecentNotificationsRow struct { EventKey string Payload string CreatedAt string } // Returns the last lim distinct events stored, newest first: one row per // event key, the last stored for it whatever its channel, so an event // stored for push and Google Chat is one row. The last, because a channel // switched on later can store the same event key again, and // HasNotificationSince counts that row: an event is as new as its newest // row, so marking it seen also covers that row. func (q *Queries) ListRecentNotifications(ctx context.Context, lim int64) ([]ListRecentNotificationsRow, error) { rows, err := q.db.QueryContext(ctx, listRecentNotifications, lim) if err != nil { return nil, err } defer rows.Close() var items []ListRecentNotificationsRow for rows.Next() { var i ListRecentNotificationsRow if err := rows.Scan(&i.EventKey, &i.Payload, &i.CreatedAt); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const markNotificationSent = `-- name: MarkNotificationSent :execrows UPDATE notification_outbox SET status = 'sent', attempts = attempts + 1, next_attempt_at = NULL, updated_at = ?1 WHERE id = ?2 AND status = 'pending' AND next_attempt_at = ?3 ` type MarkNotificationSentParams struct { Now string ID string LeaseUntil sql.NullString } // Records a delivered notification; updated_at is when it was sent. The // lease must still be the claim's. func (q *Queries) MarkNotificationSent(ctx context.Context, arg MarkNotificationSentParams) (int64, error) { result, err := q.db.ExecContext(ctx, markNotificationSent, arg.Now, arg.ID, arg.LeaseUntil) if err != nil { return 0, err } return result.RowsAffected() } const nextNotificationDue = `-- name: NextNotificationDue :one SELECT next_attempt_at FROM notification_outbox WHERE status = 'pending' ORDER BY next_attempt_at LIMIT 1 ` // Returns when the next pending notification is due. Returns sql.ErrNoRows // when none is pending. func (q *Queries) NextNotificationDue(ctx context.Context) (sql.NullString, error) { row := q.db.QueryRowContext(ctx, nextNotificationDue) var next_attempt_at sql.NullString err := row.Scan(&next_attempt_at) return next_attempt_at, err } const retryNotification = `-- name: RetryNotification :execrows UPDATE notification_outbox SET attempts = attempts + 1, next_attempt_at = ?1, last_error = ?2, updated_at = ?3 WHERE id = ?4 AND status = 'pending' AND next_attempt_at = ?5 ` type RetryNotificationParams struct { NextAttemptAt sql.NullString LastError sql.NullString Now string ID string LeaseUntil sql.NullString } // Records a failed delivery and when to try again. The lease must still be // the claim's. func (q *Queries) RetryNotification(ctx context.Context, arg RetryNotificationParams) (int64, error) { result, err := q.db.ExecContext(ctx, retryNotification, arg.NextAttemptAt, arg.LastError, arg.Now, arg.ID, arg.LeaseUntil, ) if err != nil { return 0, err } return result.RowsAffected() } const updateNotificationPref = `-- name: UpdateNotificationPref :execrows UPDATE notification_prefs SET push = ?, chat = ?, updated_at = ? WHERE event = ? ` type UpdateNotificationPrefParams struct { Push int64 Chat int64 UpdatedAt string Event string } // Sets which channels an event goes to; affects no row when the event has // no preference row. func (q *Queries) UpdateNotificationPref(ctx context.Context, arg UpdateNotificationPrefParams) (int64, error) { result, err := q.db.ExecContext(ctx, updateNotificationPref, arg.Push, arg.Chat, arg.UpdatedAt, arg.Event, ) if err != nil { return 0, err } return result.RowsAffected() }