-
This commit is contained in:
32
faas/internal/repository/interfaces.go
Normal file
32
faas/internal/repository/interfaces.go
Normal file
@ -0,0 +1,32 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/RyanCopley/skybridge/faas/internal/domain"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// FunctionRepository provides CRUD operations for functions
|
||||
type FunctionRepository interface {
|
||||
Create(ctx context.Context, function *domain.FunctionDefinition) (*domain.FunctionDefinition, error)
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*domain.FunctionDefinition, error)
|
||||
GetByName(ctx context.Context, appID, name string) (*domain.FunctionDefinition, error)
|
||||
Update(ctx context.Context, id uuid.UUID, updates *domain.UpdateFunctionRequest) (*domain.FunctionDefinition, error)
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, appID string, limit, offset int) ([]*domain.FunctionDefinition, error)
|
||||
GetByAppID(ctx context.Context, appID string) ([]*domain.FunctionDefinition, error)
|
||||
}
|
||||
|
||||
// ExecutionRepository provides CRUD operations for function executions
|
||||
type ExecutionRepository interface {
|
||||
Create(ctx context.Context, execution *domain.FunctionExecution) (*domain.FunctionExecution, error)
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*domain.FunctionExecution, error)
|
||||
Update(ctx context.Context, id uuid.UUID, execution *domain.FunctionExecution) (*domain.FunctionExecution, error)
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, functionID *uuid.UUID, limit, offset int) ([]*domain.FunctionExecution, error)
|
||||
GetByFunctionID(ctx context.Context, functionID uuid.UUID, limit, offset int) ([]*domain.FunctionExecution, error)
|
||||
GetByStatus(ctx context.Context, status domain.ExecutionStatus, limit, offset int) ([]*domain.FunctionExecution, error)
|
||||
UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ExecutionStatus) error
|
||||
GetRunningExecutions(ctx context.Context) ([]*domain.FunctionExecution, error)
|
||||
}
|
||||
260
faas/internal/repository/postgres/execution_repository.go
Normal file
260
faas/internal/repository/postgres/execution_repository.go
Normal file
@ -0,0 +1,260 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/RyanCopley/skybridge/faas/internal/domain"
|
||||
"github.com/RyanCopley/skybridge/faas/internal/repository"
|
||||
)
|
||||
|
||||
type executionRepository struct {
|
||||
db *sql.DB
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewExecutionRepository(db *sql.DB, logger *zap.Logger) repository.ExecutionRepository {
|
||||
return &executionRepository{
|
||||
db: db,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *executionRepository) Create(ctx context.Context, execution *domain.FunctionExecution) (*domain.FunctionExecution, error) {
|
||||
query := `
|
||||
INSERT INTO executions (id, function_id, status, input, executor_id, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING created_at`
|
||||
|
||||
err := r.db.QueryRowContext(ctx, query,
|
||||
execution.ID, execution.FunctionID, execution.Status, execution.Input,
|
||||
execution.ExecutorID, execution.CreatedAt,
|
||||
).Scan(&execution.CreatedAt)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to create execution", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to create execution: %w", err)
|
||||
}
|
||||
|
||||
return execution, nil
|
||||
}
|
||||
|
||||
func (r *executionRepository) GetByID(ctx context.Context, id uuid.UUID) (*domain.FunctionExecution, error) {
|
||||
query := `
|
||||
SELECT id, function_id, status, input, output, error, duration, memory_used,
|
||||
container_id, executor_id, created_at, started_at, completed_at
|
||||
FROM executions WHERE id = $1`
|
||||
|
||||
execution := &domain.FunctionExecution{}
|
||||
var durationNanos sql.NullInt64
|
||||
|
||||
err := r.db.QueryRowContext(ctx, query, id).Scan(
|
||||
&execution.ID, &execution.FunctionID, &execution.Status, &execution.Input,
|
||||
&execution.Output, &execution.Error, &durationNanos, &execution.MemoryUsed,
|
||||
&execution.ContainerID, &execution.ExecutorID, &execution.CreatedAt,
|
||||
&execution.StartedAt, &execution.CompletedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, fmt.Errorf("execution not found")
|
||||
}
|
||||
r.logger.Error("Failed to get execution by ID", zap.String("id", id.String()), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to get execution: %w", err)
|
||||
}
|
||||
|
||||
// Convert duration
|
||||
if durationNanos.Valid {
|
||||
execution.Duration = time.Duration(durationNanos.Int64)
|
||||
}
|
||||
|
||||
return execution, nil
|
||||
}
|
||||
|
||||
func (r *executionRepository) Update(ctx context.Context, id uuid.UUID, execution *domain.FunctionExecution) (*domain.FunctionExecution, error) {
|
||||
query := `
|
||||
UPDATE executions
|
||||
SET status = $2, output = $3, error = $4, duration = $5, memory_used = $6,
|
||||
container_id = $7, started_at = $8, completed_at = $9
|
||||
WHERE id = $1`
|
||||
|
||||
var durationNanos sql.NullInt64
|
||||
if execution.Duration > 0 {
|
||||
durationNanos.Int64 = int64(execution.Duration)
|
||||
durationNanos.Valid = true
|
||||
}
|
||||
|
||||
_, err := r.db.ExecContext(ctx, query,
|
||||
id, execution.Status, execution.Output, execution.Error,
|
||||
durationNanos, execution.MemoryUsed, execution.ContainerID,
|
||||
execution.StartedAt, execution.CompletedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to update execution", zap.String("id", id.String()), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to update execution: %w", err)
|
||||
}
|
||||
|
||||
// Return updated execution
|
||||
return r.GetByID(ctx, id)
|
||||
}
|
||||
|
||||
func (r *executionRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
||||
query := `DELETE FROM executions WHERE id = $1`
|
||||
|
||||
result, err := r.db.ExecContext(ctx, query, id)
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to delete execution", zap.String("id", id.String()), zap.Error(err))
|
||||
return fmt.Errorf("failed to delete execution: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get affected rows: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("execution not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *executionRepository) List(ctx context.Context, functionID *uuid.UUID, limit, offset int) ([]*domain.FunctionExecution, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
|
||||
if functionID != nil {
|
||||
query = `
|
||||
SELECT id, function_id, status, input, output, error, duration, memory_used,
|
||||
container_id, executor_id, created_at, started_at, completed_at
|
||||
FROM executions WHERE function_id = $1
|
||||
ORDER BY created_at DESC LIMIT $2 OFFSET $3`
|
||||
args = []interface{}{*functionID, limit, offset}
|
||||
} else {
|
||||
query = `
|
||||
SELECT id, function_id, status, input, output, error, duration, memory_used,
|
||||
container_id, executor_id, created_at, started_at, completed_at
|
||||
FROM executions
|
||||
ORDER BY created_at DESC LIMIT $1 OFFSET $2`
|
||||
args = []interface{}{limit, offset}
|
||||
}
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to list executions", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to list executions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var executions []*domain.FunctionExecution
|
||||
for rows.Next() {
|
||||
execution := &domain.FunctionExecution{}
|
||||
var durationNanos sql.NullInt64
|
||||
|
||||
err := rows.Scan(
|
||||
&execution.ID, &execution.FunctionID, &execution.Status, &execution.Input,
|
||||
&execution.Output, &execution.Error, &durationNanos, &execution.MemoryUsed,
|
||||
&execution.ContainerID, &execution.ExecutorID, &execution.CreatedAt,
|
||||
&execution.StartedAt, &execution.CompletedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to scan execution", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to scan execution: %w", err)
|
||||
}
|
||||
|
||||
// Convert duration
|
||||
if durationNanos.Valid {
|
||||
execution.Duration = time.Duration(durationNanos.Int64)
|
||||
}
|
||||
|
||||
executions = append(executions, execution)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate executions: %w", err)
|
||||
}
|
||||
|
||||
return executions, nil
|
||||
}
|
||||
|
||||
func (r *executionRepository) GetByFunctionID(ctx context.Context, functionID uuid.UUID, limit, offset int) ([]*domain.FunctionExecution, error) {
|
||||
return r.List(ctx, &functionID, limit, offset)
|
||||
}
|
||||
|
||||
func (r *executionRepository) GetByStatus(ctx context.Context, status domain.ExecutionStatus, limit, offset int) ([]*domain.FunctionExecution, error) {
|
||||
query := `
|
||||
SELECT id, function_id, status, input, output, error, duration, memory_used,
|
||||
container_id, executor_id, created_at, started_at, completed_at
|
||||
FROM executions WHERE status = $1
|
||||
ORDER BY created_at DESC LIMIT $2 OFFSET $3`
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query, status, limit, offset)
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to get executions by status", zap.String("status", string(status)), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to get executions by status: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var executions []*domain.FunctionExecution
|
||||
for rows.Next() {
|
||||
execution := &domain.FunctionExecution{}
|
||||
var durationNanos sql.NullInt64
|
||||
|
||||
err := rows.Scan(
|
||||
&execution.ID, &execution.FunctionID, &execution.Status, &execution.Input,
|
||||
&execution.Output, &execution.Error, &durationNanos, &execution.MemoryUsed,
|
||||
&execution.ContainerID, &execution.ExecutorID, &execution.CreatedAt,
|
||||
&execution.StartedAt, &execution.CompletedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to scan execution", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to scan execution: %w", err)
|
||||
}
|
||||
|
||||
// Convert duration
|
||||
if durationNanos.Valid {
|
||||
execution.Duration = time.Duration(durationNanos.Int64)
|
||||
}
|
||||
|
||||
executions = append(executions, execution)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate executions: %w", err)
|
||||
}
|
||||
|
||||
return executions, nil
|
||||
}
|
||||
|
||||
func (r *executionRepository) UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ExecutionStatus) error {
|
||||
query := `UPDATE executions SET status = $2 WHERE id = $1`
|
||||
|
||||
result, err := r.db.ExecContext(ctx, query, id, status)
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to update execution status", zap.String("id", id.String()), zap.Error(err))
|
||||
return fmt.Errorf("failed to update execution status: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get affected rows: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("execution not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *executionRepository) GetRunningExecutions(ctx context.Context) ([]*domain.FunctionExecution, error) {
|
||||
return r.GetByStatus(ctx, domain.StatusRunning, 1000, 0)
|
||||
}
|
||||
278
faas/internal/repository/postgres/function_repository.go
Normal file
278
faas/internal/repository/postgres/function_repository.go
Normal file
@ -0,0 +1,278 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/RyanCopley/skybridge/faas/internal/domain"
|
||||
"github.com/RyanCopley/skybridge/faas/internal/repository"
|
||||
)
|
||||
|
||||
type functionRepository struct {
|
||||
db *sql.DB
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewFunctionRepository(db *sql.DB, logger *zap.Logger) repository.FunctionRepository {
|
||||
return &functionRepository{
|
||||
db: db,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *functionRepository) Create(ctx context.Context, function *domain.FunctionDefinition) (*domain.FunctionDefinition, error) {
|
||||
envJSON, err := json.Marshal(function.Environment)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal environment: %w", err)
|
||||
}
|
||||
|
||||
query := `
|
||||
INSERT INTO functions (id, name, app_id, runtime, image, handler, code, environment, timeout, memory,
|
||||
owner_type, owner_name, owner_owner, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
||||
RETURNING created_at, updated_at`
|
||||
|
||||
err = r.db.QueryRowContext(ctx, query,
|
||||
function.ID, function.Name, function.AppID, function.Runtime, function.Image,
|
||||
function.Handler, function.Code, envJSON, function.Timeout.Duration,
|
||||
function.Memory, function.Owner.Type, function.Owner.Name, function.Owner.Owner,
|
||||
function.CreatedAt, function.UpdatedAt,
|
||||
).Scan(&function.CreatedAt, &function.UpdatedAt)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to create function", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to create function: %w", err)
|
||||
}
|
||||
|
||||
return function, nil
|
||||
}
|
||||
|
||||
func (r *functionRepository) GetByID(ctx context.Context, id uuid.UUID) (*domain.FunctionDefinition, error) {
|
||||
query := `
|
||||
SELECT id, name, app_id, runtime, image, handler, code, environment, timeout, memory,
|
||||
owner_type, owner_name, owner_owner, created_at, updated_at
|
||||
FROM functions WHERE id = $1`
|
||||
|
||||
function := &domain.FunctionDefinition{}
|
||||
var envJSON []byte
|
||||
var timeoutNanos int64
|
||||
|
||||
err := r.db.QueryRowContext(ctx, query, id).Scan(
|
||||
&function.ID, &function.Name, &function.AppID, &function.Runtime, &function.Image,
|
||||
&function.Handler, &function.Code, &envJSON, &timeoutNanos, &function.Memory,
|
||||
&function.Owner.Type, &function.Owner.Name, &function.Owner.Owner,
|
||||
&function.CreatedAt, &function.UpdatedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, fmt.Errorf("function not found")
|
||||
}
|
||||
r.logger.Error("Failed to get function by ID", zap.String("id", id.String()), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to get function: %w", err)
|
||||
}
|
||||
|
||||
// Unmarshal environment
|
||||
if err := json.Unmarshal(envJSON, &function.Environment); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal environment: %w", err)
|
||||
}
|
||||
|
||||
// Convert timeout
|
||||
function.Timeout.Duration = time.Duration(timeoutNanos)
|
||||
|
||||
return function, nil
|
||||
}
|
||||
|
||||
func (r *functionRepository) GetByName(ctx context.Context, appID, name string) (*domain.FunctionDefinition, error) {
|
||||
query := `
|
||||
SELECT id, name, app_id, runtime, image, handler, code, environment, timeout, memory,
|
||||
owner_type, owner_name, owner_owner, created_at, updated_at
|
||||
FROM functions WHERE app_id = $1 AND name = $2`
|
||||
|
||||
function := &domain.FunctionDefinition{}
|
||||
var envJSON []byte
|
||||
var timeoutNanos int64
|
||||
|
||||
err := r.db.QueryRowContext(ctx, query, appID, name).Scan(
|
||||
&function.ID, &function.Name, &function.AppID, &function.Runtime, &function.Image,
|
||||
&function.Handler, &function.Code, &envJSON, &timeoutNanos, &function.Memory,
|
||||
&function.Owner.Type, &function.Owner.Name, &function.Owner.Owner,
|
||||
&function.CreatedAt, &function.UpdatedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, fmt.Errorf("function not found")
|
||||
}
|
||||
r.logger.Error("Failed to get function by name", zap.String("app_id", appID), zap.String("name", name), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to get function: %w", err)
|
||||
}
|
||||
|
||||
// Unmarshal environment
|
||||
if err := json.Unmarshal(envJSON, &function.Environment); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal environment: %w", err)
|
||||
}
|
||||
|
||||
// Convert timeout
|
||||
function.Timeout.Duration = time.Duration(timeoutNanos)
|
||||
|
||||
return function, nil
|
||||
}
|
||||
|
||||
func (r *functionRepository) Update(ctx context.Context, id uuid.UUID, updates *domain.UpdateFunctionRequest) (*domain.FunctionDefinition, error) {
|
||||
// First get the current function
|
||||
current, err := r.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Apply updates
|
||||
if updates.Name != nil {
|
||||
current.Name = *updates.Name
|
||||
}
|
||||
if updates.Runtime != nil {
|
||||
current.Runtime = *updates.Runtime
|
||||
}
|
||||
if updates.Image != nil {
|
||||
current.Image = *updates.Image
|
||||
}
|
||||
if updates.Handler != nil {
|
||||
current.Handler = *updates.Handler
|
||||
}
|
||||
if updates.Code != nil {
|
||||
current.Code = *updates.Code
|
||||
}
|
||||
if updates.Environment != nil {
|
||||
current.Environment = updates.Environment
|
||||
}
|
||||
if updates.Timeout != nil {
|
||||
current.Timeout = *updates.Timeout
|
||||
}
|
||||
if updates.Memory != nil {
|
||||
current.Memory = *updates.Memory
|
||||
}
|
||||
if updates.Owner != nil {
|
||||
current.Owner = *updates.Owner
|
||||
}
|
||||
|
||||
// Marshal environment
|
||||
envJSON, err := json.Marshal(current.Environment)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal environment: %w", err)
|
||||
}
|
||||
|
||||
query := `
|
||||
UPDATE functions
|
||||
SET name = $2, runtime = $3, image = $4, handler = $5, code = $6, environment = $7,
|
||||
timeout = $8, memory = $9, owner_type = $10, owner_name = $11, owner_owner = $12,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING updated_at`
|
||||
|
||||
err = r.db.QueryRowContext(ctx, query,
|
||||
id, current.Name, current.Runtime, current.Image, current.Handler,
|
||||
current.Code, envJSON, int64(current.Timeout.Duration), current.Memory,
|
||||
current.Owner.Type, current.Owner.Name, current.Owner.Owner,
|
||||
).Scan(¤t.UpdatedAt)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to update function", zap.String("id", id.String()), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to update function: %w", err)
|
||||
}
|
||||
|
||||
return current, nil
|
||||
}
|
||||
|
||||
func (r *functionRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
||||
query := `DELETE FROM functions WHERE id = $1`
|
||||
|
||||
result, err := r.db.ExecContext(ctx, query, id)
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to delete function", zap.String("id", id.String()), zap.Error(err))
|
||||
return fmt.Errorf("failed to delete function: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get affected rows: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("function not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *functionRepository) List(ctx context.Context, appID string, limit, offset int) ([]*domain.FunctionDefinition, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
|
||||
if appID != "" {
|
||||
query = `
|
||||
SELECT id, name, app_id, runtime, image, handler, code, environment, timeout, memory,
|
||||
owner_type, owner_name, owner_owner, created_at, updated_at
|
||||
FROM functions WHERE app_id = $1
|
||||
ORDER BY created_at DESC LIMIT $2 OFFSET $3`
|
||||
args = []interface{}{appID, limit, offset}
|
||||
} else {
|
||||
query = `
|
||||
SELECT id, name, app_id, runtime, image, handler, code, environment, timeout, memory,
|
||||
owner_type, owner_name, owner_owner, created_at, updated_at
|
||||
FROM functions
|
||||
ORDER BY created_at DESC LIMIT $1 OFFSET $2`
|
||||
args = []interface{}{limit, offset}
|
||||
}
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to list functions", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to list functions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var functions []*domain.FunctionDefinition
|
||||
for rows.Next() {
|
||||
function := &domain.FunctionDefinition{}
|
||||
var envJSON []byte
|
||||
var timeoutNanos int64
|
||||
|
||||
err := rows.Scan(
|
||||
&function.ID, &function.Name, &function.AppID, &function.Runtime, &function.Image,
|
||||
&function.Handler, &function.Code, &envJSON, &timeoutNanos, &function.Memory,
|
||||
&function.Owner.Type, &function.Owner.Name, &function.Owner.Owner,
|
||||
&function.CreatedAt, &function.UpdatedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to scan function", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to scan function: %w", err)
|
||||
}
|
||||
|
||||
// Unmarshal environment
|
||||
if err := json.Unmarshal(envJSON, &function.Environment); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal environment: %w", err)
|
||||
}
|
||||
|
||||
// Convert timeout
|
||||
function.Timeout.Duration = time.Duration(timeoutNanos)
|
||||
|
||||
functions = append(functions, function)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate functions: %w", err)
|
||||
}
|
||||
|
||||
return functions, nil
|
||||
}
|
||||
|
||||
func (r *functionRepository) GetByAppID(ctx context.Context, appID string) ([]*domain.FunctionDefinition, error) {
|
||||
return r.List(ctx, appID, 1000, 0) // Get all functions for the app
|
||||
}
|
||||
Reference in New Issue
Block a user