Documentation
¶
Index ¶
- type Activity
- type ActivityForParams
- type AllActivityForParams
- type CancelJobParams
- type ClaimDueJobParams
- type Course
- type CourseActivityForParams
- type CourseOfParams
- type DBTX
- type DeleteCourseParams
- type Event
- type EventsBetweenParams
- type FinishJobParams
- type InsertAccessRequestParams
- type JobOfParams
- type JobsOfParams
- type Querier
- type Queries
- func (q *Queries) ActivityFor(ctx context.Context, arg ActivityForParams) ([]Activity, error)
- func (q *Queries) AllActivityFor(ctx context.Context, arg AllActivityForParams) ([]Activity, error)
- func (q *Queries) CancelJob(ctx context.Context, arg CancelJobParams) (ScheduledJob, error)
- func (q *Queries) ClaimDueJob(ctx context.Context, arg ClaimDueJobParams) (ScheduledJob, error)
- func (q *Queries) CourseActivityFor(ctx context.Context, arg CourseActivityForParams) ([]Activity, error)
- func (q *Queries) CourseOf(ctx context.Context, arg CourseOfParams) (Course, error)
- func (q *Queries) CoursesOf(ctx context.Context, owner string) ([]Course, error)
- func (q *Queries) DeleteCourse(ctx context.Context, arg DeleteCourseParams) (int64, error)
- func (q *Queries) DeleteUser(ctx context.Context, email string) (int64, error)
- func (q *Queries) DeleteUserGitLabToken(ctx context.Context, owner string) error
- func (q *Queries) EventsBetween(ctx context.Context, arg EventsBetweenParams) ([]Event, error)
- func (q *Queries) FinishJob(ctx context.Context, arg FinishJobParams) error
- func (q *Queries) GetUser(ctx context.Context, email string) (User, error)
- func (q *Queries) GetUserSecret(ctx context.Context, owner string) (UserSecret, error)
- func (q *Queries) InsertAccessRequest(ctx context.Context, arg InsertAccessRequestParams) (User, error)
- func (q *Queries) JobOf(ctx context.Context, arg JobOfParams) (ScheduledJob, error)
- func (q *Queries) JobsOf(ctx context.Context, arg JobsOfParams) ([]ScheduledJob, error)
- func (q *Queries) ListUsers(ctx context.Context) ([]User, error)
- func (q *Queries) MarkNotified(ctx context.Context, id string) error
- func (q *Queries) ReapExpiredEvents(ctx context.Context, before time.Time) (int64, error)
- func (q *Queries) ReapExpiredJobs(ctx context.Context, before time.Time) (int64, error)
- func (q *Queries) RecentEvents(ctx context.Context, arg RecentEventsParams) ([]Event, error)
- func (q *Queries) RecordActivity(ctx context.Context, arg RecordActivityParams) error
- func (q *Queries) RecordEvent(ctx context.Context, arg RecordEventParams) error
- func (q *Queries) SaveCourse(ctx context.Context, arg SaveCourseParams) error
- func (q *Queries) SaveJob(ctx context.Context, arg SaveJobParams) error
- func (q *Queries) SaveUserGitLabToken(ctx context.Context, arg SaveUserGitLabTokenParams) error
- func (q *Queries) SetSummarySentAt(ctx context.Context, summarySentAt *time.Time) error
- func (q *Queries) SetUserStatus(ctx context.Context, arg SetUserStatusParams) (User, error)
- func (q *Queries) SystemState(ctx context.Context) (SystemState, error)
- func (q *Queries) UnnotifiedTerminalJobs(ctx context.Context) ([]ScheduledJob, error)
- func (q *Queries) WithTx(tx pgx.Tx) *Queries
- type RecentEventsParams
- type RecordActivityParams
- type RecordEventParams
- type SaveCourseParams
- type SaveJobParams
- type SaveUserGitLabTokenParams
- type ScheduledJob
- type SetUserStatusParams
- type SystemState
- type User
- type UserSecret
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActivityForParams ¶
type AllActivityForParams ¶
type ClaimDueJobParams ¶
type CourseActivityForParams ¶
type CourseOfParams ¶
type DeleteCourseParams ¶
type FinishJobParams ¶
type InsertAccessRequestParams ¶ added in v3.48.0
type JobOfParams ¶
type JobsOfParams ¶
type Querier ¶
type Querier interface {
// The three reads below all take a nullable limit, because `limit null` means
// "no limit" in PostgreSQL -- exactly the `limit <= 0` case of the findActivity
// helper they replace. The GUI reads pass the cap; the audit dump passes null.
ActivityFor(ctx context.Context, arg ActivityForParams) ([]Activity, error)
AllActivityFor(ctx context.Context, arg AllActivityForParams) ([]Activity, error)
// Only one's own, only while still pending. A job already running is too late
// and another owner's job is invisible: both return no row, and the caller turns
// that into the same error. That sameness is deliberate -- "not found" must not
// become an oracle for whether someone else has a job with that id.
CancelJob(ctx context.Context, arg CancelJobParams) (ScheduledJob, error)
// The atomic claim. This single statement is what replaces a distributed lock:
// exactly one runner ever owns a given job.
//
// FOR UPDATE SKIP LOCKED is strictly stronger than the FindOneAndUpdate it
// replaces -- several runners do not queue behind each other, they take
// different jobs.
//
// Deliberately NOT wrapped in an explicit transaction. The row lock ends with
// the statement, and the flip to 'running' IS the lock. Holding a transaction
// open across the job's execution would mean minutes with a locked row and a
// pool connection tied up, which is the obvious-looking mistake here.
ClaimDueJob(ctx context.Context, arg ClaimDueJobParams) (ScheduledJob, error)
CourseActivityFor(ctx context.Context, arg CourseActivityForParams) ([]Activity, error)
CourseOf(ctx context.Context, arg CourseOfParams) (Course, error)
// Every read here takes an owner and filters on it. There is deliberately no
// query that reads a course by name alone: owner isolation is enforced by the
// shape of this file, not by remembering to add a filter at each call site.
CoursesOf(ctx context.Context, owner string) ([]Course, error)
// :execrows so the caller can tell "deleted" from "there was nothing to
// delete". Deleting another user's course must report not-found rather than
// pretending it worked.
DeleteCourse(ctx context.Context, arg DeleteCourseParams) (int64, error)
DeleteUser(ctx context.Context, email string) (int64, error)
// An update to null, not a delete of the row: the row is the anchor for the
// other per-user secrets this table is meant to grow, and removing a GitLab
// token must not take them with it. Exactly the $unset semantics.
//
// A row that does not exist matches nothing and reports success, as before: the
// caller's intent is "make sure there is none".
DeleteUserGitLabToken(ctx context.Context, owner string) error
// [since, until) -- half open on purpose. The upper bound belongs to the NEXT
// digest window; including it would mail the same event twice.
//
// Oldest first, with the id as tiebreaker. Mongo left events sharing a timestamp
// in an arbitrary order; this is a stable total order and a free improvement.
EventsBetween(ctx context.Context, arg EventsBetweenParams) ([]Event, error)
// Matching nothing is success, as before: the runner logs an error here, and a
// job the retention sweep has already removed should not produce noise.
FinishJob(ctx context.Context, arg FinishJobParams) error
GetUser(ctx context.Context, email string) (User, error)
GetUserSecret(ctx context.Context, owner string) (UserSecret, error)
// `do nothing` on a conflict, so a double click or a second tab cannot turn one
// request into two admin mails: only the insert that actually created the row
// gets a row back, the other gets pgx.ErrNoRows.
InsertAccessRequest(ctx context.Context, arg InsertAccessRequestParams) (User, error)
JobOf(ctx context.Context, arg JobOfParams) (ScheduledJob, error)
// The status list is optional: empty or null means no filter, which is what the
// GUI's unfiltered view passes. Spelled with cardinality rather than a second
// query so there is one ordering to keep correct.
JobsOf(ctx context.Context, arg JobsOfParams) ([]ScheduledJob, error)
// Open requests first (they are what an admin comes here for), then everyone
// else; newest request first within each group.
ListUsers(ctx context.Context) ([]User, error)
MarkNotified(ctx context.Context, id string) error
// The replacement for Mongo's TTL index on at: the monitoring trail is a rolling
// window, not a permanent archive.
ReapExpiredEvents(ctx context.Context, before time.Time) (int64, error)
// The replacement for Mongo's TTL index on finished_at. `finished_at is null`
// falls out of the comparison on its own, so pending and running jobs are never
// reaped -- exactly what the partial TTL index did.
ReapExpiredJobs(ctx context.Context, before time.Time) (int64, error)
// The admin page's live feed. A null limit means unlimited, as with activity.
RecentEvents(ctx context.Context, arg RecentEventsParams) ([]Event, error)
RecordActivity(ctx context.Context, arg RecordActivityParams) error
RecordEvent(ctx context.Context, arg RecordEventParams) error
// An upsert on the key, replacing the whole row -- what ReplaceOne(upsert) did.
// imported_at is included on purpose: the caller carries it on the struct and a
// replace has to write it back, or editing a course would reset when it was
// imported.
SaveCourse(ctx context.Context, arg SaveCourseParams) error
SaveJob(ctx context.Context, arg SaveJobParams) error
// The column list is what makes this touch only the gitlab fields: other
// secrets on the row survive. In Mongo that was a $set of three named keys and
// depended on remembering to name them.
SaveUserGitLabToken(ctx context.Context, arg SaveUserGitLabTokenParams) error
// Self-healing: the row is seeded by the migration, but an upsert means a
// vanished row does not turn the nightly digest into a permanent failure.
SetSummarySentAt(ctx context.Context, summarySentAt *time.Time) error
SetUserStatus(ctx context.Context, arg SetUserStatusParams) (User, error)
SystemState(ctx context.Context) (SystemState, error)
// The runner's notify sweep, across all owners: one mail per finished job.
// Cancelled is excluded -- the user did that on purpose and there is no mail for
// it. This is what makes "mail on every terminal state" survive a crash between
// finishing a job and mailing it.
UnnotifiedTerminalJobs(ctx context.Context) ([]ScheduledJob, error)
}
type Queries ¶
type Queries struct {
// contains filtered or unexported fields
}
func (*Queries) ActivityFor ¶
The three reads below all take a nullable limit, because `limit null` means "no limit" in PostgreSQL -- exactly the `limit <= 0` case of the findActivity helper they replace. The GUI reads pass the cap; the audit dump passes null.
func (*Queries) AllActivityFor ¶
func (*Queries) CancelJob ¶
func (q *Queries) CancelJob(ctx context.Context, arg CancelJobParams) (ScheduledJob, error)
Only one's own, only while still pending. A job already running is too late and another owner's job is invisible: both return no row, and the caller turns that into the same error. That sameness is deliberate -- "not found" must not become an oracle for whether someone else has a job with that id.
func (*Queries) ClaimDueJob ¶
func (q *Queries) ClaimDueJob(ctx context.Context, arg ClaimDueJobParams) (ScheduledJob, error)
The atomic claim. This single statement is what replaces a distributed lock: exactly one runner ever owns a given job.
FOR UPDATE SKIP LOCKED is strictly stronger than the FindOneAndUpdate it replaces -- several runners do not queue behind each other, they take different jobs.
Deliberately NOT wrapped in an explicit transaction. The row lock ends with the statement, and the flip to 'running' IS the lock. Holding a transaction open across the job's execution would mean minutes with a locked row and a pool connection tied up, which is the obvious-looking mistake here.
func (*Queries) CourseActivityFor ¶
func (*Queries) CoursesOf ¶
Every read here takes an owner and filters on it. There is deliberately no query that reads a course by name alone: owner isolation is enforced by the shape of this file, not by remembering to add a filter at each call site.
func (*Queries) DeleteCourse ¶
:execrows so the caller can tell "deleted" from "there was nothing to delete". Deleting another user's course must report not-found rather than pretending it worked.
func (*Queries) DeleteUser ¶ added in v3.48.0
func (*Queries) DeleteUserGitLabToken ¶
An update to null, not a delete of the row: the row is the anchor for the other per-user secrets this table is meant to grow, and removing a GitLab token must not take them with it. Exactly the $unset semantics.
A row that does not exist matches nothing and reports success, as before: the caller's intent is "make sure there is none".
func (*Queries) EventsBetween ¶
[since, until) -- half open on purpose. The upper bound belongs to the NEXT digest window; including it would mail the same event twice.
Oldest first, with the id as tiebreaker. Mongo left events sharing a timestamp in an arbitrary order; this is a stable total order and a free improvement.
func (*Queries) FinishJob ¶
func (q *Queries) FinishJob(ctx context.Context, arg FinishJobParams) error
Matching nothing is success, as before: the runner logs an error here, and a job the retention sweep has already removed should not produce noise.
func (*Queries) GetUserSecret ¶
func (*Queries) InsertAccessRequest ¶ added in v3.48.0
func (q *Queries) InsertAccessRequest(ctx context.Context, arg InsertAccessRequestParams) (User, error)
`do nothing` on a conflict, so a double click or a second tab cannot turn one request into two admin mails: only the insert that actually created the row gets a row back, the other gets pgx.ErrNoRows.
func (*Queries) JobOf ¶
func (q *Queries) JobOf(ctx context.Context, arg JobOfParams) (ScheduledJob, error)
func (*Queries) JobsOf ¶
func (q *Queries) JobsOf(ctx context.Context, arg JobsOfParams) ([]ScheduledJob, error)
The status list is optional: empty or null means no filter, which is what the GUI's unfiltered view passes. Spelled with cardinality rather than a second query so there is one ordering to keep correct.
func (*Queries) ListUsers ¶ added in v3.48.0
Open requests first (they are what an admin comes here for), then everyone else; newest request first within each group.
func (*Queries) ReapExpiredEvents ¶
The replacement for Mongo's TTL index on at: the monitoring trail is a rolling window, not a permanent archive.
func (*Queries) ReapExpiredJobs ¶
The replacement for Mongo's TTL index on finished_at. `finished_at is null` falls out of the comparison on its own, so pending and running jobs are never reaped -- exactly what the partial TTL index did.
func (*Queries) RecentEvents ¶
The admin page's live feed. A null limit means unlimited, as with activity.
func (*Queries) RecordActivity ¶
func (q *Queries) RecordActivity(ctx context.Context, arg RecordActivityParams) error
func (*Queries) RecordEvent ¶
func (q *Queries) RecordEvent(ctx context.Context, arg RecordEventParams) error
func (*Queries) SaveCourse ¶
func (q *Queries) SaveCourse(ctx context.Context, arg SaveCourseParams) error
An upsert on the key, replacing the whole row -- what ReplaceOne(upsert) did. imported_at is included on purpose: the caller carries it on the struct and a replace has to write it back, or editing a course would reset when it was imported.
func (*Queries) SaveUserGitLabToken ¶
func (q *Queries) SaveUserGitLabToken(ctx context.Context, arg SaveUserGitLabTokenParams) error
The column list is what makes this touch only the gitlab fields: other secrets on the row survive. In Mongo that was a $set of three named keys and depended on remembering to name them.
func (*Queries) SetSummarySentAt ¶
Self-healing: the row is seeded by the migration, but an upsert means a vanished row does not turn the nightly digest into a permanent failure.
func (*Queries) SetUserStatus ¶ added in v3.48.0
func (*Queries) SystemState ¶
func (q *Queries) SystemState(ctx context.Context) (SystemState, error)
func (*Queries) UnnotifiedTerminalJobs ¶
func (q *Queries) UnnotifiedTerminalJobs(ctx context.Context) ([]ScheduledJob, error)
The runner's notify sweep, across all owners: one mail per finished job. Cancelled is excluded -- the user did that on purpose and there is no mail for it. This is what makes "mail on every terminal state" survive a crash between finishing a job and mailing it.
type RecentEventsParams ¶
type RecordActivityParams ¶
type RecordEventParams ¶
type SaveCourseParams ¶
type SaveJobParams ¶
type SaveJobParams struct {
ID string
Owner string
Op string
Course string
Assignment string
OnlyFor []string
Params []byte
RunAt time.Time
ConfigHash string
Status string
GraceMinutes int
CreatedAt time.Time
StartedAt *time.Time
FinishedAt *time.Time
Log string
Err string
Notified bool
WorkerID string
}
type ScheduledJob ¶
type ScheduledJob struct {
ID string
Owner string
Op string
Course string
Assignment string
OnlyFor []string
Params []byte
RunAt time.Time
ConfigHash string
Status string
GraceMinutes int
CreatedAt time.Time
StartedAt *time.Time
FinishedAt *time.Time
Log string
Err string
Notified bool
WorkerID string
}