Compare commits
19 Commits
c17b78cc48
...
5ffb558ab8
Author | SHA1 | Date | |
---|---|---|---|
5ffb558ab8 | |||
0a8f84bb15 | |||
6583ae7d29 | |||
e38171e53d | |||
7cf51f9b90 | |||
9d9b354698 | |||
ae7bc131f7 | |||
135e09ea8e | |||
24d51a3751 | |||
d994ead6f6 | |||
4d262c8fff | |||
ffc3164cb7 | |||
9512cd10bc | |||
505bc3b522 | |||
99ea2d37ab | |||
3f92bdb325 | |||
098ecda869 | |||
ca1e1a1da5 | |||
6bec8e3373 |
@ -1,42 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func ExecuteRawStatement(ctx context.Context, db *gorm.DB, query string, args ...any) error {
|
||||
if query == "" {
|
||||
return errors.New("query can not be empty")
|
||||
}
|
||||
|
||||
if args == nil {
|
||||
return errors.New("arguments can not be nil")
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Exec(query, args...)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func QueryRawStatement(ctx context.Context, db *gorm.DB, query string, args ...any) (*sql.Rows, error) {
|
||||
if query == "" {
|
||||
return nil, errors.New("query can not be empty")
|
||||
}
|
||||
|
||||
if args == nil {
|
||||
return nil, errors.New("arguments can not be nil")
|
||||
}
|
||||
|
||||
result, err := db.WithContext(ctx).Raw(query, args...).Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/test"
|
||||
"gorm.io/gorm"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExecuteRawStatement(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
query string
|
||||
args []any
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *sql.Rows
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 01: Empty Query",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
query: "",
|
||||
args: nil,
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 02: Nil Query",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
query: "aasd",
|
||||
args: nil,
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ExecuteRawStatement(tt.args.ctx, tt.args.db, tt.args.query, tt.args.args...)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ExecuteRawStatement() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryRawStatement(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
query string
|
||||
args []any
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *sql.Rows
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 01: Empty Query",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
query: "",
|
||||
args: nil,
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 02: Nil Query",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
query: "aasd",
|
||||
args: nil,
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := QueryRawStatement(tt.args.ctx, tt.args.db, tt.args.query, tt.args.args...)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("QueryRawStatement() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("QueryRawStatement() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error {
|
||||
|
||||
if anthrovePost == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: "anthrovePost is nil"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Create(&anthrovePost)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_post_id": anthrovePost.ID,
|
||||
"anthrove_post_rating": anthrovePost.Rating,
|
||||
}).Trace("database: created anthrove post")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreatePostInBatch(ctx context.Context, db *gorm.DB, anthrovePost []models.Post, batchSize int) error {
|
||||
if anthrovePost == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: "anthrovePost cannot be nil"}
|
||||
}
|
||||
|
||||
if len(anthrovePost) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "anthrovePost cannot be empty"}
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).CreateInBatches(anthrovePost, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_size": len(anthrovePost),
|
||||
"batch_size": batchSize,
|
||||
}).Trace("database: created tag node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (*models.Post, error) {
|
||||
|
||||
if anthrovePostID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "anthrovePostID is not set"}
|
||||
}
|
||||
|
||||
if len(anthrovePostID) != 25 {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
|
||||
}
|
||||
|
||||
var post models.Post
|
||||
result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
func GetPostBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) {
|
||||
|
||||
if sourceURL == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "sourceURL is not set"}
|
||||
}
|
||||
|
||||
var post models.Post
|
||||
result := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.url = $1 LIMIT 1`, sourceURL).First(&post)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID models.AnthroveSourceID) (*models.Post, error) {
|
||||
|
||||
if sourceID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "sourceID is not set"}
|
||||
}
|
||||
|
||||
var post models.Post
|
||||
result := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.source_id = $1 LIMIT 1`, sourceID).First(&post)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return &post, nil
|
||||
}
|
@ -1,469 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/test"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestCreateAnthrovePostNode(t *testing.T) {
|
||||
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Tests
|
||||
|
||||
validPost := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")),
|
||||
},
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
invalidPost := &models.Post{
|
||||
Rating: "error",
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthrovePost *models.Post
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid AnthrovePostID and Rating",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
db: gormDB,
|
||||
anthrovePost: validPost,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Invalid Rating",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
db: gormDB,
|
||||
anthrovePost: invalidPost,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: Nill",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
db: gormDB,
|
||||
anthrovePost: nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CreatePost(tt.args.ctx, tt.args.db, tt.args.anthrovePost); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreatePost() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPostByAnthroveID(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Tests
|
||||
|
||||
post := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")),
|
||||
},
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
err = CreatePost(ctx, gormDB, post)
|
||||
if err != nil {
|
||||
t.Fatal("Could not create post", err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthrovePostID models.AnthrovePostID
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *models.Post
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid anthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
want: post,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Invalid anthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePostID: "1234",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: No anthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePostID: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetPostByAnthroveID(tt.args.ctx, tt.args.db, tt.args.anthrovePostID)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetPostByAnthroveID() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !checkPost(got, tt.want) {
|
||||
t.Errorf("GetPostByAnthroveID() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPostBySourceURL(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Tests
|
||||
post := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")),
|
||||
},
|
||||
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
err = CreatePost(ctx, gormDB, post)
|
||||
if err != nil {
|
||||
t.Fatal("Could not create post", err)
|
||||
}
|
||||
|
||||
source := models.Source{
|
||||
BaseModel: models.BaseModel[models.AnthroveSourceID]{
|
||||
ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")),
|
||||
},
|
||||
DisplayName: "e621",
|
||||
Domain: "e621.net",
|
||||
Icon: "https://e621.net/icon.ico",
|
||||
}
|
||||
|
||||
err = CreateSource(ctx, gormDB, &source)
|
||||
if err != nil {
|
||||
t.Fatal("Could not create source", err)
|
||||
}
|
||||
|
||||
err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.org", models.PostReferenceConfig{})
|
||||
if err != nil {
|
||||
t.Fatal("Could not create source reference", err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
sourceURL string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *models.Post
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid sourceURL",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
sourceURL: "http://test.org",
|
||||
},
|
||||
want: post,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Invalid sourceURL",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
sourceURL: "1234",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: No sourceURL",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
sourceURL: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetPostBySourceURL(tt.args.ctx, tt.args.db, tt.args.sourceURL)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetPostBySourceURL() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !checkPost(got, tt.want) {
|
||||
t.Errorf("GetPostBySourceURL() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPostBySourceID(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Tests
|
||||
|
||||
post := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")),
|
||||
},
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
err = CreatePost(ctx, gormDB, post)
|
||||
if err != nil {
|
||||
t.Fatal("Could not create post", err)
|
||||
}
|
||||
|
||||
source := models.Source{
|
||||
BaseModel: models.BaseModel[models.AnthroveSourceID]{
|
||||
ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")),
|
||||
},
|
||||
DisplayName: "e621",
|
||||
Domain: "e621.net",
|
||||
Icon: "https://e621.net/icon.ico",
|
||||
}
|
||||
|
||||
err = CreateSource(ctx, gormDB, &source)
|
||||
if err != nil {
|
||||
t.Fatal("Could not create source", err)
|
||||
}
|
||||
|
||||
err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.otg", models.PostReferenceConfig{})
|
||||
if err != nil {
|
||||
t.Fatal("Could not create source reference", err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
sourceID models.AnthroveSourceID
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *models.Post
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid sourceID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
sourceID: source.ID,
|
||||
},
|
||||
want: post,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Invalid sourceID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
sourceID: "1234",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: No sourceID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
sourceID: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetPostBySourceID(tt.args.ctx, tt.args.db, tt.args.sourceID)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetPostBySourceID() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !checkPost(got, tt.want) {
|
||||
t.Errorf("GetPostBySourceID() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePostInBatch(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Tests
|
||||
|
||||
validPosts := []models.Post{
|
||||
{
|
||||
Rating: models.SFW,
|
||||
},
|
||||
{
|
||||
Rating: models.NSFW,
|
||||
},
|
||||
{
|
||||
Rating: models.Questionable,
|
||||
},
|
||||
}
|
||||
|
||||
emptyPost := []models.Post{}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthrovePost []models.Post
|
||||
batchSize int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid Data",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePost: validPosts,
|
||||
batchSize: len(validPosts),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Emtpy Data",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePost: emptyPost,
|
||||
batchSize: 0,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: Nil Data",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePost: nil,
|
||||
batchSize: 0,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 4: batchSize 0",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthrovePost: validPosts,
|
||||
batchSize: 0,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CreatePostInBatch(tt.args.ctx, tt.args.db, tt.args.anthrovePost, tt.args.batchSize); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreatePostInBatch() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func checkPost(got *models.Post, want *models.Post) bool {
|
||||
|
||||
if got == nil && want == nil {
|
||||
return true
|
||||
} else if got == nil || want == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if got.ID != want.ID {
|
||||
return false
|
||||
}
|
||||
|
||||
if got.Rating != want.Rating {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error {
|
||||
if anthrovePostID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthrovePostID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if sourceDomain == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Exec(`INSERT INTO "PostReference" (post_id, source_id, url, full_file_url, preview_file_url, sample_file_url, source_post_id) SELECT $1, source.id, $2, $4, $5, $6, $7 FROM "Source" AS source WHERE domain = $3;`, anthrovePostID, postURL, sourceDomain, config.FullFileURL, config.PreviewFileURL, config.SampleFileURL, config.SourcePostID)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.NoDataFound{}
|
||||
}
|
||||
if errors.Is(result.Error, gorm.ErrCheckConstraintViolated) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_post_id": anthrovePostID,
|
||||
"anthrove_source_domain": sourceDomain,
|
||||
}).Trace("database: created anthrove post to source link")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error {
|
||||
|
||||
if anthrovePostID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthrovePostID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
|
||||
}
|
||||
|
||||
userFavorite := models.UserFavorite{
|
||||
UserID: string(anthroveUserID),
|
||||
PostID: string(anthrovePostID),
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Create(&userFavorite)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
"anthrove_post_id": anthrovePostID,
|
||||
}).Trace("database: created user to post link")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) {
|
||||
var count int64
|
||||
|
||||
if anthrovePostID == "" {
|
||||
return false, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthrovePostID) != 25 {
|
||||
return false, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return false, &otterError.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return false, &otterError.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return false, &otterError.NoDataFound{}
|
||||
}
|
||||
return false, result.Error
|
||||
}
|
||||
|
||||
exists := count > 0
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"relationship_exists": exists,
|
||||
"relationship_anthrove_user_id": anthroveUserID,
|
||||
"relationship_anthrove_post_id": anthrovePostID,
|
||||
}).Trace("database: checked user post relationship")
|
||||
|
||||
return exists, nil
|
||||
}
|
@ -1,392 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/test"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestCheckUserToPostLink(t *testing.T) {
|
||||
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Test
|
||||
|
||||
validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1"))
|
||||
invalidUserID := models.AnthroveUserID("XXX")
|
||||
|
||||
validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1"))
|
||||
|
||||
err = CreateUser(ctx, gormDB, validUserID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
post := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: validPostID,
|
||||
},
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
err = CreatePost(ctx, gormDB, post)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthroveUserID models.AnthroveUserID
|
||||
anthrovePostID models.AnthrovePostID
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid AnthroveUserID and AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: validUserID,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
want: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: validUserID,
|
||||
anthrovePostID: "qadw",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: "123456",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 5: No AnthrovePostID given",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: "",
|
||||
anthrovePostID: "123456",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 6: No anthrovePostID given",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: "",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckUserToPostLinkWithNoData(t *testing.T) {
|
||||
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Test
|
||||
|
||||
validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1"))
|
||||
invalidUserID := models.AnthroveUserID("XXX")
|
||||
|
||||
validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1"))
|
||||
|
||||
err = CreateUser(ctx, gormDB, validUserID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
post := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: validPostID,
|
||||
},
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
err = CreatePost(ctx, gormDB, post)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthroveUserID models.AnthroveUserID
|
||||
anthrovePostID models.AnthrovePostID
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid AnthroveUserID and AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: validUserID,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
want: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: validUserID,
|
||||
anthrovePostID: "qadw",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: "123456",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 5: No AnthrovePostID given",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: "",
|
||||
anthrovePostID: "123456",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 6: No anthrovePostID given",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: "",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEstablishUserToPostLink(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Test
|
||||
|
||||
validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1"))
|
||||
invalidUserID := models.AnthroveUserID("XXX")
|
||||
|
||||
validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1"))
|
||||
|
||||
err = CreateUser(ctx, gormDB, validUserID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
post := &models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: validPostID,
|
||||
},
|
||||
Rating: "safe",
|
||||
}
|
||||
|
||||
err = CreatePost(ctx, gormDB, post)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthroveUserID models.AnthroveUserID
|
||||
anthrovePostID models.AnthrovePostID
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid AnthroveUserID and AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: validUserID,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: validUserID,
|
||||
anthrovePostID: "123456",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: invalid AnthroveUserID and valid AnthrovePostID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: post.ID,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: "123456",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 5: AnthrovePostID is empty",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: invalidUserID,
|
||||
anthrovePostID: "",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 6: anthroveUserID is empty",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveUserID: "",
|
||||
anthrovePostID: validPostID,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CreateReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreateReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CreateSource creates a pgModels.Source
|
||||
func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error {
|
||||
|
||||
if anthroveSource.Domain == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "Domain is required"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Where(models.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"node_source_url": anthroveSource.Domain,
|
||||
"node_source_displayName": anthroveSource.DisplayName,
|
||||
"node_source_icon": anthroveSource.Icon,
|
||||
}).Trace("database: created source node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllSource returns a list of all pgModels.Source
|
||||
func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) {
|
||||
var sources []models.Source
|
||||
|
||||
result := db.WithContext(ctx).Find(&sources)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_amount": result.RowsAffected,
|
||||
}).Trace("database: get all source nodes")
|
||||
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// GetSourceByDomain returns the first source it finds based on the domain
|
||||
func GetSourceByDomain(ctx context.Context, db *gorm.DB, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) {
|
||||
var sources models.Source
|
||||
|
||||
if sourceDomain == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "AnthroveSourceDomain is not set"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&sources)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_amount": result.RowsAffected,
|
||||
}).Trace("database: get all source nodes")
|
||||
|
||||
return &sources, nil
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/test"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestCreateSourceNode(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Test
|
||||
|
||||
validPostID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Post1"))
|
||||
|
||||
validSource := &models.Source{
|
||||
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID},
|
||||
DisplayName: "e621",
|
||||
Domain: "e621.net",
|
||||
Icon: "icon.e621.net",
|
||||
}
|
||||
|
||||
invalidSource := &models.Source{
|
||||
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID},
|
||||
Domain: "notfound.intern",
|
||||
}
|
||||
|
||||
invalidSourceDomain := &models.Source{
|
||||
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID},
|
||||
Domain: "",
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
anthroveSource *models.Source
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid anthroveSource",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveSource: validSource,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: inValid anthroveSource",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveSource: invalidSourceDomain,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 3: unique anthroveSource",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
anthroveSource: invalidSource,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CreateSource(tt.args.ctx, tt.args.db, tt.args.anthroveSource); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreateSource() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllSourceNodes(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Test
|
||||
|
||||
sources := []models.Source{
|
||||
{
|
||||
DisplayName: "e621",
|
||||
Domain: "e621.net",
|
||||
Icon: "icon.e621.net",
|
||||
},
|
||||
{
|
||||
DisplayName: "furaffinity",
|
||||
Domain: "furaffinity.net",
|
||||
Icon: "icon.furaffinity.net",
|
||||
},
|
||||
{
|
||||
DisplayName: "fenpaws",
|
||||
Domain: "fenpa.ws",
|
||||
Icon: "icon.fenpa.ws",
|
||||
},
|
||||
}
|
||||
|
||||
for _, source := range sources {
|
||||
err = CreateSource(ctx, gormDB, &source)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []models.Source
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Get all entries",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
},
|
||||
want: sources,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetAllSource(tt.args.ctx, tt.args.db)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetAllSource() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !checkSourcesNode(got, tt.want) {
|
||||
t.Errorf("GetAllSource() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSourceNodesByURL(t *testing.T) {
|
||||
// Setup trow away container
|
||||
ctx := context.Background()
|
||||
container, gormDB, err := test.StartPostgresContainer(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start PostgreSQL container: %v", err)
|
||||
}
|
||||
defer container.Terminate(ctx)
|
||||
|
||||
// Setup Test
|
||||
|
||||
source := &models.Source{
|
||||
DisplayName: "e621",
|
||||
Domain: "e621.net",
|
||||
Icon: "icon.e621.net",
|
||||
}
|
||||
|
||||
err = CreateSource(ctx, gormDB, source)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
db *gorm.DB
|
||||
domain models.AnthroveSourceDomain
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *models.Source
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test 1: Valid URL",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
domain: "e621.net",
|
||||
},
|
||||
want: source,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test 2: Invalid URL",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
domain: "eeeee.net",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test 2: No URL",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
db: gormDB,
|
||||
domain: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetSourceByDomain(tt.args.ctx, tt.args.db, tt.args.domain)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetSourceByDomain() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !checkSourceNode(got, tt.want) {
|
||||
t.Errorf("GetSourceByDomain() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func checkSourcesNode(got []models.Source, want []models.Source) bool {
|
||||
for i, source := range want {
|
||||
if source.DisplayName != got[i].DisplayName {
|
||||
return false
|
||||
}
|
||||
if source.Domain != got[i].Domain {
|
||||
return false
|
||||
}
|
||||
if source.Icon != got[i].Icon {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
func checkSourceNode(got *models.Source, want *models.Source) bool {
|
||||
|
||||
if want == nil && got == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if got.Domain != want.Domain {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
@ -1,440 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName, tagType models.TagType) error {
|
||||
|
||||
if tagName == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"}
|
||||
}
|
||||
|
||||
if tagType == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Create(&models.Tag{Name: string(tagName), Type: tagType})
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_name": tagName,
|
||||
"tag_type": tagType,
|
||||
}).Trace("database: created tag node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTagInBatchAndUpdate(ctx context.Context, db *gorm.DB, tags []models.Tag, batchSize int) error {
|
||||
if len(tags) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "tags cannot be empty"}
|
||||
}
|
||||
|
||||
if tags == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: "tags cannot be nil"}
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).
|
||||
Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "name"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"tag_type"}),
|
||||
}).CreateInBatches(tags, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_size": len(tags),
|
||||
"batch_size": batchSize,
|
||||
}).Trace("database: created tag node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName) error {
|
||||
|
||||
if tagName == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Delete(&models.Tag{Name: string(tagName)})
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.NoDataFound{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_name": tagName,
|
||||
}).Trace("database: deleted tag")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAllTagByTagsType(ctx context.Context, db *gorm.DB, tagType models.TagType) ([]models.Tag, error) {
|
||||
var tags []models.Tag
|
||||
|
||||
if tagType == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&models.Tag{}).Where("tag_type = ?", tagType).Scan(&tags)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tags_length": len(tags),
|
||||
}).Trace("database: got tag")
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error {
|
||||
|
||||
if anthrovePostID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"}
|
||||
}
|
||||
|
||||
if len(anthrovePostID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
|
||||
}
|
||||
|
||||
if tag == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: "Tag is nil"}
|
||||
}
|
||||
|
||||
pgPost := models.Post{
|
||||
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
||||
ID: anthrovePostID,
|
||||
},
|
||||
}
|
||||
|
||||
err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return &otterError.NoDataFound{}
|
||||
}
|
||||
return errors.Join(err, &otterError.NoRelationCreated{})
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_post_id": anthrovePostID,
|
||||
"tag_name": tag.Name,
|
||||
"tag_type": tag.Type,
|
||||
}).Trace("database: created tag node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) {
|
||||
var tags []models.Tag
|
||||
|
||||
result := db.WithContext(ctx).Find(&tags)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_amount": len(tags),
|
||||
}).Trace("database: got tags")
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func CreateTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error {
|
||||
|
||||
if tagAliasName == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"}
|
||||
}
|
||||
if tagID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "name"}},
|
||||
DoNothing: true,
|
||||
}).Create(&models.TagAlias{
|
||||
Name: string(tagAliasName),
|
||||
TagID: string(tagID),
|
||||
})
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_name": tagAliasName,
|
||||
"tag_alias_tag_id": tagID,
|
||||
}).Trace("database: created tagAlias")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTagAliasInBatch(ctx context.Context, db *gorm.DB, tagAliases []models.TagAlias, batchSize int) error {
|
||||
if len(tagAliases) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be empty"}
|
||||
}
|
||||
|
||||
if tagAliases == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be nil"}
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "name"}},
|
||||
DoNothing: true,
|
||||
}).CreateInBatches(tagAliases, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_size": len(tagAliases),
|
||||
"batch_size": batchSize,
|
||||
}).Trace("database: created tag node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAllTagAlias(ctx context.Context, db *gorm.DB) ([]models.TagAlias, error) {
|
||||
var tagAliases []models.TagAlias
|
||||
|
||||
result := db.WithContext(ctx).Find(&tagAliases)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_length": len(tagAliases),
|
||||
}).Trace("database: created tagAlias")
|
||||
|
||||
return tagAliases, nil
|
||||
}
|
||||
|
||||
func GetAllTagAliasByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagAlias, error) {
|
||||
var tagAliases []models.TagAlias
|
||||
|
||||
if tagID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagAliases)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_length": len(tagAliases),
|
||||
"tag_alias_tag_id": tagID,
|
||||
}).Trace("database: get specific tagAlias")
|
||||
|
||||
return tagAliases, nil
|
||||
}
|
||||
|
||||
func DeleteTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName) error {
|
||||
|
||||
if tagAliasName == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Delete(&models.TagAlias{Name: string(tagAliasName)})
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.NoDataFound{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_name": tagAliasName,
|
||||
}).Trace("database: deleted tagAlias")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error {
|
||||
|
||||
if tagGroupName == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"}
|
||||
}
|
||||
if tagID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Create(&models.TagGroup{
|
||||
Name: string(tagGroupName),
|
||||
TagID: string(tagID),
|
||||
})
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_group_name": tagGroupName,
|
||||
"tag_group_tag_id": tagID,
|
||||
}).Trace("database: created tagGroup")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTagGroupInBatch(ctx context.Context, db *gorm.DB, tagGroups []models.TagGroup, batchSize int) error {
|
||||
if len(tagGroups) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be empty"}
|
||||
}
|
||||
|
||||
if tagGroups == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be nil"}
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).CreateInBatches(tagGroups, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_size": len(tagGroups),
|
||||
"batch_size": batchSize,
|
||||
}).Trace("database: created tag node")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAllTagGroup(ctx context.Context, db *gorm.DB) ([]models.TagGroup, error) {
|
||||
var tagGroups []models.TagGroup
|
||||
|
||||
result := db.WithContext(ctx).Find(&tagGroups)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_length": len(tagGroups),
|
||||
}).Trace("database: created tagGroup")
|
||||
|
||||
return tagGroups, nil
|
||||
}
|
||||
|
||||
func GetAllTagGroupByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagGroup, error) {
|
||||
var tagGroups []models.TagGroup
|
||||
|
||||
if tagID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagGroups)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_length": len(tagGroups),
|
||||
"tag_alias_tag_id": tagID,
|
||||
}).Trace("database: get specific tagGroup")
|
||||
|
||||
return tagGroups, nil
|
||||
}
|
||||
|
||||
func DeleteTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName) error {
|
||||
|
||||
if tagGroupName == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Delete(&models.TagGroup{Name: string(tagGroupName)})
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.NoDataFound{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"tag_alias_name": tagGroupName,
|
||||
}).Trace("database: deleted tagAlias")
|
||||
|
||||
return nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,398 +0,0 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
gonanoid "github.com/matoous/go-nanoid/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Workaround, should be changed later maybe, but its not that bad right now
|
||||
type selectFrequencyTag struct {
|
||||
tagName string `gorm:"tag_name"`
|
||||
count int64 `gorm:"count"`
|
||||
tagType models.TagType `gorm:"tag_type"`
|
||||
}
|
||||
|
||||
func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error {
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
BaseModel: models.BaseModel[models.AnthroveUserID]{
|
||||
ID: anthroveUserID,
|
||||
},
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).FirstOrCreate(&user)
|
||||
if result.Error != nil {
|
||||
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error {
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if accountId == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "accountID cannot be empty"}
|
||||
}
|
||||
|
||||
if accountUsername == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"}
|
||||
}
|
||||
|
||||
validationCode, err := gonanoid.New(25)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Exec(`WITH userObj AS (
|
||||
INSERT INTO "User" (id)
|
||||
VALUES ($1)
|
||||
ON CONFLICT (id) DO NOTHING
|
||||
)
|
||||
INSERT INTO "UserSource" (user_id, source_id, account_username, account_id, account_validate, account_validation_key)
|
||||
SELECT $2, source.id, $3, $4, false, $5
|
||||
FROM "Source" AS source
|
||||
WHERE source.id = $6;`, anthroveUserID, anthroveUserID, accountUsername, accountId, validationCode, sourceID)
|
||||
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.EntityAlreadyExists{}
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return &otterError.NoDataWritten{}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
"source_id": sourceID,
|
||||
"account_username": accountUsername,
|
||||
"account_id": accountId,
|
||||
}).Info("database: created user-source relationship")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (int64, error) {
|
||||
var count int64
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return 0, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return 0, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return 0, &otterError.NoDataFound{}
|
||||
}
|
||||
return 0, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
"anthrove_user_fav_count": count,
|
||||
}).Trace("database: got user favorite count")
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) {
|
||||
var userSources []models.UserSource
|
||||
userSourceMap := make(map[string]models.UserSource)
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
for _, userSource := range userSources {
|
||||
var source models.Source
|
||||
result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
userSourceMap[source.DisplayName] = models.UserSource{
|
||||
UserID: userSource.AccountID,
|
||||
AccountUsername: userSource.AccountUsername,
|
||||
Source: models.Source{
|
||||
DisplayName: source.DisplayName,
|
||||
Domain: source.Domain,
|
||||
Icon: source.Icon,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
}).Trace("database: got user source link")
|
||||
|
||||
return userSourceMap, nil
|
||||
}
|
||||
|
||||
func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) {
|
||||
var userSource models.UserSource
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if sourceID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "sourceID cannot be empty"}
|
||||
}
|
||||
|
||||
if len(sourceID) != 25 {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: "sourceID needs to be 25 characters long"}
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSource)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
"source_id": sourceID,
|
||||
}).Trace("database: got specified user source link")
|
||||
|
||||
return &userSource, nil
|
||||
}
|
||||
|
||||
func GetAllUsers(ctx context.Context, db *gorm.DB) ([]models.User, error) {
|
||||
var users []models.User
|
||||
|
||||
result := db.WithContext(ctx).Model(&models.User{}).Find(&users)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id_count": len(users),
|
||||
}).Trace("database: got all anthrove user IDs")
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// TODO: FIX THE TEST
|
||||
func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) {
|
||||
var favoritePosts []models.Post
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
db.WithContext(ctx).Joins("RIGHT JOIN \"UserFavorite\" AS of ON \"Post\".id = of.post_id AND of.user_id = ?", anthroveUserID).Preload("References").Offset(skip).Limit(limit).Find(&favoritePosts)
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
"anthrove_user_fav_count": len(favoritePosts),
|
||||
}).Trace("database: got all anthrove user favorites")
|
||||
|
||||
return &models.FavoriteList{Posts: favoritePosts}, nil
|
||||
}
|
||||
|
||||
func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) {
|
||||
var queryUserFavorites []selectFrequencyTag
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
rows, err := db.WithContext(ctx).Raw(
|
||||
`WITH user_posts AS (
|
||||
SELECT post_id FROM "UserFavorite" WHERE user_id = $1
|
||||
)
|
||||
SELECT post_tags.tag_name AS tag_name, count(*) AS count, (SELECT tag_type FROM "Tag" WHERE "Tag".name = post_tags.tag_name LIMIT 1) AS tag_type FROM post_tags, user_posts WHERE post_tags.post_id IN (user_posts.post_id) GROUP BY post_tags.tag_name ORDER BY tag_type DESC, tag_name DESC`, anthroveUserID).Rows()
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, &otterError.NoDataFound{}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userFavoritesFrequency = make([]models.TagsWithFrequency, 0)
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var tagName string
|
||||
var count int64
|
||||
var tagType string
|
||||
rows.Scan(&tagName, &count, &tagType)
|
||||
userFavoritesFrequency = append(userFavoritesFrequency, models.TagsWithFrequency{
|
||||
Frequency: count,
|
||||
Tags: models.Tag{
|
||||
Name: tagName,
|
||||
Type: models.TagType(tagType),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"anthrove_user_id": anthroveUserID,
|
||||
"tag_amount": len(queryUserFavorites),
|
||||
}).Trace("database: got user tag node with relation to faved posts")
|
||||
|
||||
return userFavoritesFrequency, nil
|
||||
}
|
||||
|
||||
func UpdateUserSourceScrapeTimeInterval(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error {
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if sourceID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty}
|
||||
}
|
||||
|
||||
if len(sourceID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort}
|
||||
}
|
||||
|
||||
if scrapeTime == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: "ScrapeTimeInterval cannot be empty"}
|
||||
}
|
||||
|
||||
userSource := &models.UserSource{
|
||||
UserID: string(anthroveUserID),
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&userSource).Update("scrape_time_interval", scrapeTime)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateUserSourceLastScrapeTime(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error {
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if sourceID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty}
|
||||
}
|
||||
|
||||
if len(sourceID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort}
|
||||
}
|
||||
|
||||
if time.Time.IsZero(time.Time(lastScrapeTime)) {
|
||||
return &otterError.EntityValidationFailed{Reason: "LastScrapeTime cannot be empty"}
|
||||
}
|
||||
|
||||
userSource := &models.UserSource{
|
||||
UserID: string(anthroveUserID),
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&userSource).Update("last_scrape_time", time.Time(lastScrapeTime))
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateUserSourceValidation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error {
|
||||
|
||||
if anthroveUserID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(anthroveUserID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort}
|
||||
}
|
||||
|
||||
if sourceID == "" {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty}
|
||||
}
|
||||
|
||||
if len(sourceID) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort}
|
||||
}
|
||||
|
||||
userSource := &models.UserSource{
|
||||
UserID: string(anthroveUserID),
|
||||
}
|
||||
|
||||
result := db.WithContext(ctx).Model(&userSource).Update("account_validate", valid)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -2,12 +2,15 @@ package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
func HandleError(ctx context.Context, span trace.Span, logger *log.Logger, fields log.Fields, error error) error {
|
||||
logger.WithContext(ctx).WithFields(fields).Error(error)
|
||||
func HandleError(ctx context.Context, span trace.Span, logger *log.Entry, error error) error {
|
||||
logger.Error(error)
|
||||
span.RecordError(error)
|
||||
span.SetStatus(codes.Error, error.Error())
|
||||
return error
|
||||
}
|
||||
|
20
internal/utils/tracing.go
Normal file
20
internal/utils/tracing.go
Normal file
@ -0,0 +1,20 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
func SetupTracing(ctx context.Context, tracer trace.Tracer, tracerName string) (context.Context, trace.Span, *log.Entry) {
|
||||
ctx, span := tracer.Start(ctx, tracerName)
|
||||
localLogger := log.WithContext(ctx)
|
||||
|
||||
return ctx, span, localLogger
|
||||
}
|
||||
|
||||
func HandleEvent(span trace.Span, logger *log.Entry, eventName string) {
|
||||
logger.Debug(eventName)
|
||||
span.AddEvent(eventName)
|
||||
}
|
@ -4,12 +4,15 @@ import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
migrate "github.com/rubenv/sql-migrate"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/contrib/bridges/otellogrus"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
@ -22,12 +25,28 @@ var (
|
||||
embedMigrations embed.FS
|
||||
client *gorm.DB
|
||||
tracer trace.Tracer
|
||||
logger *log.Logger
|
||||
logger = log.New()
|
||||
)
|
||||
|
||||
func Connect(_ context.Context, config models.DatabaseConfig) error {
|
||||
var localSSL string
|
||||
func Connect(ctx context.Context, config models.DatabaseConfig) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "Connect")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"endpoint": config.Endpoint,
|
||||
"port": config.Port,
|
||||
"database": config.Database,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("endpoint", config.Endpoint),
|
||||
attribute.Int("port", config.Port),
|
||||
attribute.String("database", config.Database),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting database connection")
|
||||
|
||||
var localSSL string
|
||||
if config.SSL {
|
||||
localSSL = "require"
|
||||
} else {
|
||||
@ -36,46 +55,58 @@ func Connect(_ context.Context, config models.DatabaseConfig) error {
|
||||
|
||||
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone)
|
||||
sqlDB, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
return utils.HandleError(ctx, span, localLogger, err)
|
||||
}
|
||||
|
||||
err = migrateDatabase(sqlDB, config)
|
||||
err = migrateDatabase(ctx, sqlDB, config)
|
||||
if err != nil {
|
||||
return err
|
||||
return utils.HandleError(ctx, span, localLogger, err)
|
||||
}
|
||||
|
||||
setupTelemetry()
|
||||
|
||||
client = sqlDB
|
||||
utils.HandleEvent(span, localLogger, "Database connected successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrateDatabase(dbPool *gorm.DB, config models.DatabaseConfig) error {
|
||||
func migrateDatabase(ctx context.Context, dbPool *gorm.DB, config models.DatabaseConfig) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "migrateDatabase")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"database": config.Database,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("database", config.Database),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting database migration")
|
||||
|
||||
dialect := "postgres"
|
||||
migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"}
|
||||
|
||||
db, err := dbPool.DB()
|
||||
if err != nil {
|
||||
return fmt.Errorf("postgres migration: %v", err)
|
||||
return utils.HandleError(ctx, span, localLogger, err)
|
||||
}
|
||||
|
||||
n, err := migrate.Exec(db, dialect, migrations, migrate.Up)
|
||||
if err != nil {
|
||||
return fmt.Errorf("postgres migration: %v", err)
|
||||
return utils.HandleError(ctx, span, localLogger, err)
|
||||
}
|
||||
|
||||
if config.Debug {
|
||||
if n != 0 {
|
||||
log.Infof("postgres migration: applied %d migrations!", n)
|
||||
|
||||
localLogger.Infof("postgres migration: applied %d migrations!", n)
|
||||
} else {
|
||||
log.Info("postgres migration: nothing to migrate")
|
||||
|
||||
localLogger.Info("postgres migration: nothing to migrate")
|
||||
}
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Database migration completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -84,13 +115,18 @@ func setupTelemetry() {
|
||||
|
||||
hook := otellogrus.NewHook(tracingName)
|
||||
logger.AddHook(hook)
|
||||
|
||||
}
|
||||
|
||||
func GetGorm(ctx context.Context) (*gorm.DB, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetGorm")
|
||||
defer span.End()
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Retrieving GORM client")
|
||||
|
||||
if client == nil {
|
||||
return nil, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return nil, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "GORM client retrieved successfully")
|
||||
return client, nil
|
||||
}
|
||||
|
@ -3,62 +3,105 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateUserFavorite(ctx context.Context, userFav models.UserFavorite) (models.UserFavorite, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateUserFavorite")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_favorite_id": userFav.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_favorite_id", string(userFav.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user favorite creation")
|
||||
|
||||
if client == nil {
|
||||
return models.UserFavorite{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Create(&userFav)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.UserFavorite{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.UserFavorite{}, result.Error
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User favorite created successfully")
|
||||
return userFav, nil
|
||||
}
|
||||
|
||||
func CreateUserFavoriteInBatch(ctx context.Context, userFav []models.UserFavorite, batchSize int) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateUserFavoriteInBatch")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_favorite_count": len(userFav),
|
||||
"batch_size": batchSize,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.Int("batch_size", batchSize),
|
||||
attribute.Int("user_favorite_count", len(userFav)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting batch user favorite creation")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if userFav == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteListIsEmpty}
|
||||
}
|
||||
|
||||
if len(userFav) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteListIsEmpty}
|
||||
if userFav == nil || len(userFav) == 0 {
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteListIsEmpty})
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).CreateInBatches(&userFav, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Batch user favorites created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateUserFavorite(ctx context.Context, userFav models.UserFavorite) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "UpdateUserFavorite")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_favorite_id": userFav.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_favorite_id", string(userFav.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user favorite update")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(userFav.ID) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDIsEmpty})
|
||||
}
|
||||
|
||||
if !userFav.DeletedAt.Valid {
|
||||
@ -68,58 +111,87 @@ func UpdateUserFavorite(ctx context.Context, userFav models.UserFavorite) error
|
||||
result := client.WithContext(ctx).Model(&userFav).Update("deleted_at", gorm.DeletedAt{})
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User favorite updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUserFavoritesByID(ctx context.Context, id models.UserFavoriteID) (models.UserFavorite, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetUserFavoritesByID")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_favorite_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_favorite_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting get user favorite by ID")
|
||||
|
||||
var userFavorites models.UserFavorite
|
||||
|
||||
if client == nil {
|
||||
return models.UserFavorite{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return models.UserFavorite{}, &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDIsEmpty}
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).First(&userFavorites, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return models.UserFavorite{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return models.UserFavorite{}, result.Error
|
||||
return models.UserFavorite{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User favorite retrieved successfully")
|
||||
return userFavorites, nil
|
||||
}
|
||||
|
||||
func DeleteUserFavorite(ctx context.Context, id models.UserFavoriteID) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteUserFavorite")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_favorite_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_favorite_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting delete user favorite")
|
||||
|
||||
var userFavorite models.UserFavorite
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDIsEmpty})
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDToShort}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserFavoriteIDToShort})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&userFavorite, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User favorite deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,84 +3,141 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreatePost(ctx context.Context, post models.Post) (models.Post, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreatePost")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"post_id": post.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("post_id", string(post.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting post creation")
|
||||
|
||||
if client == nil {
|
||||
return models.Post{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Create(&post)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.Post{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.Post{}, result.Error
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Post created successfully")
|
||||
return post, nil
|
||||
}
|
||||
|
||||
func CreatePostInBatch(ctx context.Context, post []models.Post, batchSize int) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreatePostInBatch")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"post_count": len(post),
|
||||
"batch_size": batchSize,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.Int("batch_size", batchSize),
|
||||
attribute.Int("post_count", len(post)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting batch post creation")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if post == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.PostListIsEmpty}
|
||||
}
|
||||
|
||||
if len(post) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.PostListIsEmpty}
|
||||
if post == nil || len(post) == 0 {
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.PostListIsEmpty})
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).CreateInBatches(&post, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Batch posts created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetPostByID(ctx context.Context, id models.PostID) (models.Post, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetPostByID")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"post_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("post_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting get post by ID")
|
||||
|
||||
var post models.Post
|
||||
|
||||
if client == nil {
|
||||
return models.Post{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return models.Post{}, &otterError.EntityValidationFailed{Reason: otterError.PostIDIsEmpty}
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.PostIDIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).First(&post, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return models.Post{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return models.Post{}, result.Error
|
||||
return models.Post{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Post retrieved successfully")
|
||||
return post, nil
|
||||
}
|
||||
|
||||
func UpdatePost(ctx context.Context, anthrovePost models.Post) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "UpdatePost")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"post_id": anthrovePost.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("post_id", string(anthrovePost.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting post update")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(anthrovePost.ID) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.PostIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.PostIDIsEmpty})
|
||||
}
|
||||
|
||||
updatePost := models.Post{
|
||||
@ -92,36 +149,51 @@ func UpdatePost(ctx context.Context, anthrovePost models.Post) error {
|
||||
result := client.WithContext(ctx).Model(&updatePost).Update("deleted_at", gorm.DeletedAt{})
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Post updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeletePost(ctx context.Context, id models.PostID) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeletePost")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"post_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("post_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting delete post")
|
||||
|
||||
var userFavorite models.UserFavorite
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.PostIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.PostIDIsEmpty})
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.PostIDToShort}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.PostIDToShort})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&userFavorite, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Post deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,62 +3,105 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateSource(ctx context.Context, source models.Source) (models.Source, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateSource")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"source_id": source.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("source_id", string(source.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting source creation")
|
||||
|
||||
if client == nil {
|
||||
return models.Source{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Create(&source)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.Source{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.Source{}, result.Error
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Source created successfully")
|
||||
return source, nil
|
||||
}
|
||||
|
||||
func CreateSourceInBatch(ctx context.Context, source []models.Source, batchSize int) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateSourceInBatch")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"source_count": len(source),
|
||||
"batch_size": batchSize,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.Int("batch_size", batchSize),
|
||||
attribute.Int("source_count", len(source)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting batch source creation")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if source == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.SourceListIsEmpty}
|
||||
}
|
||||
|
||||
if len(source) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.SourceListIsEmpty}
|
||||
if source == nil || len(source) == 0 {
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceListIsEmpty})
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).CreateInBatches(&source, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Batch sources created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateSource(ctx context.Context, source models.Source) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "UpdateSource")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"source_id": source.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("source_id", string(source.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting source update")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(source.ID) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.SourceIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceIDIsEmpty})
|
||||
}
|
||||
|
||||
updateSource := models.Source{
|
||||
@ -70,84 +113,127 @@ func UpdateSource(ctx context.Context, source models.Source) error {
|
||||
result := client.WithContext(ctx).Model(&updateSource).Update("deleted_at", gorm.DeletedAt{})
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Source updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetSourceByID(ctx context.Context, id models.SourceID) (models.Source, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetSourceByID")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"source_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("source_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting get source by ID")
|
||||
|
||||
var source models.Source
|
||||
|
||||
if client == nil {
|
||||
return models.Source{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return models.Source{}, &otterError.EntityValidationFailed{Reason: otterError.SourceIDIsEmpty}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceIDIsEmpty})
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return models.Source{}, &otterError.EntityValidationFailed{Reason: otterError.SourceIDToShort}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceIDToShort})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).First(&source, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return models.Source{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return models.Source{}, result.Error
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Source retrieved successfully")
|
||||
return source, nil
|
||||
}
|
||||
|
||||
func GetSourceByDomain(ctx context.Context, sourceDomain models.SourceDomain) (models.Source, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetSourceByDomain")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"source_domain": sourceDomain,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("source_domain", string(sourceDomain)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting get source by domain")
|
||||
|
||||
var source models.Source
|
||||
|
||||
if client == nil {
|
||||
return models.Source{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(sourceDomain) == 0 {
|
||||
return models.Source{}, &otterError.EntityValidationFailed{Reason: otterError.SourceDomainIsEmpty}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceDomainIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).First(&source, "domain = ?", sourceDomain)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return models.Source{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return models.Source{}, result.Error
|
||||
return models.Source{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Source retrieved successfully")
|
||||
return source, nil
|
||||
}
|
||||
|
||||
func DeleteSource(ctx context.Context, id models.SourceID) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteSource")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"source_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("source_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting delete source")
|
||||
|
||||
var source models.Source
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.SourceIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceIDIsEmpty})
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.SourceIDToShort}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.SourceIDToShort})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&source, id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Source deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
@ -12,18 +13,23 @@ import (
|
||||
)
|
||||
|
||||
func CreateTag(ctx context.Context, tagName models.TagName, tagType models.TagType) (models.Tag, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateTag")
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTag")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_name": tagName,
|
||||
"tag_type": tagType,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("tag_name", string(tagName)),
|
||||
attribute.String("tag_type", string(tagType)),
|
||||
)
|
||||
|
||||
span.AddEvent("Starting tag creation")
|
||||
utils.HandleEvent(span, localLogger, "Starting tag creation")
|
||||
|
||||
if client == nil {
|
||||
return models.Tag{}, utils.HandleError(ctx, span, logger, nil, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
return models.Tag{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
tag := models.Tag{
|
||||
@ -31,131 +37,86 @@ func CreateTag(ctx context.Context, tagName models.TagName, tagType models.TagTy
|
||||
Type: tagType,
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).WithFields(log.Fields{
|
||||
"name": tagName,
|
||||
"type": tagType,
|
||||
}).Debug("attempting to create tag")
|
||||
|
||||
result := client.WithContext(ctx).Create(&tag)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
|
||||
loggerFields := log.Fields{
|
||||
"name": tagName,
|
||||
"type": tagType,
|
||||
return models.Tag{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.Tag{}, utils.HandleError(ctx, span, logger, loggerFields, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
return models.Tag{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
loggerFields := log.Fields{
|
||||
"name": tagName,
|
||||
"type": tagType,
|
||||
}
|
||||
return models.Tag{}, utils.HandleError(ctx, span, logger, loggerFields, result.Error)
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).WithFields(log.Fields{
|
||||
"name": tagName,
|
||||
"type": tagType,
|
||||
}).Debug("tag created")
|
||||
span.AddEvent("Tag created successfully")
|
||||
utils.HandleEvent(span, localLogger, "Tag created successfully")
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func CreateTagInBatch(ctx context.Context, tags []models.Tag, batchSize int) error {
|
||||
ctx, span := tracer.Start(ctx, "CreateTagInBatch")
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagInBatch")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_count": len(tags),
|
||||
"batch_size": batchSize,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.Int64("batch_size", int64(batchSize)),
|
||||
attribute.Int64("tag_count", int64(len(tags))),
|
||||
attribute.Int("batch_size", batchSize),
|
||||
attribute.Int("tag_count", len(tags)),
|
||||
)
|
||||
|
||||
span.AddEvent("Starting batch tag creation")
|
||||
utils.HandleEvent(span, localLogger, "Starting batch tag creation")
|
||||
|
||||
if client == nil {
|
||||
return utils.HandleError(ctx, span, logger, nil, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if tags == nil || len(tags) == 0 {
|
||||
return utils.HandleError(ctx, span, logger, nil, &otterError.EntityValidationFailed{Reason: otterError.TagListIsEmpty})
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.TagListIsEmpty})
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return utils.HandleError(ctx, span, logger, nil, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).WithFields(log.Fields{
|
||||
"tag_length": len(tags),
|
||||
}).Debug("attempting to create tags")
|
||||
|
||||
result := client.WithContext(ctx).CreateInBatches(&tags, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
loggerFields := log.Fields{
|
||||
"tag_length": len(tags),
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return utils.HandleError(ctx, span, logger, loggerFields, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
loggerFields := log.Fields{
|
||||
"tag_length": len(tags),
|
||||
}
|
||||
return utils.HandleError(ctx, span, logger, loggerFields, result.Error)
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).WithFields(log.Fields{
|
||||
"tag_length": len(tags),
|
||||
}).Debug("tags created")
|
||||
|
||||
span.AddEvent("Batch tags created successfully")
|
||||
utils.HandleEvent(span, localLogger, "Batch tags created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTag(ctx context.Context, tagName models.TagName) error {
|
||||
ctx, span := tracer.Start(ctx, "DeleteTag")
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteTag")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_name": tagName,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("tag_name", string(tagName)),
|
||||
)
|
||||
|
||||
span.AddEvent("Starting tag deletion")
|
||||
utils.HandleEvent(span, localLogger, "Starting tag deletion")
|
||||
|
||||
var tag models.Tag
|
||||
|
||||
if client == nil {
|
||||
return utils.HandleError(ctx, span, logger, nil, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(tagName) == 0 {
|
||||
return utils.HandleError(ctx, span, logger, nil, &otterError.Database{Reason: otterError.TagNameIsEmpty})
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).WithFields(log.Fields{
|
||||
"tag_name": tagName,
|
||||
}).Debug("attempting to delete tag")
|
||||
|
||||
result := client.WithContext(ctx).Delete(&tag, tagName)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
|
||||
loggerFields := log.Fields{
|
||||
"tag_name": tagName,
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return utils.HandleError(ctx, span, logger, loggerFields, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
loggerFields := log.Fields{
|
||||
"tag_name": tagName,
|
||||
}
|
||||
return utils.HandleError(ctx, span, logger, loggerFields, result.Error)
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).WithFields(log.Fields{
|
||||
"tag_name": tagName,
|
||||
}).Debug("tag deleted")
|
||||
|
||||
span.AddEvent("Tag deleted successfully")
|
||||
utils.HandleEvent(span, localLogger, "Tag deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,14 +3,33 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateTagAlias(ctx context.Context, tagAliasName models.TagAliasName, tagName models.TagName) (models.TagAlias, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagAlias")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_alias_name": tagAliasName,
|
||||
"tag_name": tagName,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("tag_alias_name", string(tagAliasName)),
|
||||
attribute.String("tag_name", string(tagName)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting tag alias creation")
|
||||
|
||||
if client == nil {
|
||||
return models.TagAlias{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
tagAlias := models.TagAlias{
|
||||
@ -21,60 +40,83 @@ func CreateTagAlias(ctx context.Context, tagAliasName models.TagAliasName, tagNa
|
||||
result := client.WithContext(ctx).Create(&tagAlias)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.TagAlias{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.TagAlias{}, result.Error
|
||||
return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Tag alias created successfully")
|
||||
return tagAlias, nil
|
||||
}
|
||||
|
||||
func CreateTagAliasInBatch(ctx context.Context, tagsAliases []models.TagAlias, batchSize int) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagAliasInBatch")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_aliases_count": len(tagsAliases),
|
||||
"batch_size": batchSize,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.Int("batch_size", batchSize),
|
||||
attribute.Int("tag_aliases_count", len(tagsAliases)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting batch tag alias creation")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if tagsAliases == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.TagAliasListIsEmpty}
|
||||
}
|
||||
|
||||
if len(tagsAliases) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.TagAliasListIsEmpty}
|
||||
if tagsAliases == nil || len(tagsAliases) == 0 {
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.TagAliasListIsEmpty})
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).CreateInBatches(&tagsAliases, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Batch tags aliases created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTagAlias(ctx context.Context, tagAliasName models.TagAliasName) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteTagAlias")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_alias_name": tagAliasName,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("tag_alias_name", string(tagAliasName)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting tag alias deletion")
|
||||
|
||||
var tagAlias models.TagAlias
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
}
|
||||
|
||||
if len(tagAliasName) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.TagAliasNameIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&tagAlias, tagAliasName)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Tag alias deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,14 +3,34 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateTagGroup(ctx context.Context, tagGroupName models.TagGroupName, tagName models.TagName) (models.TagGroup, error) {
|
||||
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagGroup")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_group_name": tagGroupName,
|
||||
"tag_name": tagName,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("tag_group_name", string(tagGroupName)),
|
||||
attribute.String("tag_name", string(tagName)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting tag group creation")
|
||||
|
||||
if client == nil {
|
||||
return models.TagGroup{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.TagGroup{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
tagGroup := models.TagGroup{
|
||||
@ -21,60 +41,89 @@ func CreateTagGroup(ctx context.Context, tagGroupName models.TagGroupName, tagNa
|
||||
result := client.WithContext(ctx).Create(&tagGroup)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.TagGroup{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.TagGroup{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.TagGroup{}, result.Error
|
||||
return models.TagGroup{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Tag group created successfully")
|
||||
return tagGroup, nil
|
||||
}
|
||||
|
||||
func CreateTagGroupInBatch(ctx context.Context, tagsGroups []models.TagGroup, batchSize int) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagAliasInBatch")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_groups_count": len(tagsGroups),
|
||||
"batch_size": batchSize,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.Int("batch_size", batchSize),
|
||||
attribute.Int("tag_group_count", len(tagsGroups)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting batch tag group creation")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if tagsGroups == nil {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.TagGroupListIsEmpty}
|
||||
}
|
||||
|
||||
if len(tagsGroups) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.TagGroupListIsEmpty}
|
||||
if tagsGroups == nil || len(tagsGroups) == 0 {
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.TagGroupListIsEmpty})
|
||||
}
|
||||
|
||||
if batchSize == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).CreateInBatches(&tagsGroups, batchSize)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Tag group created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTagGroup(ctx context.Context, tagGroupName models.TagGroupName) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteTagGroup")
|
||||
defer span.End()
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("tag_group_name", string(tagGroupName)),
|
||||
)
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"tag_group_name": tagGroupName,
|
||||
})
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting tag group deletion")
|
||||
|
||||
var tagGroup models.TagGroup
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(tagGroupName) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.TagGroupNameIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.TagGroupNameIsEmpty})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&tagGroup, tagGroupName)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Tag group deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,77 +3,106 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateUser(ctx context.Context, id models.UserID) (models.User, error) {
|
||||
if client == nil {
|
||||
return models.User{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
}
|
||||
func CreateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
|
||||
user := models.User{
|
||||
BaseModel: models.BaseModel[models.UserID]{
|
||||
ID: id,
|
||||
},
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateUser")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_id": user.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_id", string(user.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user creation")
|
||||
|
||||
if client == nil {
|
||||
return models.User{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Create(&user)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.User{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.User{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.User{}, result.Error
|
||||
return models.User{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User created successfully")
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func GetUserByID(ctx context.Context, id models.UserID) (models.User, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetUserByID")
|
||||
defer span.End()
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_id", string(id)),
|
||||
)
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_id": id,
|
||||
})
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user retrieval")
|
||||
|
||||
var user models.User
|
||||
|
||||
if client == nil {
|
||||
return models.User{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return models.User{}, &otterError.EntityValidationFailed{Reason: otterError.UserIDIsEmpty}
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return models.User{}, &otterError.EntityValidationFailed{Reason: otterError.UserIDToShort}
|
||||
return models.User{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).First(&user, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return models.User{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return models.User{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return models.User{}, result.Error
|
||||
return models.User{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User retrieved successfully")
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func DeleteUser(ctx context.Context, id models.UserID) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteUser")
|
||||
defer span.End()
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_id", string(id)),
|
||||
)
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_id": id,
|
||||
})
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user deletion")
|
||||
|
||||
var user models.User
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&user, id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
@ -3,34 +3,65 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/utils"
|
||||
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateUserSource(ctx context.Context, userSource models.UserSource) (models.UserSource, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateUserSource")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_source_id": userSource.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_source_id", string(userSource.SourceID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user source creation")
|
||||
|
||||
if client == nil {
|
||||
return models.UserSource{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Create(&userSource)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return models.UserSource{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return models.UserSource{}, result.Error
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User source created successfully")
|
||||
return userSource, nil
|
||||
}
|
||||
|
||||
func UpdateUserSource(ctx context.Context, userSource models.UserSource) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "UpdateUserSource")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_source_id": userSource.ID,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_source_id", string(userSource.ID)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting user source update")
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(userSource.ID) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.UserSourceIDIsEmpty})
|
||||
}
|
||||
|
||||
updatedUserSource := models.UserSource{
|
||||
@ -47,62 +78,89 @@ func UpdateUserSource(ctx context.Context, userSource models.UserSource) error {
|
||||
result := client.WithContext(ctx).Updates(&updatedUserSource)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
|
||||
}
|
||||
return result.Error
|
||||
return utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User source updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUserSourceByID(ctx context.Context, id models.UserSourceID) (models.UserSource, error) {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetUserSourceByID")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_source_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_source_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting get user source by ID")
|
||||
|
||||
var user models.UserSource
|
||||
|
||||
if client == nil {
|
||||
return models.UserSource{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return models.UserSource{}, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDIsEmpty}
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDIsEmpty})
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return models.UserSource{}, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDToShort}
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDToShort})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).First(&user, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return models.UserSource{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return models.UserSource{}, result.Error
|
||||
return models.UserSource{}, utils.HandleError(ctx, span, localLogger, result.Error)
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User source retrieved successfully")
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func DeleteUserSource(ctx context.Context, id models.UserSourceID) error {
|
||||
ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteUserSource")
|
||||
defer span.End()
|
||||
|
||||
localLogger.WithFields(log.Fields{
|
||||
"user_source_id": id,
|
||||
})
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("user_source_id", string(id)),
|
||||
)
|
||||
|
||||
utils.HandleEvent(span, localLogger, "Starting delete user source")
|
||||
|
||||
var user models.UserSource
|
||||
|
||||
if client == nil {
|
||||
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
|
||||
}
|
||||
|
||||
if len(id) == 0 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDIsEmpty}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDIsEmpty})
|
||||
}
|
||||
|
||||
if len(id) != 25 {
|
||||
return &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDToShort}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDToShort})
|
||||
}
|
||||
|
||||
result := client.WithContext(ctx).Delete(&user, id)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||
return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
utils.HandleEvent(span, localLogger, "User source deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user