Skip to content

Backfilling Existing Subscriptions

When updating a product block that already exists in your orchestrator, it could be the case that new attributes are added or removed. When removing resource types from a ProductBlock, the migrate-domain-models command is able to pick up on this change, and generates a migration that removes these resource types from your database completely.

However, when adding a new resource type to a ProductBlock, pre-existing product instances in the subscription database are not backfilled. For this, another SQL transaction must be added to the generated migration file.

Generating a Database Migration

After the new resource type is added to the product block, the generated migration file should already contain at least the following two transactions:

conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('site_contains_optical_equipment', 'Whether a site contains optical equipment') RETURNING resource_types.resource_type_id
"""))

conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_contains_optical_equipment')))
"""))

Note that this will correctly add the new resource type to the database, but is missing a backfill for a default value. In the case of this example, a new resource type site_contains_optical_equipment is added. Assume that all subscriptions that already exist in the database already are sites that contain optical equipment. It would therefore make sense to backfill the value True into all subscriptions that already exist.

Adapting the Generated Database Migration

To implement this backfilling mechanism, only one SQL statement needs to be added to the migration, given below.

conn.execute(sa.text("""
WITH rt_id AS (SELECT resource_type_id FROM resource_types WHERE resource_type = 'site_contains_optical_equipment') INSERT INTO subscription_instance_values (subscription_instance_id, resource_type_id, value) SELECT subscription_instance_id, rt_id.resource_type_id, 'True' FROM rt_id, subscription_instances WHERE product_block_id = (SELECT product_block_id FROM product_blocks WHERE name = 'SiteBlock');
"""))

Adding this statement at the end of the upgrade() method in the generated migration file, will set the value of site_contains_optical_equipment in all existing Site subscriptions to True. A more formatted version of this SQL statement is given here. To adapt this example to your needs, update the resource type name, default value, and name of the product block where this resource type is added.

WITH rt_id AS (
    SELECT
        resource_type_id
    FROM
        resource_types
    WHERE
        -- The name of your new resource type
        resource_type = 'site_contains_optical_equipment'
)
INSERT INTO
    subscription_instance_values (
        subscription_instance_id,
        resource_type_id,
        value
    )
SELECT
    subscription_instance_id,
    rt_id.resource_type_id,
    'True'  -- The new value that is backfilled
FROM
    rt_id,
    subscription_instances
WHERE
    product_block_id = (
        SELECT
            product_block_id
        FROM
            product_blocks
        WHERE
            -- The name of the product block where this value is backfilled
            name = 'SiteBlock'
    );

The downgrade() method of the generated migration does not need any modification to work. It simply removes the resource type from the subscription database altogether.