Add bulk create or update service for add-on purchases for SaaS

What does this MR do and why?

The code changes introduce a new service that allows users to bulk provision multiple add-ons for their GitLab subscriptions. Previously, only one add-on could be provision at a time. The introduced service will later allow the bulk provision as planned here.

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Database queries

SQL database queries from specific, more extensive spec !164589 (diffs)

# TRANSACTION START


D, [2024-09-04T13:13:24.153757 #155170] DEBUG -- :   TRANSACTION (0.3ms)  SAVEPOINT active_record_2 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/lib/gitlab/database/schema_cache_with_renamed_table_legacy.rb:27:in `columns'*/
D, [2024-09-04T13:13:24.154045 #155170] DEBUG -- :   ↳ lib/gitlab/database/schema_cache_with_renamed_table_legacy.rb:27:in `columns'


# DUO PRO


D, [2024-09-04T13:13:24.157100 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Pluck (0.3ms)  SELECT "subscription_add_ons"."id" FROM "subscription_add_ons" WHERE "subscription_add_ons"."name" = 1 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on_purchase.rb:33:in `block in <class:AddOnPurchase>'*/
D, [2024-09-04T13:13:24.157323 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on_purchase.rb:33:in `block in <class:AddOnPurchase>'

D, [2024-09-04T13:13:24.158347 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Pluck (0.3ms)  SELECT "subscription_add_ons"."id" FROM "subscription_add_ons" WHERE "subscription_add_ons"."name" = 3 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on_purchase.rb:35:in `block in <class:AddOnPurchase>'*/
D, [2024-09-04T13:13:24.158575 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on_purchase.rb:35:in `block in <class:AddOnPurchase>'

D, [2024-09-04T13:13:24.160666 #155170] DEBUG -- :   GitlabSubscriptions::AddOnPurchase Load (0.3ms)  SELECT "subscription_add_on_purchases".* FROM "subscription_add_on_purchases" WHERE "subscription_add_on_purchases"."namespace_id" = 176 AND "subscription_add_on_purchases"."subscription_add_on_id" IS NULL ORDER BY "subscription_add_on_purchases"."id" ASC LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/duo.rb:6:in `any_add_on_purchase_for_namespace'*/
D, [2024-09-04T13:13:24.160900 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/duo.rb:6:in `any_add_on_purchase_for_namespace'



D, [2024-09-04T13:13:24.161955 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Load (0.3ms)  SELECT "subscription_add_ons".* FROM "subscription_add_ons" WHERE "subscription_add_ons"."name" = 1 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'*/
D, [2024-09-04T13:13:24.162189 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'

D, [2024-09-04T13:13:24.165391 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Exists? (0.3ms)  SELECT 1 AS one FROM "subscription_add_ons" WHERE "subscription_add_ons"."name" = 1 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'*/
D, [2024-09-04T13:13:24.165729 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'

D, [2024-09-04T13:13:24.167121 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Create (0.5ms)  INSERT INTO "subscription_add_ons" ("created_at", "updated_at", "name", "description") VALUES ('2024-09-04 11:13:24.166080', '2024-09-04 11:13:24.166080', 1, 'Add-on for GitLab Duo Pro.') RETURNING "id" /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'*/
D, [2024-09-04T13:13:24.167435 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'



D, [2024-09-04T13:13:24.171918 #155170] DEBUG -- :   GitlabSubscriptions::AddOnPurchase Exists? (0.5ms)  SELECT 1 AS one FROM "subscription_add_on_purchases" WHERE "subscription_add_on_purchases"."subscription_add_on_id" = 31 AND "subscription_add_on_purchases"."namespace_id" = 176 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'*/
D, [2024-09-04T13:13:24.194635 #155170] DEBUG -- :   ↳ ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'

D, [2024-09-04T13:13:24.196917 #155170] DEBUG -- :   GitlabSubscriptions::AddOnPurchase Create (0.7ms)  INSERT INTO "subscription_add_on_purchases" ("created_at", "updated_at", "subscription_add_on_id", "namespace_id", "quantity", "expires_on", "purchase_xid", "started_at", "organization_id") VALUES ('2024-09-04 11:13:24.195431', '2024-09-04 11:13:24.195431', 31, 176, 1, '2025-09-04', 'S-A00000001', '2024-09-04', 1) RETURNING "id" /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'*/
D, [2024-09-04T13:13:24.197240 #155170] DEBUG -- :   ↳ ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'


# PRODUCT ANALYTICS


D, [2024-09-04T13:13:24.200782 #155170] DEBUG -- :   GitlabSubscriptions::AddOnPurchase Load (0.4ms)  SELECT "subscription_add_on_purchases".* FROM "subscription_add_on_purchases" INNER JOIN "subscription_add_ons" "add_on" ON "add_on"."id" = "subscription_add_on_purchases"."subscription_add_on_id" WHERE "subscription_add_on_purchases"."namespace_id" = 176 AND "add_on"."name" = 2 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/services/gitlab_subscriptions/add_on_purchases/gitlab_com/provision_service.rb:83:in `add_on_purchase'*/
D, [2024-09-04T13:13:24.201016 #155170] DEBUG -- :   ↳ ee/app/services/gitlab_subscriptions/add_on_purchases/gitlab_com/provision_service.rb:83:in `add_on_purchase'



D, [2024-09-04T13:13:24.202153 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Load (0.3ms)  SELECT "subscription_add_ons".* FROM "subscription_add_ons" WHERE "subscription_add_ons"."name" = 2 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'*/
D, [2024-09-04T13:13:24.202383 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'

D, [2024-09-04T13:13:24.204078 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Exists? (0.1ms)  SELECT 1 AS one FROM "subscription_add_ons" WHERE "subscription_add_ons"."name" = 2 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'*/
D, [2024-09-04T13:13:24.204421 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'

D, [2024-09-04T13:13:24.205447 #155170] DEBUG -- :   GitlabSubscriptions::AddOn Create (0.2ms)  INSERT INTO "subscription_add_ons" ("created_at", "updated_at", "name", "description") VALUES ('2024-09-04 11:13:24.204743', '2024-09-04 11:13:24.204743', 2, 'Add-on for product analytics. Quantity suggests multiple of available stored event.') RETURNING "id" /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'*/
D, [2024-09-04T13:13:24.205766 #155170] DEBUG -- :   ↳ ee/app/models/gitlab_subscriptions/add_on.rb:35:in `find_or_create_by_name'



D, [2024-09-04T13:13:24.207800 #155170] DEBUG -- :   GitlabSubscriptions::AddOnPurchase Exists? (0.3ms)  SELECT 1 AS one FROM "subscription_add_on_purchases" WHERE "subscription_add_on_purchases"."subscription_add_on_id" = 32 AND "subscription_add_on_purchases"."namespace_id" = 176 LIMIT 1 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'*/
D, [2024-09-04T13:13:24.208113 #155170] DEBUG -- :   ↳ ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'

D, [2024-09-04T13:13:24.209277 #155170] DEBUG -- :   GitlabSubscriptions::AddOnPurchase Create (0.3ms)  INSERT INTO "subscription_add_on_purchases" ("created_at", "updated_at", "subscription_add_on_id", "namespace_id", "quantity", "expires_on", "purchase_xid", "started_at", "organization_id") VALUES ('2024-09-04 11:13:24.208511', '2024-09-04 11:13:24.208511', 32, 176, 1, '2025-09-04', 'S-A00000001', '2024-09-04', 1) RETURNING "id" /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'*/
D, [2024-09-04T13:13:24.209575 #155170] DEBUG -- :   ↳ ee/app/services/gitlab_subscriptions/add_on_purchases/create_service.rb:12:in `execute'


# TRANSACTION END


D, [2024-09-04T13:13:24.210292 #155170] DEBUG -- :   TRANSACTION (0.2ms)  RELEASE SAVEPOINT active_record_2 /*application:test,correlation_id:066e6023cc9a1011e8d1cfa7a66a9e8f,db_config_name:main,line:/lib/gitlab/database.rb:369:in `block in transaction'*/
D, [2024-09-04T13:13:24.211105 #155170] DEBUG -- :   ↳ lib/gitlab/database.rb:369:in `block in transaction'

How to set up and validate locally

Green pipeline should be sufficient.

Resolves #482117

Edited by Lukas Wanko

Merge request reports

Loading