Skip to content

Commit

Permalink
refactor: Use more models to represent data
Browse files Browse the repository at this point in the history
  • Loading branch information
mauricioabreu committed Apr 23, 2024
1 parent 86ecc86 commit 440c562
Show file tree
Hide file tree
Showing 17 changed files with 201 additions and 84 deletions.
41 changes: 34 additions & 7 deletions internal/api/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package api
import (
"net/http"

"github.com/dionysia-dev/dionysia/internal/model"
"github.com/dionysia-dev/dionysia/internal/service"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
Expand Down Expand Up @@ -31,9 +30,9 @@ func NewInputController(inputHandler service.InputHandler) *InputController {
// @Failure 500 {object} api.ErrorResponse "Internal server error"
// @Router /inputs [post]
func (c *InputController) CreateInput(ctx *gin.Context) {
var inputData model.Input
var inputData InputData
if err := ctx.BindJSON(&inputData); err != nil {
statusCode, response := handleValidationError(err)
statusCode, response := HandleValidationError(err)
if statusCode == 0 && response == nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse{
Error: Error{
Expand All @@ -49,7 +48,32 @@ func (c *InputController) CreateInput(ctx *gin.Context) {
return
}

input, err := c.inputHandler.CreateInput(ctx, &inputData)
audioProfiles := make([]service.AudioProfile, 0, len(inputData.AudioProfiles))
for _, audioProfileData := range inputData.AudioProfiles {
audioProfiles = append(audioProfiles, service.AudioProfile{
Codec: audioProfileData.Codec,
Bitrate: audioProfileData.Bitrate,
})
}

videoProfiles := make([]service.VideoProfile, 0, len(inputData.VideoProfiles))
for _, videoProfileData := range inputData.VideoProfiles {
videoProfiles = append(videoProfiles, service.VideoProfile{
Codec: videoProfileData.Codec,
Bitrate: videoProfileData.Bitrate,
MaxKeyInterval: videoProfileData.MaxKeyInterval,
Framerate: videoProfileData.Framerate,
Width: videoProfileData.Width,
Height: videoProfileData.Height,
})
}

input, err := c.inputHandler.CreateInput(ctx, &service.Input{
Name: inputData.Name,
Format: inputData.Format,
AudioProfiles: audioProfiles,
VideoProfiles: videoProfiles,
})
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse{
Error: Error{
Expand Down Expand Up @@ -138,9 +162,9 @@ func (c *InputController) DeleteInput(ctx *gin.Context) {
}

func (c *InputController) Authenticate(ctx *gin.Context) {
var authData model.IngestAuthData
var authData IngestAuthData
if err := ctx.BindJSON(&authData); err != nil {
statusCode, response := handleValidationError(err)
statusCode, response := HandleValidationError(err)
if statusCode == 0 && response == nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse{
Error: Error{
Expand All @@ -156,7 +180,10 @@ func (c *InputController) Authenticate(ctx *gin.Context) {
return
}

err := c.inputHandler.Authenticate(ctx, authData)
err := c.inputHandler.Authenticate(ctx, service.IngestAuth{
Path: authData.Path,
Action: authData.Action,
})

switch {
case err == service.ErrFailedAuth:
Expand Down
30 changes: 30 additions & 0 deletions internal/api/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package api

import "github.com/google/uuid"

type InputData struct {
ID uuid.UUID `json:"id" swaggerignore:"true"`
Name string `json:"name" validate:"required"`
Format string `json:"format" validate:"required"`
AudioProfiles []AudioProfileData `json:"audio_profiles"`
VideoProfiles []VideoProfileData `json:"video_profiles"`
}

type AudioProfileData struct {
Codec string `json:"codec"`
Bitrate int `json:"bitrate"`
}

type VideoProfileData struct {
Codec string `json:"codec"`
Bitrate int `json:"bitrate"`
MaxKeyInterval int `json:"max_key_interval"`
Framerate int `json:"framerate"`
Width int `json:"width"`
Height int `json:"height"`
}

type IngestAuthData struct {
Path uuid.UUID `json:"path" validate:"required"`
Action string `json:"action" validate:"required"`
}
4 changes: 2 additions & 2 deletions internal/api/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ type ErrorResponse struct {

type StatusCode int

// handleValidationError validate and handle errors of structs that has `validator/v10` rules
func handleValidationError(err error) (StatusCode, *ErrorResponse) {
// HandleValidationError validate and handle errors of structs that has `validator/v10` rules
func HandleValidationError(err error) (StatusCode, *ErrorResponse) {
validationErrors, ok := err.(validator.ValidationErrors)
if !ok {
return 0, nil
Expand Down
23 changes: 11 additions & 12 deletions internal/api/response_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package api
package api_test

import (
"net/http"
"testing"

"github.com/dionysia-dev/dionysia/internal/model"
"github.com/dionysia-dev/dionysia/internal/api"
"github.com/go-playground/validator/v10"
"github.com/stretchr/testify/assert"
)
Expand All @@ -15,23 +15,22 @@ var validate *validator.Validate
func TestHandleValidationError(t *testing.T) {
validate = validator.New(validator.WithRequiredStructEnabled())

// Test cases
testCases := []struct {
name string
inputError *model.Input
expectedStatusCode StatusCode
expectedErrorResp *ErrorResponse
inputError *api.InputData
expectedStatusCode api.StatusCode
expectedErrorResp *api.ErrorResponse
}{
{
name: "Test with bad request body",
inputError: &model.Input{
inputError: &api.InputData{
Name: "just a name",
},
expectedStatusCode: http.StatusBadRequest,
expectedErrorResp: &ErrorResponse{
Error: Error{
expectedErrorResp: &api.ErrorResponse{
Error: api.Error{
Message: "Invalid request parameters",
Details: []ErrorDetail{
Details: []api.ErrorDetail{
{
Reason: "Format",
Message: "required",
Expand All @@ -42,7 +41,7 @@ func TestHandleValidationError(t *testing.T) {
},
{
name: "Test with valid request body",
inputError: &model.Input{
inputError: &api.InputData{
Name: "beautiful name",
Format: "nice format",
},
Expand All @@ -54,7 +53,7 @@ func TestHandleValidationError(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := validate.Struct(tc.inputError)
actualStatusCode, actualErrorResp := handleValidationError(err)
actualStatusCode, actualErrorResp := api.HandleValidationError(err)

assert.Equal(t, tc.expectedStatusCode, actualStatusCode, "Status code mismatch")
assert.Equal(t, tc.expectedErrorResp, actualErrorResp, "Error response mismatch")
Expand Down
2 changes: 1 addition & 1 deletion internal/db/migrate.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package db

import (
"github.com/dionysia-dev/dionysia/internal/model"
"github.com/dionysia-dev/dionysia/internal/db/model"
"gorm.io/gorm"
)

Expand Down
7 changes: 1 addition & 6 deletions internal/model/input.go → internal/db/model/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ type Input struct {

type AudioProfile struct {
InputID uuid.UUID
Bitrate int `json:"bitrate"`
Codec string `json:"codec"`
Bitrate int `json:"bitrate"`
}

type VideoProfile struct {
Expand All @@ -27,8 +27,3 @@ type VideoProfile struct {
Width int `json:"width"`
Height int `json:"height"`
}

type IngestAuthData struct {
Path uuid.UUID `json:"path" validate:"required"`
Action string `json:"action" validate:"required"`
}
2 changes: 1 addition & 1 deletion internal/db/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"errors"

"github.com/dionysia-dev/dionysia/internal/model"
"github.com/dionysia-dev/dionysia/internal/db/model"
"github.com/google/uuid"
"gorm.io/gorm"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/mocks/store.go

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

18 changes: 8 additions & 10 deletions internal/task/command.go → internal/service/command.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package task
package service

import (
"fmt"
"log"
"os/exec"
"strings"

"github.com/dionysia-dev/dionysia/internal/model"
)

const (
Expand All @@ -17,14 +15,14 @@ const (
)

type CommandConfig struct {
DefaultVideoProfiles []model.VideoProfile
DefaultAudioProfiles []model.AudioProfile
DefaultVideoProfiles []VideoProfile
DefaultAudioProfiles []AudioProfile
}

func NewDefaultCommandConfig() *CommandConfig {
return &CommandConfig{
//nolint:gomnd // values are self explanatory
DefaultVideoProfiles: []model.VideoProfile{
DefaultVideoProfiles: []VideoProfile{
{
Codec: defaultVideoCodec,
Bitrate: 500,
Expand Down Expand Up @@ -59,7 +57,7 @@ func NewDefaultCommandConfig() *CommandConfig {
},
},
//nolint:gomnd // values are self explanatory
DefaultAudioProfiles: []model.AudioProfile{
DefaultAudioProfiles: []AudioProfile{
{
Codec: defaultAudioCodec,
Bitrate: 128,
Expand All @@ -76,7 +74,7 @@ func NewGPACCommandBuilder(config *CommandConfig) *GPACCommandBuilder {
return &GPACCommandBuilder{config: config}
}

func (b *GPACCommandBuilder) Build(id, address, output string, input model.Input) *GPACCommand {
func (b *GPACCommandBuilder) Build(id, address, output string, input Input) *GPACCommand {
if len(input.VideoProfiles) == 0 {
input.VideoProfiles = b.config.DefaultVideoProfiles
}
Expand All @@ -101,7 +99,7 @@ type GPACCommand struct {
ID string
Address string
Output string
Input model.Input
Input Input
Runner func(string, []string) error
}

Expand Down Expand Up @@ -138,7 +136,7 @@ func (g *GPACCommand) Execute() error {
return g.Runner("gpac", args)
}

func NewGPACCommand(id, address, output string, input model.Input) *GPACCommand {
func NewGPACCommand(id, address, output string, input Input) *GPACCommand {
runner := func(program string, args []string) error {
cmd := exec.Command(program, args...)
return cmd.Run()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package task_test
package service_test

import (
"testing"

"github.com/dionysia-dev/dionysia/internal/model"
"github.com/dionysia-dev/dionysia/internal/task"
"github.com/dionysia-dev/dionysia/internal/service"
"github.com/stretchr/testify/assert"
)

func TestGPACCommandExecute(t *testing.T) {
input := model.Input{
VideoProfiles: []model.VideoProfile{{Bitrate: 1000}, {Bitrate: 2000}},
AudioProfiles: []model.AudioProfile{{Bitrate: 128}},
input := service.Input{
VideoProfiles: []service.VideoProfile{{Bitrate: 1000}, {Bitrate: 2000}},
AudioProfiles: []service.AudioProfile{{Bitrate: 128}},
}
cmd := task.NewGPACCommand("1234", "rtmp://localhost", "/output", input)
cmd := service.NewGPACCommand("1234", "rtmp://localhost", "/output", input)

mockRunner := func(program string, args []string) error {
assert.Equal(t, "gpac", program)
Expand Down
Loading

0 comments on commit 440c562

Please sign in to comment.