From c6313f234bf25f741cfd4f93fd411ac54279a6d4 Mon Sep 17 00:00:00 2001 From: Rogee Date: Thu, 5 Dec 2024 11:32:00 +0800 Subject: [PATCH] fix: issues --- backend/common/media_store/store.go | 18 +- backend/config.toml | 4 + backend/database/.transform.yaml | 5 +- .../migrations/20241128075611_init.sql | 21 +- .../qvyun/public/model/media_resources.go | 24 --- .../models/qvyun/public/model/medias.go | 22 ++- .../qvyun/public/table/media_resources.go | 96 --------- .../models/qvyun/public/table/medias.go | 7 +- .../qvyun/public/table/table_use_schema.go | 1 - backend/modules/medias/controller.go | 13 +- backend/modules/medias/dto.go | 3 +- backend/modules/medias/service.go | 187 +++++++----------- backend/modules/medias/service_test.go | 130 ++++-------- backend/modules/tasks/store/store_medias.go | 45 +++++ backend/pkg/path/fs.go | 8 + backend/pkg/pg/media.go | 17 +- backend/providers/storage | 1 + 17 files changed, 206 insertions(+), 396 deletions(-) delete mode 100644 backend/database/models/qvyun/public/model/media_resources.go delete mode 100644 backend/database/models/qvyun/public/table/media_resources.go create mode 160000 backend/providers/storage diff --git a/backend/common/media_store/store.go b/backend/common/media_store/store.go index d6db2ad..79e1274 100644 --- a/backend/common/media_store/store.go +++ b/backend/common/media_store/store.go @@ -16,7 +16,7 @@ type UUIDMap struct { Name string } -func NewStore(path string) (*Store, error) { +func NewStore(path string) (Store, error) { mapFile := filepath.Join(path, "map.json") log.Infof("read in from: %s", mapFile) if _, err := os.Stat(mapFile); err != nil { @@ -38,10 +38,10 @@ func NewStore(path string) (*Store, error) { return nil, errors.Wrapf(err, "unmarshal json: %s", mapFile) } - return &store, nil + return store, nil } -func (s *Store) Save(path string) error { +func (s Store) Save(path string) error { mapFile := filepath.Join(path, "map.json") b, err := json.Marshal(s) if err != nil { @@ -55,13 +55,13 @@ func (s *Store) Save(path string) error { return nil } -func (s *Store) Add(uuid, name string) { - *s = append(*s, UUIDMap{UUID: uuid, Name: name}) +func (s Store) Add(uuid, name string) { + s = append(s, UUIDMap{UUID: uuid, Name: name}) } -func (s *Store) UUIDs() []string { +func (s Store) UUIDs() []string { var uuids []string - for _, m := range *s { + for _, m := range s { uuids = append(uuids, m.UUID) } @@ -69,8 +69,8 @@ func (s *Store) UUIDs() []string { } // Exists -func (s *Store) Exists(name string) bool { - for _, m := range *s { +func (s Store) Exists(name string) bool { + for _, m := range s { if m.Name == name { return true } diff --git a/backend/config.toml b/backend/config.toml index 342334e..e47890a 100755 --- a/backend/config.toml +++ b/backend/config.toml @@ -26,3 +26,7 @@ AesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI" [HashIDs] Salt = "LiXi.Y@140202" + +[Storage] +Type = "local" +Path = "/projects/mp-qvyun/backend/fixtures/medias" diff --git a/backend/database/.transform.yaml b/backend/database/.transform.yaml index 5c40142..0d987e6 100755 --- a/backend/database/.transform.yaml +++ b/backend/database/.transform.yaml @@ -2,6 +2,5 @@ ignores: [] # ignore tables types: users: # table name oauth: backend/pkg/pg.UserOAuth - - media_resources: # table name - type: backend/pkg/pg.MediaType + medias: + resources: backend/pkg/pg.MediaResources diff --git a/backend/database/migrations/20241128075611_init.sql b/backend/database/migrations/20241128075611_init.sql index 2607c8e..24c1eb0 100644 --- a/backend/database/migrations/20241128075611_init.sql +++ b/backend/database/migrations/20241128075611_init.sql @@ -71,10 +71,11 @@ CREATE TABLE uuid uuid NOT NULL, tenant_id INT8 NOT NULL, title VARCHAR(198) NOT NULL, - description VARCHAR(198) NOT NULL, - price INT8 NOT NULL, + description VARCHAR(198) NOT NULL default '', + price INT8 NOT NULL default 0, discount INT8 NOT NULL default 100, - publish BOOL NOT NULL, + publish BOOL NOT NULL default false, + resources jsonb default '{}'::jsonb, created_at timestamp NOT NULL default now(), updated_at timestamp NOT NULL default now() ); @@ -83,20 +84,6 @@ CREATE INDEX idx_medias_tenant_id ON medias (tenant_id); CREATE INDEX idx_medias_title ON medias (title); -CREATE TABLE - media_resources ( - id SERIAL8 PRIMARY KEY, - media_id INT8 NOT NULL, - type VARCHAR(128) NOT NULL, - source text NOT NULL default '', - size INT8 NOT NULL, - publish BOOL NOT NULL, - created_at timestamp NOT NULL default now(), - updated_at timestamp NOT NULL default now() - ); - -CREATE INDEX idx_media_resources_media_id ON media_resources (media_id); - CREATE TABLE user_medias ( id SERIAL8 PRIMARY KEY, user_id INT8 NOT NULL, diff --git a/backend/database/models/qvyun/public/model/media_resources.go b/backend/database/models/qvyun/public/model/media_resources.go deleted file mode 100644 index e7ffa76..0000000 --- a/backend/database/models/qvyun/public/model/media_resources.go +++ /dev/null @@ -1,24 +0,0 @@ -// -// Code generated by go-jet DO NOT EDIT. -// -// WARNING: Changes to this file may cause incorrect behavior -// and will be lost if the code is regenerated -// - -package model - -import ( - "backend/pkg/pg" - "time" -) - -type MediaResources struct { - ID int64 `sql:"primary_key" json:"id"` - MediaID int64 `json:"media_id"` - Type pg.MediaType `json:"type"` - Source string `json:"source"` - Size int64 `json:"size"` - Publish bool `json:"publish"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} diff --git a/backend/database/models/qvyun/public/model/medias.go b/backend/database/models/qvyun/public/model/medias.go index e7dc0d0..f51ab90 100644 --- a/backend/database/models/qvyun/public/model/medias.go +++ b/backend/database/models/qvyun/public/model/medias.go @@ -8,19 +8,21 @@ package model import ( + "backend/pkg/pg" "github.com/google/uuid" "time" ) type Medias struct { - ID int64 `sql:"primary_key" json:"id"` - UUID uuid.UUID `json:"uuid"` - TenantID int64 `json:"tenant_id"` - Title string `json:"title"` - Description string `json:"description"` - Price int64 `json:"price"` - Discount int64 `json:"discount"` - Publish bool `json:"publish"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ID int64 `sql:"primary_key" json:"id"` + UUID uuid.UUID `json:"uuid"` + TenantID int64 `json:"tenant_id"` + Title string `json:"title"` + Description string `json:"description"` + Price int64 `json:"price"` + Discount int64 `json:"discount"` + Publish bool `json:"publish"` + Resources pg.MediaResources `json:"resources"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } diff --git a/backend/database/models/qvyun/public/table/media_resources.go b/backend/database/models/qvyun/public/table/media_resources.go deleted file mode 100644 index afbbb13..0000000 --- a/backend/database/models/qvyun/public/table/media_resources.go +++ /dev/null @@ -1,96 +0,0 @@ -// -// Code generated by go-jet DO NOT EDIT. -// -// WARNING: Changes to this file may cause incorrect behavior -// and will be lost if the code is regenerated -// - -package table - -import ( - "github.com/go-jet/jet/v2/postgres" -) - -var MediaResources = newMediaResourcesTable("public", "media_resources", "") - -type mediaResourcesTable struct { - postgres.Table - - // Columns - ID postgres.ColumnInteger - MediaID postgres.ColumnInteger - Type postgres.ColumnString - Source postgres.ColumnString - Size postgres.ColumnInteger - Publish postgres.ColumnBool - CreatedAt postgres.ColumnTimestamp - UpdatedAt postgres.ColumnTimestamp - - AllColumns postgres.ColumnList - MutableColumns postgres.ColumnList -} - -type MediaResourcesTable struct { - mediaResourcesTable - - EXCLUDED mediaResourcesTable -} - -// AS creates new MediaResourcesTable with assigned alias -func (a MediaResourcesTable) AS(alias string) *MediaResourcesTable { - return newMediaResourcesTable(a.SchemaName(), a.TableName(), alias) -} - -// Schema creates new MediaResourcesTable with assigned schema name -func (a MediaResourcesTable) FromSchema(schemaName string) *MediaResourcesTable { - return newMediaResourcesTable(schemaName, a.TableName(), a.Alias()) -} - -// WithPrefix creates new MediaResourcesTable with assigned table prefix -func (a MediaResourcesTable) WithPrefix(prefix string) *MediaResourcesTable { - return newMediaResourcesTable(a.SchemaName(), prefix+a.TableName(), a.TableName()) -} - -// WithSuffix creates new MediaResourcesTable with assigned table suffix -func (a MediaResourcesTable) WithSuffix(suffix string) *MediaResourcesTable { - return newMediaResourcesTable(a.SchemaName(), a.TableName()+suffix, a.TableName()) -} - -func newMediaResourcesTable(schemaName, tableName, alias string) *MediaResourcesTable { - return &MediaResourcesTable{ - mediaResourcesTable: newMediaResourcesTableImpl(schemaName, tableName, alias), - EXCLUDED: newMediaResourcesTableImpl("", "excluded", ""), - } -} - -func newMediaResourcesTableImpl(schemaName, tableName, alias string) mediaResourcesTable { - var ( - IDColumn = postgres.IntegerColumn("id") - MediaIDColumn = postgres.IntegerColumn("media_id") - TypeColumn = postgres.StringColumn("type") - SourceColumn = postgres.StringColumn("source") - SizeColumn = postgres.IntegerColumn("size") - PublishColumn = postgres.BoolColumn("publish") - CreatedAtColumn = postgres.TimestampColumn("created_at") - UpdatedAtColumn = postgres.TimestampColumn("updated_at") - allColumns = postgres.ColumnList{IDColumn, MediaIDColumn, TypeColumn, SourceColumn, SizeColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn} - mutableColumns = postgres.ColumnList{MediaIDColumn, TypeColumn, SourceColumn, SizeColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn} - ) - - return mediaResourcesTable{ - Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), - - //Columns - ID: IDColumn, - MediaID: MediaIDColumn, - Type: TypeColumn, - Source: SourceColumn, - Size: SizeColumn, - Publish: PublishColumn, - CreatedAt: CreatedAtColumn, - UpdatedAt: UpdatedAtColumn, - - AllColumns: allColumns, - MutableColumns: mutableColumns, - } -} diff --git a/backend/database/models/qvyun/public/table/medias.go b/backend/database/models/qvyun/public/table/medias.go index 98af271..5dd9881 100644 --- a/backend/database/models/qvyun/public/table/medias.go +++ b/backend/database/models/qvyun/public/table/medias.go @@ -25,6 +25,7 @@ type mediasTable struct { Price postgres.ColumnInteger Discount postgres.ColumnInteger Publish postgres.ColumnBool + Resources postgres.ColumnString CreatedAt postgres.ColumnTimestamp UpdatedAt postgres.ColumnTimestamp @@ -75,10 +76,11 @@ func newMediasTableImpl(schemaName, tableName, alias string) mediasTable { PriceColumn = postgres.IntegerColumn("price") DiscountColumn = postgres.IntegerColumn("discount") PublishColumn = postgres.BoolColumn("publish") + ResourcesColumn = postgres.StringColumn("resources") CreatedAtColumn = postgres.TimestampColumn("created_at") UpdatedAtColumn = postgres.TimestampColumn("updated_at") - allColumns = postgres.ColumnList{IDColumn, UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn} - mutableColumns = postgres.ColumnList{UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn} + allColumns = postgres.ColumnList{IDColumn, UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, ResourcesColumn, CreatedAtColumn, UpdatedAtColumn} + mutableColumns = postgres.ColumnList{UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, ResourcesColumn, CreatedAtColumn, UpdatedAtColumn} ) return mediasTable{ @@ -93,6 +95,7 @@ func newMediasTableImpl(schemaName, tableName, alias string) mediasTable { Price: PriceColumn, Discount: DiscountColumn, Publish: PublishColumn, + Resources: ResourcesColumn, CreatedAt: CreatedAtColumn, UpdatedAt: UpdatedAtColumn, diff --git a/backend/database/models/qvyun/public/table/table_use_schema.go b/backend/database/models/qvyun/public/table/table_use_schema.go index 5d4655d..1115a31 100644 --- a/backend/database/models/qvyun/public/table/table_use_schema.go +++ b/backend/database/models/qvyun/public/table/table_use_schema.go @@ -10,7 +10,6 @@ package table // UseSchema sets a new schema name for all generated table SQL builder types. It is recommended to invoke // this method only once at the beginning of the program. func UseSchema(schema string) { - MediaResources = MediaResources.FromSchema(schema) Medias = Medias.FromSchema(schema) Migrations = Migrations.FromSchema(schema) TenantUserBalances = TenantUserBalances.FromSchema(schema) diff --git a/backend/modules/medias/controller.go b/backend/modules/medias/controller.go index d1fcd14..5c87e1d 100644 --- a/backend/modules/medias/controller.go +++ b/backend/modules/medias/controller.go @@ -44,14 +44,9 @@ func (c *Controller) Show(ctx fiber.Ctx) error { // Audio func (c *Controller) Video(ctx fiber.Ctx) error { - mediaId := ToInt64(ctx.Params("media")) - tenantId := ToInt64(ctx.Locals("tenantId")) - userId := ToInt64(ctx.Locals("userId")) + // mediaId := ToInt64(ctx.Params("media")) + // tenantId := ToInt64(ctx.Locals("tenantId")) + // userId := ToInt64(ctx.Locals("userId")) - item, err := c.svc.GetVideo(ctx.Context(), tenantId, userId, mediaId) - if err != nil { - return ctx.Status(fiber.StatusInternalServerError).JSON(errorx.InternalError) - } - - return ctx.JSON(item) + return ctx.JSON(nil) } diff --git a/backend/modules/medias/dto.go b/backend/modules/medias/dto.go index b51f13f..37f16cc 100644 --- a/backend/modules/medias/dto.go +++ b/backend/modules/medias/dto.go @@ -13,6 +13,5 @@ type ListFilter struct { type ListItem struct { model.Medias - Bought bool `json:"bought"` - MediaResources []model.MediaResources `json:"media_resources"` + Bought bool `json:"bought"` } diff --git a/backend/modules/medias/service.go b/backend/modules/medias/service.go index 955f9e0..6d61132 100644 --- a/backend/modules/medias/service.go +++ b/backend/modules/medias/service.go @@ -3,12 +3,15 @@ package medias import ( "context" "database/sql" + "path/filepath" - "backend/database/models/qvyun/public/model" "backend/database/models/qvyun/public/table" + "backend/pkg/path" "backend/pkg/pg" + "backend/providers/storage" . "github.com/go-jet/jet/v2/postgres" + "github.com/google/uuid" "github.com/pkg/errors" "github.com/samber/lo" "github.com/sirupsen/logrus" @@ -16,8 +19,9 @@ import ( // @provider:except type Service struct { - db *sql.DB - log *logrus.Entry `inject:"false"` + db *sql.DB + storageConfig *storage.Config + log *logrus.Entry `inject:"false"` } func (svc *Service) Prepare() error { @@ -42,26 +46,7 @@ func (svc *Service) GetByID(ctx context.Context, tenantId, userId, id int64) (*L return nil, errors.Wrap(err, "query media by id") } - tblResource := table.MediaResources - stmtResource := tblResource. - SELECT( - tblResource.MediaID, - tblResource.Type, - tblResource.Size, - ). - WHERE(tblResource.MediaID.EQ(Int(id))) - log.Debug(stmtResource.DebugSql()) - - var resources []model.MediaResources - if err := stmt.QueryContext(ctx, svc.db, &resources); err != nil { - return nil, errors.Wrap(err, "query media resources") - } - - if len(resources) == 0 { - return &media, nil - } - - media.MediaResources = resources + // todo: resources var err error media.Bought, err = svc.HasUserBought(ctx, tenantId, userId, media.ID) @@ -72,55 +57,6 @@ func (svc *Service) GetByID(ctx context.Context, tenantId, userId, id int64) (*L return &media, nil } -// Decorate List Resources -func (svc *Service) DecorateListResources(ctx context.Context, tenantId, userId int64, items []ListItem) ([]ListItem, error) { - log := svc.log.WithField("method", "DecorateListResources") - - mediaIDs := make([]int64, len(items)) - for i, item := range items { - mediaIDs[i] = item.ID - } - - tbl := table.MediaResources - stmt := tbl. - SELECT( - tbl.MediaID, - tbl.Type, - tbl.Size, - ). - WHERE(tbl.MediaID.IN(lo.Map(mediaIDs, func(item int64, _ int) Expression { - return Int(item) - })...)) - log.Debug(stmt.DebugSql()) - - var resources []model.MediaResources - if err := stmt.QueryContext(ctx, svc.db, &resources); err != nil { - return nil, errors.Wrap(err, "query media resources") - } - - if len(resources) == 0 { - return nil, nil - } - - // group resources by media id - resourcesMap := make(map[int64][]model.MediaResources) - for _, resource := range resources { - if _, ok := resourcesMap[resource.MediaID]; !ok { - resourcesMap[resource.MediaID] = make([]model.MediaResources, 0) - } - resourcesMap[resource.MediaID] = append(resourcesMap[resource.MediaID], resource) - } - - // set resources to items - for i, item := range items { - if resources, ok := resourcesMap[item.ID]; ok { - items[i].MediaResources = resources - } - } - - return items, nil -} - // List func (svc *Service) List(ctx context.Context, tenantId, userId int64, filter *ListFilter) ([]ListItem, error) { log := svc.log.WithField("method", "List") @@ -226,57 +162,76 @@ func (svc *Service) HasUserBought(ctx context.Context, tenantId, userId, mediaId return mediaID > 0, nil } -// GetVideo -func (svc *Service) GetVideo(ctx context.Context, tenantId, userId, mediaId int64) (*pg.MediaSource, error) { - log := svc.log.WithField("method", "GetVideo") +// UnPublishTenantWithNotInUUIDs +func (svc *Service) UnPublishTenantWithNotInUUIDs(ctx context.Context, tenantId int64, uuids []string) error { + log := svc.log.WithField("method", "UnPublishTenantWithNotInUUIDs") - ok, err := svc.HasUserBought(ctx, tenantId, userId, mediaId) - if err != nil { - return nil, errors.Wrap(err, "check user bought") - } - log.Debugf("user bought media: %d of tennatID: %d", mediaId, tenantId) - - source, err := svc.GetResourceOfType(ctx, mediaId, pg.MediaTypeVideo) - if err != nil { - return nil, errors.Wrap(err, "get video resource") - } - - if ok { - return source, nil - } - // cut 1 min video - maxDuration := int64(60) - duration := int64(0) - - for i, item := range source.Items { - duration += item.Duration - if duration >= maxDuration { - source.Items = source.Items[:i] - break - } - } - - return source, nil -} - -// GetResourceOfType -func (svc *Service) GetResourceOfType(ctx context.Context, mediaId int64, resourceType pg.MediaType) (*pg.MediaSource, error) { - log := svc.log.WithField("method", "GetResourceOfType") - - tbl := table.MediaResources + tbl := table.Medias stmt := tbl. - SELECT(tbl.Source). + UPDATE(). + SET( + tbl.Publish.SET(Bool(false)), + ). WHERE( - tbl.MediaID.EQ(Int(mediaId)).AND( - tbl.Type.EQ(String(resourceType.String())), + tbl.TenantID.EQ(Int(tenantId)).AND( + tbl.UUID.NOT_IN(lo.Map(uuids, func(item string, _ int) Expression { + return String(item) + })...), ), ) log.Debug(stmt.DebugSql()) - var source pg.MediaSource - if err := stmt.QueryContext(ctx, svc.db, &source); err != nil { - return nil, errors.Wrap(err, "query media source") + if _, err := stmt.ExecContext(ctx, svc.db); err != nil { + return errors.Wrap(err, "unpublish tenant with not in uuids") } - return &source, nil + return nil +} + +// GetTenantUUIDs +func (svc *Service) GetTenantUUIDs(ctx context.Context, tenantId int64) ([]string, error) { + log := svc.log.WithField("method", "GetTenantUUIDs") + + tbl := table.Medias + stmt := tbl. + SELECT(tbl.UUID). + WHERE(tbl.TenantID.EQ(Int(tenantId))) + log.Debug(stmt.DebugSql()) + + var uuids []string + if err := stmt.QueryContext(ctx, svc.db, &uuids); err != nil { + return nil, errors.Wrap(err, "query tenant uuids") + } + + return uuids, nil +} + +// PublishTenant +func (svc *Service) PublishTenantMedia(ctx context.Context, tenantId int64, uuid uuid.UUID, name string) error { + log := svc.log.WithField("method", "PublishTenant") + + resources := pg.MediaResources{} + if path.DirExists(filepath.Join(svc.storageConfig.Path, uuid.String(), pg.MediaTypeVideo.String())) { + resources = append(resources, pg.MediaTypeVideo) + } + + if path.DirExists(filepath.Join(svc.storageConfig.Path, uuid.String(), pg.MediaTypeAudio.String())) { + resources = append(resources, pg.MediaTypeAudio) + } + + if path.DirExists(filepath.Join(svc.storageConfig.Path, uuid.String(), pg.MediaTypePdf.String())) { + resources = append(resources, pg.MediaTypePdf) + } + + tbl := table.Medias + stmt := tbl. + INSERT(tbl.TenantID, tbl.UUID, tbl.Title, tbl.Resources). + VALUES(Int(tenantId), UUID(uuid), String(name), Json(resources.MustValue())) + log.Debug(stmt.DebugSql()) + + if _, err := stmt.ExecContext(ctx, svc.db); err != nil { + return errors.Wrap(err, "publish tenant") + } + + return nil } diff --git a/backend/modules/medias/service_test.go b/backend/modules/medias/service_test.go index 2d84c49..d08e867 100644 --- a/backend/modules/medias/service_test.go +++ b/backend/modules/medias/service_test.go @@ -8,7 +8,7 @@ import ( "backend/database/models/qvyun/public/table" "backend/fixtures" dbUtil "backend/pkg/db" - "backend/pkg/pg" + "backend/providers/storage" . "github.com/go-jet/jet/v2/postgres" "github.com/google/uuid" @@ -118,59 +118,6 @@ func TestService_List(t *testing.T) { So(err, ShouldBeNil) }) - Convey("create media's resources", func() { - items := []model.MediaResources{ - { - MediaID: 1, - Type: pg.MediaTypeVideo, - Size: 100, - Publish: true, - }, - { - MediaID: 1, - Type: pg.MediaTypeAudio, - Size: 100, - Publish: true, - }, - { - MediaID: 2, - Type: pg.MediaTypeVideo, - Size: 100, - Publish: true, - }, - { - MediaID: 2, - Type: pg.MediaTypeAudio, - Size: 100, - Publish: true, - }, - { - MediaID: 3, - Type: pg.MediaTypeVideo, - Size: 100, - Publish: true, - }, - { - MediaID: 3, - Type: pg.MediaTypeAudio, - Size: 100, - Publish: true, - }, - } - - tbl := table.MediaResources - stmt := tbl.INSERT( - tbl.MediaID, - tbl.Type, - tbl.Size, - tbl.Publish, - ).MODELS(items) - t.Log(stmt.DebugSql()) - - _, err := stmt.Exec(db) - So(err, ShouldBeNil) - }) - Convey("get list", func() { svc := &Service{db: db} So(svc.Prepare(), ShouldBeNil) @@ -213,61 +160,50 @@ func TestService_List1(t *testing.T) { }) } -func TestService_DecorateListResources(t *testing.T) { - Convey("TestService_DecorateListResources", t, func() { +func TestService_PublishTenant(t *testing.T) { + Convey("TestService_PublishTenant", t, func() { db, err := fixtures.GetDB() So(err, ShouldBeNil) - defer db.Close() Convey("truncate all tables", func() { - So(dbUtil.TruncateAllTables(context.TODO(), db, "medias", "media_resources"), ShouldBeNil) + So(dbUtil.TruncateAllTables(context.TODO(), db, "medias"), ShouldBeNil) }) - Convey("create media's resources", func() { - items := []model.MediaResources{ - { - MediaID: 1, - Type: pg.MediaTypeVideo, - Size: 100, - Publish: true, - }, - { - MediaID: 2, - Type: pg.MediaTypeAudio, - Size: 100, - Publish: true, - }, + u1, err := uuid.Parse("6c63c4d8-b2cb-4588-8dd3-9a2276918d17") + So(err, ShouldBeNil) + + u2, err := uuid.Parse("8c183427-02b1-4426-ad65-18c6e7735072") + So(err, ShouldBeNil) + + u3, err := uuid.Parse("24aa56a1-a85b-4a03-9a1b-c39a36103ddf") + So(err, ShouldBeNil) + + Convey("insert some data", func() { + items := []model.Medias{ + {UUID: u1, TenantID: 1, Title: "title1", Description: "hello", Price: 100, Publish: true}, + {UUID: u2, TenantID: 1, Title: "title2", Description: "hello", Price: 100, Publish: true}, + {UUID: u3, TenantID: 1, Title: "title3", Description: "hello", Price: 100, Publish: true}, } - tbl := table.MediaResources - stmt := tbl.INSERT( - tbl.MediaID, - tbl.Type, - tbl.Size, - tbl.Publish, - ).MODELS(items) - t.Log(stmt.DebugSql()) + Convey("publish tenant", func() { + svc := &Service{ + db: db, + storageConfig: &storage.Config{ + Path: "/projects/mp-qvyun/backend/fixtures/medias", + }, + } + So(svc.Prepare(), ShouldBeNil) - _, err := stmt.Exec(db) - So(err, ShouldBeNil) - }) + err := svc.PublishTenantMedia(context.TODO(), 1, items[0].UUID, items[0].Title) + So(err, ShouldBeNil) - Convey("decorate list resources", func() { - items := []ListItem{ - {Medias: model.Medias{ID: 1}}, - {Medias: model.Medias{ID: 2}}, - } + err = svc.PublishTenantMedia(context.TODO(), 1, items[1].UUID, items[1].Title) + So(err, ShouldBeNil) - svc := &Service{db: db} - So(svc.Prepare(), ShouldBeNil) - - items, err := svc.DecorateListResources(context.TODO(), 1, 1, items) - So(err, ShouldBeNil) - - for _, item := range items { - So(item.MediaResources, ShouldHaveLength, 1) - } + err = svc.PublishTenantMedia(context.TODO(), 1, items[2].UUID, items[2].Title) + So(err, ShouldBeNil) + }) }) }) } diff --git a/backend/modules/tasks/store/store_medias.go b/backend/modules/tasks/store/store_medias.go index 84c601f..ff1d3bf 100644 --- a/backend/modules/tasks/store/store_medias.go +++ b/backend/modules/tasks/store/store_medias.go @@ -1,8 +1,14 @@ package store import ( + "context" + + "backend/common/media_store" "backend/modules/medias" + "github.com/google/uuid" + "github.com/pkg/errors" + "github.com/samber/lo" log "github.com/sirupsen/logrus" ) @@ -21,5 +27,44 @@ func (d *StoreMedias) Prepare() error { func (d *StoreMedias) RunE(targetPath string) error { d.log.Infof("Store medias from: %s ", targetPath) + store, err := media_store.NewStore(targetPath) + if err != nil { + return errors.Wrapf(err, "new store: %s", targetPath) + } + + // uuids := lo.FilterMap(store.UUIDs(), func(item string, _ int) (uuid.UUID, bool) { + // u, err := uuid.FromBytes([]byte(item)) + // if err != nil { + // return uuid.Nil, false + // } + // return u, true + // }) + + if err := d.mediasSvc.UnPublishTenantWithNotInUUIDs(context.Background(), 1, store.UUIDs()); err != nil { + return errors.Wrapf(err, "UnPublishTenantWithNotInUUIDs: %+v", store.UUIDs()) + } + + dbUUIDs, err := d.mediasSvc.GetTenantUUIDs(context.Background(), 1) + if err != nil { + return errors.Wrap(err, "GetTenantUUIDs") + } + + for _, item := range store { + if lo.Contains(dbUUIDs, item.UUID) { + continue + } + + u, err := uuid.FromBytes([]byte(item.UUID)) + if err != nil { + return errors.Wrap(err, "uuid from bytes") + } + + if err := d.mediasSvc.PublishTenantMedia(context.Background(), 1, u, item.Name); err != nil { + return errors.Wrapf(err, "PublishTenant: %+v", item) + } + + d.log.Infof("PublishTenant: %+v", item) + } + return nil } diff --git a/backend/pkg/path/fs.go b/backend/pkg/path/fs.go index 13ee15f..9c9db57 100644 --- a/backend/pkg/path/fs.go +++ b/backend/pkg/path/fs.go @@ -27,3 +27,11 @@ func GetSubDirs(root string) ([]string, error) { return paths, nil } + +func DirExists(path string) bool { + st, err := os.Stat(path) + if err != nil { + return false + } + return st.IsDir() +} diff --git a/backend/pkg/pg/media.go b/backend/pkg/pg/media.go index 16cbcb6..7d03fd2 100644 --- a/backend/pkg/pg/media.go +++ b/backend/pkg/pg/media.go @@ -4,6 +4,8 @@ import ( "database/sql/driver" "encoding/json" "errors" + + "github.com/samber/lo" ) // swagger:enum MediaType @@ -14,12 +16,9 @@ import ( // ) type MediaType string -type MediaSource struct { - Duration int64 `json:"duration"` - Items []MediaSourceItem `json:"items"` -} +type MediaResources []MediaType -func (x MediaSource) Scan(value interface{}) (err error) { +func (x MediaResources) Scan(value interface{}) (err error) { switch v := value.(type) { case string: return json.Unmarshal([]byte(v), &x) @@ -31,12 +30,10 @@ func (x MediaSource) Scan(value interface{}) (err error) { return errors.New("Unknown type for ") } -func (x MediaSource) Value() (driver.Value, error) { +func (x MediaResources) Value() (driver.Value, error) { return json.Marshal(x) } -type MediaSourceItem struct { - Source string `json:"source"` - Size int64 `json:"size"` - Duration int64 `json:"duration"` +func (x MediaResources) MustValue() driver.Value { + return lo.Must(json.Marshal(x)) } diff --git a/backend/providers/storage b/backend/providers/storage new file mode 160000 index 0000000..9de1e7b --- /dev/null +++ b/backend/providers/storage @@ -0,0 +1 @@ +Subproject commit 9de1e7b7b0acc99a9833bc289f133d1488ed0730