diff --git a/.gitignore b/.gitignore index cb2bf660..6ab23ba1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ /apipark .gitlab-ci.yml /.vscode/ +.vscode/ +.air.toml \ No newline at end of file diff --git a/go.mod b/go.mod index d7878223..a347fe38 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/influxdata/influxdb-client-go/v2 v2.14.0 github.com/nsqio/go-nsq v1.1.0 github.com/ollama/ollama v0.5.8 + github.com/stretchr/testify v1.9.0 github.com/urfave/cli v1.22.16 golang.org/x/crypto v0.31.0 gopkg.in/yaml.v3 v3.0.1 @@ -31,6 +32,7 @@ require ( github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect @@ -59,6 +61,7 @@ require ( github.com/oapi-codegen/runtime v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/redis/go-redis/v9 v9.5.3 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect diff --git a/module/service/dto/input.go b/module/service/dto/input.go index dcea95b4..7569d1b5 100644 --- a/module/service/dto/input.go +++ b/module/service/dto/input.go @@ -23,6 +23,7 @@ type CreateService struct { Model *string `json:"model"` AsApp *bool `json:"as_app"` AsServer *bool `json:"as_server"` + ModelMapping string `json:"model_mapping"` } type EditService struct { @@ -36,6 +37,7 @@ type EditService struct { Model *string `json:"model"` ApprovalType *string `json:"approval_type"` State *string `json:"state"` + ModelMapping string `json:"model_mapping"` } type CreateApp struct { diff --git a/module/service/dto/output.go b/module/service/dto/output.go index ef4e6820..636420f0 100644 --- a/module/service/dto/output.go +++ b/module/service/dto/output.go @@ -104,6 +104,7 @@ type Service struct { AsApp bool `json:"as_app"` ServiceKind string `json:"service_kind"` State string `json:"state"` + ModelMapping string `json:"model_mapping"` } type App struct { @@ -191,16 +192,17 @@ type ServiceDoc struct { } type ExportService struct { - Id string `json:"id"` - Name string `json:"name"` - Prefix string `json:"prefix,omitempty"` - Description string `json:"description"` - Team string `json:"team"` - ServiceType string `json:"service_type"` - Catalogue string `json:"catalogue"` - Tags []string `json:"tags"` - Logo string `json:"logo"` - Doc string `json:"doc"` + Id string `json:"id"` + Name string `json:"name"` + Prefix string `json:"prefix,omitempty"` + Description string `json:"description"` + Team string `json:"team"` + ServiceType string `json:"service_type"` + Catalogue string `json:"catalogue"` + Tags []string `json:"tags"` + Logo string `json:"logo"` + Doc string `json:"doc"` + ModelMapping string `json:"model_mapping"` } type ExportApp struct { diff --git a/module/service/iml.go b/module/service/iml.go index a36197cd..f081fc86 100644 --- a/module/service/iml.go +++ b/module/service/iml.go @@ -19,6 +19,7 @@ import ( "github.com/eolinker/ap-account/service/role" application_authorization "github.com/APIParkLab/APIPark/service/application-authorization" + service_model_mapping "github.com/APIParkLab/APIPark/service/service-model-mapping" api_doc "github.com/APIParkLab/APIPark/service/api-doc" @@ -68,6 +69,8 @@ type imlServiceModule struct { apiService api.IAPIService `autowired:""` apiDocService api_doc.IAPIDocService `autowired:""` transaction store.ITransaction `autowired:""` + + serviceModelMappingService service_model_mapping.IServiceModelMappingService `autowired:""` } func (i *imlServiceModule) ExportAll(ctx context.Context) ([]*service_dto.ExportService, error) { @@ -116,11 +119,9 @@ func (i *imlServiceModule) ExportAll(ctx context.Context) ([]*service_dto.Export items = append(items, info) } return items, nil - } func (i *imlServiceModule) searchMyServices(ctx context.Context, teamId string, keyword string) ([]*service.Service, error) { - userID := utils.UserId(ctx) condition := make(map[string]interface{}) condition["as_server"] = true @@ -140,7 +141,6 @@ func (i *imlServiceModule) searchMyServices(ctx context.Context, teamId string, condition["team"] = teamIds return i.serviceService.Search(ctx, keyword, condition, "create_at desc") } - } func (i *imlServiceModule) SearchMyServices(ctx context.Context, teamId string, keyword string) ([]*service_dto.ServiceItem, error) { @@ -182,7 +182,6 @@ func (i *imlServiceModule) Simple(ctx context.Context) ([]*service_dto.SimpleSer items := make([]*service_dto.SimpleServiceItem, 0, len(services)) for _, p := range services { - items = append(items, &service_dto.SimpleServiceItem{ Id: p.Id, Name: p.Name, @@ -195,14 +194,12 @@ func (i *imlServiceModule) Simple(ctx context.Context) ([]*service_dto.SimpleSer func (i *imlServiceModule) MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error) { services, err := i.searchMyServices(ctx, "", "") - if err != nil { return nil, err } items := make([]*service_dto.SimpleServiceItem, 0, len(services)) for _, p := range services { - items = append(items, &service_dto.SimpleServiceItem{ Id: p.Id, Name: p.Name, @@ -247,6 +244,13 @@ func (i *imlServiceModule) Get(ctx context.Context, id string) (*service_dto.Ser } } + + serviceModelMapping, err := i.serviceModelMappingService.Get(ctx, id) + if err != nil { + return nil, err + } + s.ModelMapping = serviceModelMapping.Content + log.Infof("get service cost %d ms", time.Since(now).Milliseconds()) return s, nil } @@ -318,7 +322,6 @@ func toServiceItem(model *service.Service) *service_dto.ServiceItem { } func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *service_dto.CreateService) (*service_dto.Service, error) { - if input.Id == "" { input.Id = uuid.New().String() } @@ -356,7 +359,6 @@ func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *ser return nil, fmt.Errorf("ai service: model can not be empty") } mo.AdditionalConfig["model"] = *input.Model - } if input.AsApp == nil { // 默认值为false @@ -388,6 +390,14 @@ func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *ser } } } + + err := i.serviceModelMappingService.Save(ctx, &service_model_mapping.Save{ + Sid: input.Id, + Content: input.ModelMapping, + }) + if err != nil { + return err + } return i.serviceService.Create(ctx, mo) }) if err != nil { @@ -410,7 +420,6 @@ func (i *imlServiceModule) Edit(ctx context.Context, id string, input *service_d if input.Model != nil { info.AdditionalConfig["model"] = *input.Model } - } err = i.transaction.Transaction(ctx, func(ctx context.Context) error { serviceType := (*service.ServiceType)(input.ServiceType) @@ -457,9 +466,15 @@ func (i *imlServiceModule) Edit(ctx context.Context, id string, input *service_d } } } + err = i.serviceModelMappingService.Save(ctx, &service_model_mapping.Save{ + Sid: id, + Content: input.ModelMapping, + }) + if err != nil { + return err + } return nil }) - if err != nil { return nil, err } @@ -523,7 +538,6 @@ type imlServiceDocModule struct { func (i *imlServiceDocModule) ServiceDoc(ctx context.Context, pid string) (*serviceDto.ServiceDoc, error) { _, err := i.serviceService.Check(ctx, pid, map[string]bool{"as_server": true}) - if err != nil { return nil, err } @@ -555,7 +569,6 @@ func (i *imlServiceDocModule) ServiceDoc(ctx context.Context, pid string) (*serv func (i *imlServiceDocModule) SaveServiceDoc(ctx context.Context, pid string, input *serviceDto.SaveServiceDoc) error { _, err := i.serviceService.Check(ctx, pid, map[string]bool{"as_server": true}) - if err != nil { return err } @@ -737,7 +750,6 @@ func (i *imlAppModule) Search(ctx context.Context, teamId string, keyword string } func (i *imlAppModule) CreateApp(ctx context.Context, teamID string, input *service_dto.CreateApp) (*service_dto.App, error) { - if input.Id == "" { input.Id = uuid.New().String() } @@ -759,9 +771,7 @@ func (i *imlAppModule) CreateApp(ctx context.Context, teamID string, input *serv } err = i.transaction.Transaction(ctx, func(ctx context.Context) error { - return i.serviceService.Create(ctx, mo) - }) if err != nil { return nil, err @@ -770,7 +780,7 @@ func (i *imlAppModule) CreateApp(ctx context.Context, teamID string, input *serv } func (i *imlAppModule) UpdateApp(ctx context.Context, appId string, input *service_dto.UpdateApp) (*service_dto.App, error) { - //userId := utils.UserId(ctx) + // userId := utils.UserId(ctx) info, err := i.serviceService.Get(ctx, appId) if err != nil { return nil, err @@ -907,7 +917,6 @@ func (i *imlAppModule) MySimpleApps(ctx context.Context, keyword string) ([]*ser } items := make([]*service_dto.SimpleAppItem, 0, len(services)) for _, p := range services { - items = append(items, &service_dto.SimpleAppItem{ Id: p.Id, Name: p.Name, diff --git a/service/service-doc/iml.go b/service/service-doc/iml.go index ddfcf67a..4546af02 100644 --- a/service/service-doc/iml.go +++ b/service/service-doc/iml.go @@ -3,9 +3,10 @@ package service_doc import ( "context" "errors" - "github.com/APIParkLab/APIPark/service/universally/commit" "time" + "github.com/APIParkLab/APIPark/service/universally/commit" + "github.com/eolinker/go-common/utils" "gorm.io/gorm" diff --git a/service/service-doc/service.go b/service/service-doc/service.go index 109bae1f..71ff1cc0 100644 --- a/service/service-doc/service.go +++ b/service/service-doc/service.go @@ -2,9 +2,10 @@ package service_doc import ( "context" - "github.com/APIParkLab/APIPark/service/universally/commit" "reflect" + "github.com/APIParkLab/APIPark/service/universally/commit" + "github.com/eolinker/go-common/autowire" ) diff --git a/service/service-model-mapping/iml.go b/service/service-model-mapping/iml.go new file mode 100644 index 00000000..69b7ed5e --- /dev/null +++ b/service/service-model-mapping/iml.go @@ -0,0 +1,67 @@ +package service_model_mapping + +import ( + "context" + "errors" + "time" + + "github.com/APIParkLab/APIPark/stores/service" + "github.com/eolinker/go-common/utils" + "gorm.io/gorm" +) + +var _ IServiceModelMappingService = (*imlServiceModelMappingService)(nil) + +type imlServiceModelMappingService struct { + store service.IServiceModelMappingStore `autowired:""` +} + +func (i *imlServiceModelMappingService) Get(ctx context.Context, sid string) (*ModelMapping, error) { + entity, err := i.store.First(ctx, map[string]interface{}{"sid": sid}) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return &ModelMapping{ + Sid: sid, + Content: "", + }, nil + } + return nil, err + } + return FromEntity(entity), nil +} + +func FromEntity(e *service.ModelMapping) *ModelMapping { + content := "" + if e.Content != "" { + content = e.Content + } + return &ModelMapping{ + ID: e.Id, + Sid: e.Sid, + Content: content, + CreateAt: e.CreateAt, + UpdateAt: e.UpdateAt, + } +} + +func (i *imlServiceModelMappingService) Save(ctx context.Context, input *Save) error { + info, err := i.store.First(ctx, map[string]interface{}{"sid": input.Sid}) + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + userID := utils.UserId(ctx) + if info != nil { + info.Content = input.Content + info.Updater = userID + info.UpdateAt = time.Now() + return i.store.Save(ctx, info) + } + return i.store.Insert(ctx, &service.ModelMapping{ + Sid: input.Sid, + Content: input.Content, + CreateAt: time.Now(), + UpdateAt: time.Now(), + Creator: userID, + Updater: userID, + }) +} diff --git a/service/service-model-mapping/model.go b/service/service-model-mapping/model.go new file mode 100644 index 00000000..66dec9e4 --- /dev/null +++ b/service/service-model-mapping/model.go @@ -0,0 +1,20 @@ +package service_model_mapping + +import ( + "time" +) + +type ModelMapping struct { + ID int64 `json:"id"` + Sid string `json:"sid"` + Content string `json:"content"` + Creator string `json:"creator"` + Updater string `json:"updater"` + CreateAt time.Time `json:"create_at"` + UpdateAt time.Time `json:"update_at"` +} + +type Save struct { + Sid string `json:"sid" validate:"required"` + Content string `json:"content" validate:"required"` +} diff --git a/service/service-model-mapping/service.go b/service/service-model-mapping/service.go new file mode 100644 index 00000000..533614ce --- /dev/null +++ b/service/service-model-mapping/service.go @@ -0,0 +1,19 @@ +package service_model_mapping + +import ( + "context" + "reflect" + + "github.com/eolinker/go-common/autowire" +) + +type IServiceModelMappingService interface { + Get(ctx context.Context, sid string) (*ModelMapping, error) + Save(ctx context.Context, input *Save) error +} + +func init() { + autowire.Auto[IServiceModelMappingService](func() reflect.Value { + return reflect.ValueOf(new(imlServiceModelMappingService)) + }) +} diff --git a/service/service/iml.go b/service/service/iml.go index 47f015fd..8e42fea6 100644 --- a/service/service/iml.go +++ b/service/service/iml.go @@ -14,9 +14,7 @@ import ( "github.com/APIParkLab/APIPark/stores/service" ) -var ( - _ IServiceService = (*imlServiceService)(nil) -) +var _ IServiceService = (*imlServiceService)(nil) type imlServiceService struct { store service.IServiceStore `autowired:""` @@ -154,9 +152,11 @@ func (i *imlServiceService) OnComplete() { func labelHandler(e *service.Service) []string { return []string{e.Name, e.UUID, e.Description} } + func uniquestHandler(i *Create) []map[string]interface{} { return []map[string]interface{}{{"uuid": i.Id}} } + func createEntityHandler(i *Create) *service.Service { cfg, _ := json.Marshal(i.AdditionalConfig) now := time.Now() diff --git a/service/universally/delete.go b/service/universally/delete.go index 565237a9..2677278e 100644 --- a/service/universally/delete.go +++ b/service/universally/delete.go @@ -4,15 +4,14 @@ import ( "context" "errors" "fmt" + "github.com/eolinker/go-common/auto" "github.com/eolinker/go-common/store" "github.com/eolinker/go-common/utils" "gorm.io/gorm" ) -var ( - _ IServiceDelete = (*imlServiceDelete[any])(nil) -) +var _ IServiceDelete = (*imlServiceDelete[any])(nil) type IServiceDelete interface { Delete(ctx context.Context, uuid string) error @@ -26,10 +25,12 @@ func NewDelete[E any](store store.ISearchStore[E]) IServiceDelete { assert(new(E)) return &imlServiceDelete[E]{store: store} } + func NewSoftDelete[E any](s store.ISearchStore[E]) IServiceDelete { assert(new(E)) return &imlServiceSoftDelete[E]{store: s} } + func (p *imlServiceDelete[E]) Delete(ctx context.Context, uuid string) error { return p.store.Transaction(ctx, func(ctx context.Context) error { o, err := p.store.First(ctx, map[string]interface{}{"uuid": uuid}) @@ -46,7 +47,6 @@ func (p *imlServiceDelete[E]) Delete(ctx context.Context, uuid string) error { } return p.store.SetLabels(ctx, idValue(o)) }) - } type imlServiceSoftDelete[E any] struct { @@ -66,7 +66,5 @@ func (p *imlServiceSoftDelete[E]) Delete(ctx context.Context, uuid string) error auto.Auto("operator", operator, o) return p.store.SoftDelete(ctx, map[string]interface{}{"uuid": uuid}) - }) - } diff --git a/stores/service/model.go b/stores/service/model.go index d0d42d30..3e205ace 100644 --- a/stores/service/model.go +++ b/stores/service/model.go @@ -1,6 +1,8 @@ package service -import "time" +import ( + "time" +) type Service struct { Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"` @@ -27,6 +29,7 @@ type Service struct { func (p *Service) IdValue() int64 { return p.Id } + func (p *Service) TableName() string { return "service" } @@ -87,3 +90,21 @@ func (d *Doc) IdValue() int64 { func (d *Doc) TableName() string { return "server_doc" } + +type ModelMapping struct { + Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:PRIMARY ID;primary_key"` + Sid string `gorm:"size:36;not null;column:sid;comment:service uuid;uniqueIndex:unique_sid;"` + Content string `gorm:"type:text;not null;column:content;comment:mapping json"` + Creator string `gorm:"type:varchar(36);not null;column:creator;comment:creator" aovalue:"creator"` + Updater string `gorm:"type:varchar(36);not null;column:updater;comment:updater" aovalue:"updater"` + CreateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:create_at;comment:create_at"` + UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;column:update_at;comment:update_at"` +} + +func (m *ModelMapping) TableName() string { + return "service_model_mapping" +} + +func (m *ModelMapping) IdValue() int64 { + return m.Id +} diff --git a/stores/service/store.go b/stores/service/store.go index 8c24fc15..702a358c 100644 --- a/stores/service/store.go +++ b/stores/service/store.go @@ -1,10 +1,11 @@ package service import ( + "reflect" + "github.com/eolinker/go-common/autowire" "github.com/eolinker/go-common/store" ) -import "reflect" type IServiceStore interface { store.ISearchStore[Service] @@ -37,6 +38,14 @@ type imlAuthorizationStore struct { store.SearchStore[Authorization] } +type IServiceModelMappingStore interface { + store.ISearchStore[ModelMapping] +} + +type imlServiceModelMappingStore struct { + store.SearchStore[ModelMapping] +} + func init() { autowire.Auto[IServiceStore](func() reflect.Value { return reflect.ValueOf(new(imlServiceStore)) @@ -52,4 +61,7 @@ func init() { return reflect.ValueOf(new(imlServiceDocStore)) }) + autowire.Auto[IServiceModelMappingStore](func() reflect.Value { + return reflect.ValueOf(new(imlServiceModelMappingStore)) + }) }