Skip to content

Commit

Permalink
Add persistence.CreatePreservationTask() method
Browse files Browse the repository at this point in the history
- Add `CreatePreservationTask()` to the ent client
- Add `CreatePreservationTask()` to the persistence service
- Regenerate the persistence service mocks
- Add a `convertPreservationTask()` function to convert a
  `db.PreservationTask` to a `datatype.PreservationTask` struct
  • Loading branch information
djjuhasz committed Mar 28, 2024
1 parent 94e767e commit e584c2d
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 14 deletions.
51 changes: 38 additions & 13 deletions internal/persistence/ent/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,52 @@ func setUpClient(t *testing.T, logger logr.Logger) (*db.Client, persistence.Serv
return entc, c
}

func createPackage(
entc *db.Client,
name string,
status enums.PackageStatus,
) (*db.Pkg, error) {
runID := uuid.MustParse("aee9644d-6397-4b34-92f7-442ad3dd3b13")
aipID := uuid.MustParse("30223842-0650-4f79-80bd-7bf43b810656")

return entc.Pkg.Create().
SetName(name).
SetWorkflowID("12345").
SetRunID(runID).
SetAipID(aipID).
SetStatus(int8(status)).
Save(context.Background())
}

func createPreservationAction(
entc *db.Client,
pkgID int,
status enums.PreservationActionStatus,
) (*db.PreservationAction, error) {
return entc.PreservationAction.Create().
SetWorkflowID("12345").
SetType(int8(enums.PreservationActionTypeCreateAIP)).
SetStatus(int8(status)).
SetPackageID(pkgID).
Save(context.Background())
}

func TestNew(t *testing.T) {
t.Run("Returns a working ent DB client", func(t *testing.T) {
t.Parallel()

entc, _ := setUpClient(t, logr.Discard())
runID := uuid.New()
aipID := uuid.New()

p, err := entc.Pkg.Create().
SetName("testing 1-2-3").
SetWorkflowID("12345").
SetRunID(runID).
SetAipID(aipID).
SetStatus(int8(enums.NewPackageStatus("in progress"))).
Save(context.Background())

p, err := createPackage(
entc,
"testing 1-2-3",
enums.NewPackageStatus("in progress"),
)
assert.NilError(t, err)

assert.Equal(t, p.Name, "testing 1-2-3")
assert.Equal(t, p.WorkflowID, "12345")
assert.Equal(t, p.RunID, runID)
assert.Equal(t, p.AipID, aipID)
assert.Equal(t, p.RunID, uuid.MustParse("aee9644d-6397-4b34-92f7-442ad3dd3b13"))
assert.Equal(t, p.AipID, uuid.MustParse("30223842-0650-4f79-80bd-7bf43b810656"))
assert.Equal(t, p.Status, int8(enums.PackageStatusInProgress))
})
}
27 changes: 26 additions & 1 deletion internal/persistence/ent/client/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/artefactual-sdps/enduro/internal/persistence/ent/db"
)

// convertPkgToPackage converts an ent `db.Pkg` package representation to a
// convertPkgToPackage converts an entgo `db.Pkg` package representation to a
// `datatypes.Package` representation.
func convertPkgToPackage(pkg *db.Pkg) *datatypes.Package {
var started, completed sql.NullTime
Expand Down Expand Up @@ -44,3 +44,28 @@ func convertPkgToPackage(pkg *db.Pkg) *datatypes.Package {
CompletedAt: completed,
}
}

// convertPreservationTask converts an entgo `db.PreservationTask` representation
// to a `datatypes.PreservationTask` representation.
func convertPreservationTask(pt *db.PreservationTask) *datatypes.PreservationTask {
var started sql.NullTime
if !pt.StartedAt.IsZero() {
started = sql.NullTime{Time: pt.StartedAt, Valid: true}
}

var completed sql.NullTime
if !pt.CompletedAt.IsZero() {
completed = sql.NullTime{Time: pt.CompletedAt, Valid: true}
}

return &datatypes.PreservationTask{
ID: uint(pt.ID),
TaskID: pt.TaskID.String(),
Name: pt.Name,
Status: enums.PreservationTaskStatus(pt.Status),
StartedAt: started,
CompletedAt: completed,
Note: pt.Note,
PreservationActionID: uint(pt.PreservationActionID),
}
}
55 changes: 55 additions & 0 deletions internal/persistence/ent/client/preservation_task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package entclient

import (
"context"
"time"

"github.com/google/uuid"

"github.com/artefactual-sdps/enduro/internal/datatypes"
)

func (c *client) CreatePreservationTask(ctx context.Context, pt *datatypes.PreservationTask) error {
// Validate required fields.
taskID, err := uuid.Parse(pt.TaskID)
if err != nil {
return newParseError(err, "TaskID")
}
if pt.Name == "" {
return newRequiredFieldError("Name")
}
if pt.PreservationActionID == 0 {
return newRequiredFieldError("PreservationActionID")
}
// TODO: Validate Status.

// Handle nullable fields.
var startedAt *time.Time
if pt.StartedAt.Valid {
startedAt = &pt.StartedAt.Time
}

var completedAt *time.Time
if pt.CompletedAt.Valid {
completedAt = &pt.CompletedAt.Time
}

q := c.ent.PreservationTask.Create().
SetTaskID(taskID).
SetName(pt.Name).
SetStatus(int8(pt.Status)).
SetNillableStartedAt(startedAt).
SetNillableCompletedAt(completedAt).
SetNote(pt.Note).
SetPreservationActionID(int(pt.PreservationActionID))

r, err := q.Save(ctx)
if err != nil {
return newDBErrorWithDetails(err, "create preservation task")
}

// Update value of pt with data from DB (e.g. ID).
*pt = *convertPreservationTask(r)

return nil
}
124 changes: 124 additions & 0 deletions internal/persistence/ent/client/preservation_task_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package entclient_test

import (
"context"
"database/sql"
"testing"
"time"

"github.com/go-logr/logr"
"gotest.tools/v3/assert"

"github.com/artefactual-sdps/enduro/internal/datatypes"
"github.com/artefactual-sdps/enduro/internal/enums"
)

func TestCreatePreservationTask(t *testing.T) {
taskID := "ef0193bf-a622-4a8b-b860-cda605a426b5"
started := sql.NullTime{Time: time.Now(), Valid: true}
completed := sql.NullTime{Time: started.Time.Add(time.Second), Valid: true}

type params struct {
pt *datatypes.PreservationTask
zeroPreservationActionID bool
}
tests := []struct {
name string
args params
want *datatypes.PreservationTask
wantErr string
}{
{
name: "Saves a new preservation task in the DB",
args: params{
pt: &datatypes.PreservationTask{
TaskID: taskID,
Name: "PT1",
Status: enums.PreservationTaskStatusInProgress,
StartedAt: started,
CompletedAt: completed,
Note: "PT1 Note",
},
},
want: &datatypes.PreservationTask{
ID: 1,
TaskID: taskID,
Name: "PT1",
Status: enums.PreservationTaskStatusInProgress,
StartedAt: started,
CompletedAt: completed,
Note: "PT1 Note",
},
},
{
name: "Errors on invalid TaskID",
args: params{
pt: &datatypes.PreservationTask{
TaskID: "123456",
},
},
wantErr: "invalid data error: parse error: field \"TaskID\": invalid UUID length: 6",
},
{
name: "Required field error for missing Name",
args: params{
pt: &datatypes.PreservationTask{
TaskID: "ef0193bf-a622-4a8b-b860-cda605a426b5",
},
},
wantErr: "invalid data error: field \"Name\" is required",
},
{
name: "Required field error for missing PreservationActionID",
args: params{
pt: &datatypes.PreservationTask{
TaskID: taskID,
Name: "PT1",
Status: enums.PreservationTaskStatusInProgress,
},
zeroPreservationActionID: true,
},
wantErr: "invalid data error: field \"PreservationActionID\" is required",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

entc, svc := setUpClient(t, logr.Discard())
ctx := context.Background()
pkg, _ := createPackage(
entc,
"Test package",
enums.PackageStatusInProgress,
)
pa, _ := createPreservationAction(
entc,
pkg.ID,
enums.PreservationActionStatusInProgress,
)

pt := *tt.args.pt // Make a local copy of pt.

if !tt.args.zeroPreservationActionID {
pt.PreservationActionID = uint(pa.ID)
}

err := svc.CreatePreservationTask(ctx, &pt)
if tt.wantErr != "" {
assert.Error(t, err, tt.wantErr)
return
}
assert.NilError(t, err)

assert.Equal(t, pt.ID, tt.want.ID)
assert.Equal(t, pt.TaskID, tt.want.TaskID)
assert.Equal(t, pt.Name, tt.want.Name)
assert.Equal(t, pt.Status, tt.want.Status)
assert.Equal(t, pt.StartedAt, tt.want.StartedAt)
assert.Equal(t, pt.CompletedAt, tt.want.CompletedAt)
assert.Equal(t, pt.Note, tt.want.Note)
assert.Equal(t, pt.PreservationActionID, uint(pa.ID))
})
}
}
38 changes: 38 additions & 0 deletions internal/persistence/fake/mock_persistence.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions internal/persistence/persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ type Service interface {
// (e.g. ID, CreatedAt).
CreatePackage(context.Context, *datatypes.Package) error
UpdatePackage(context.Context, uint, PackageUpdater) (*datatypes.Package, error)

CreatePreservationTask(context.Context, *datatypes.PreservationTask) error
}

0 comments on commit e584c2d

Please sign in to comment.