diff --git a/app/services/ml/create_model_version_service.rb b/app/services/ml/create_model_version_service.rb index ff27e78221f1c5ea488541cbe25fd49ef4e08eaf..e7a592101070c1a5a2f6e8285a692a629f901cc6 100644 --- a/app/services/ml/create_model_version_service.rb +++ b/app/services/ml/create_model_version_service.rb @@ -7,19 +7,38 @@ def initialize(model, params = {}) @version = params[:version] @package = params[:package] @description = params[:description] + @user = params[:user] end def execute - @version ||= Ml::IncrementVersionService.new(@model.latest_version.try(:version)).execute + ApplicationRecord.transaction do + @version ||= Ml::IncrementVersionService.new(@model.latest_version.try(:version)).execute - model_version = Ml::ModelVersion.find_or_create!(@model, @version, @package, @description) + package = @package || find_or_create_package(@model.name, @version) - model_version.candidate = ::Ml::CreateCandidateService.new( - @model.default_experiment, - { model_version: model_version } - ).execute + model_version = Ml::ModelVersion.create!(model: @model, project: @model.project, version: @version, + package: package, description: @description) - model_version + model_version.candidate = ::Ml::CreateCandidateService.new( + @model.default_experiment, + { model_version: model_version } + ).execute + + model_version + end + end + + private + + def find_or_create_package(model_name, model_version) + package_params = { + name: model_name, + version: model_version + } + + ::Packages::MlModel::FindOrCreatePackageService + .new(@model.project, @user, package_params) + .execute end end end diff --git a/spec/services/ml/create_model_version_service_spec.rb b/spec/services/ml/create_model_version_service_spec.rb index ea3e2f654d4a7e36144669c7c2a840284cea25f8..4e71c538f7e11fe10a7e937e16aea668cd0e6c52 100644 --- a/spec/services/ml/create_model_version_service_spec.rb +++ b/spec/services/ml/create_model_version_service_spec.rb @@ -25,4 +25,41 @@ expect(model.reload.latest_version.version).to eq('4.0.0') end end + + context 'when a version is created' do + it 'creates a package' do + expect { service }.to change { Ml::ModelVersion.count }.by(1).and change { + Packages::MlModel::Package.count + }.by(1) + expect(model.reload.latest_version.package.name).to eq(model.name) + expect(model.latest_version.package.version).to eq(model.latest_version.version) + end + end + + context 'when a version is created and the package already exists' do + it 'does not creates a package' do + next_version = Ml::IncrementVersionService.new(model.latest_version.try(:version)).execute + create(:ml_model_package, name: model.name, version: next_version, project: model.project) + + expect { service }.to change { Ml::ModelVersion.count }.by(1).and not_change { + Packages::MlModel::Package.count + } + expect(model.reload.latest_version.package.name).to eq(model.name) + expect(model.latest_version.package.version).to eq(model.latest_version.version) + end + end + + context 'when a version is created and an existing package supplied' do + it 'does not creates a package' do + next_version = Ml::IncrementVersionService.new(model.latest_version.try(:version)).execute + package = create(:ml_model_package, name: model.name, version: next_version, project: model.project) + service = described_class.new(model, { package: package }) + + expect { service.execute }.to change { Ml::ModelVersion.count }.by(1).and not_change { + Packages::MlModel::Package.count + } + expect(model.reload.latest_version.package.name).to eq(model.name) + expect(model.latest_version.package.version).to eq(model.latest_version.version) + end + end end