diff --git a/internal/manager/persistence/sqlc/query_workers.sql b/internal/manager/persistence/sqlc/query_workers.sql index a2d6713c..f34179a0 100644 --- a/internal/manager/persistence/sqlc/query_workers.sql +++ b/internal/manager/persistence/sqlc/query_workers.sql @@ -2,6 +2,44 @@ -- Worker queries -- +-- name: CreateWorker :one +INSERT INTO workers ( + created_at, + uuid, + secret, + name, + address, + platform, + software, + status, + last_seen_at, + status_requested, + lazy_status_request, + supported_task_types, + deleted_at, + can_restart +) values ( + @created_at, + @uuid, + @secret, + @name, + @address, + @platform, + @software, + @status, + @last_seen_at, + @status_requested, + @lazy_status_request, + @supported_task_types, + @deleted_at, + @can_restart +) +RETURNING id; + +-- name: AddWorkerTagMembership :exec +INSERT INTO worker_tag_membership (worker_tag_id, worker_id) +VALUES (@worker_tag_id, @worker_id); + -- name: FetchWorker :one -- FetchWorker only returns the worker if it wasn't soft-deleted. SELECT * FROM workers WHERE workers.uuid = @uuid and deleted_at is NULL; diff --git a/internal/manager/persistence/sqlc/query_workers.sql.go b/internal/manager/persistence/sqlc/query_workers.sql.go index 8d7c8682..0f652889 100644 --- a/internal/manager/persistence/sqlc/query_workers.sql.go +++ b/internal/manager/persistence/sqlc/query_workers.sql.go @@ -7,15 +7,106 @@ package sqlc import ( "context" + "database/sql" + "time" ) -const fetchWorker = `-- name: FetchWorker :one - -SELECT id, created_at, updated_at, uuid, secret, name, address, platform, software, status, last_seen_at, status_requested, lazy_status_request, supported_task_types, deleted_at, can_restart FROM workers WHERE workers.uuid = ?1 and deleted_at is NULL +const addWorkerTagMembership = `-- name: AddWorkerTagMembership :exec +INSERT INTO worker_tag_membership (worker_tag_id, worker_id) +VALUES (?1, ?2) ` +type AddWorkerTagMembershipParams struct { + WorkerTagID int64 + WorkerID int64 +} + +func (q *Queries) AddWorkerTagMembership(ctx context.Context, arg AddWorkerTagMembershipParams) error { + _, err := q.db.ExecContext(ctx, addWorkerTagMembership, arg.WorkerTagID, arg.WorkerID) + return err +} + +const createWorker = `-- name: CreateWorker :one + +INSERT INTO workers ( + created_at, + uuid, + secret, + name, + address, + platform, + software, + status, + last_seen_at, + status_requested, + lazy_status_request, + supported_task_types, + deleted_at, + can_restart +) values ( + ?1, + ?2, + ?3, + ?4, + ?5, + ?6, + ?7, + ?8, + ?9, + ?10, + ?11, + ?12, + ?13, + ?14 +) +RETURNING id +` + +type CreateWorkerParams struct { + CreatedAt time.Time + UUID string + Secret string + Name string + Address string + Platform string + Software string + Status string + LastSeenAt sql.NullTime + StatusRequested string + LazyStatusRequest bool + SupportedTaskTypes string + DeletedAt sql.NullTime + CanRestart bool +} + // Worker queries // +func (q *Queries) CreateWorker(ctx context.Context, arg CreateWorkerParams) (int64, error) { + row := q.db.QueryRowContext(ctx, createWorker, + arg.CreatedAt, + arg.UUID, + arg.Secret, + arg.Name, + arg.Address, + arg.Platform, + arg.Software, + arg.Status, + arg.LastSeenAt, + arg.StatusRequested, + arg.LazyStatusRequest, + arg.SupportedTaskTypes, + arg.DeletedAt, + arg.CanRestart, + ) + var id int64 + err := row.Scan(&id) + return id, err +} + +const fetchWorker = `-- name: FetchWorker :one +SELECT id, created_at, updated_at, uuid, secret, name, address, platform, software, status, last_seen_at, status_requested, lazy_status_request, supported_task_types, deleted_at, can_restart FROM workers WHERE workers.uuid = ?1 and deleted_at is NULL +` + // FetchWorker only returns the worker if it wasn't soft-deleted. func (q *Queries) FetchWorker(ctx context.Context, uuid string) (Worker, error) { row := q.db.QueryRowContext(ctx, fetchWorker, uuid) diff --git a/internal/manager/persistence/workers.go b/internal/manager/persistence/workers.go index 50e5a176..0907556e 100644 --- a/internal/manager/persistence/workers.go +++ b/internal/manager/persistence/workers.go @@ -4,6 +4,7 @@ package persistence import ( "context" + "database/sql" "fmt" "strings" "time" @@ -67,9 +68,50 @@ func (w *Worker) StatusChangeClear() { } func (db *DB) CreateWorker(ctx context.Context, w *Worker) error { - if err := db.gormDB.WithContext(ctx).Create(w).Error; err != nil { + queries, err := db.queries() + if err != nil { + return err + } + + now := db.now().Time + workerID, err := queries.CreateWorker(ctx, sqlc.CreateWorkerParams{ + CreatedAt: now, + UUID: w.UUID, + Secret: w.Secret, + Name: w.Name, + Address: w.Address, + Platform: w.Platform, + Software: w.Software, + Status: string(w.Status), + LastSeenAt: sql.NullTime{ + Time: w.LastSeenAt, + Valid: !w.LastSeenAt.IsZero(), + }, + StatusRequested: string(w.StatusRequested), + LazyStatusRequest: w.LazyStatusRequest, + SupportedTaskTypes: w.SupportedTaskTypes, + DeletedAt: sql.NullTime(w.DeletedAt), + CanRestart: w.CanRestart, + }) + if err != nil { return fmt.Errorf("creating new worker: %w", err) } + + w.ID = uint(workerID) + w.CreatedAt = now + + // TODO: remove the create-with-tags functionality to a higher-level function. + // This code is just here to make this function work like the GORM code did. + for _, tag := range w.Tags { + err := queries.AddWorkerTagMembership(ctx, sqlc.AddWorkerTagMembershipParams{ + WorkerTagID: int64(tag.ID), + WorkerID: workerID, + }) + if err != nil { + return err + } + } + return nil } diff --git a/internal/manager/persistence/workers_test.go b/internal/manager/persistence/workers_test.go index 53afd19d..2d37d5fc 100644 --- a/internal/manager/persistence/workers_test.go +++ b/internal/manager/persistence/workers_test.go @@ -38,6 +38,7 @@ func TestCreateFetchWorker(t *testing.T) { err = db.CreateWorker(ctx, &w) require.NoError(t, err) + assert.NotZero(t, w.ID) fetchedWorker, err = db.FetchWorker(ctx, w.UUID) require.NoError(t, err) @@ -50,6 +51,7 @@ func TestCreateFetchWorker(t *testing.T) { assert.Equal(t, w.Platform, fetchedWorker.Platform) assert.Equal(t, w.Software, fetchedWorker.Software) assert.Equal(t, w.Status, fetchedWorker.Status) + assert.False(t, fetchedWorker.DeletedAt.Valid) assert.EqualValues(t, w.SupportedTaskTypes, fetchedWorker.SupportedTaskTypes) }