Execute a mutator

Once you have configured a mutator, you are ready to edit the user data and consents in your store. This can be done by executing the mutator.

How to execute a mutator

There are two ways to execute a mutator:

  • Download and deploy your tenant's code-generated UserClouds SDK, and call the mutator indirectly using its SDK function name
  • Call the ExecuteMutator API

When calling the ExecuteMutator API directly you pass:

  • An array of SelectorValues, which are used to parameterize the mutator's selector to define which users should be edited
  • Optional client context data, which may be referred to by the mutator access policy
  • RowData, a mapping from mutator column name to a ValueAndPurposes record, which captures any requested data or consent changes for that column. ValueAndPurposes contains the following attributes, each of which will be explained more fully in the context of FullUpdates and PartialUpdates below:
    • Value - used for FullUpdates
    • ValueAdditions - used for PartialUpdates
    • ValueDeletions - used for PartialUpdates
    • PurposeAdditions - used for FullUpdates and PartialUpdates
    • PurposeDeletions - used for FullUpdates and PartialUpdates

What happens when you execute a mutator

When you execute a mutator, the following steps happen in sequence:

  1. The mutator validates and normalizes the inbound data for each column associated with the mutator, using the configured data normalizer for that column.
  2. The mutator finds candidate user records to update based on the mutator selector clause and the passed in SelectorValues.
  3. Two access policies are applied to each selected user record: the global baseline policy for mutators (learn more here) and the mutator's own access policy composition. This step may involve evaluating the provided client context or any user-specific data already present in the User Store to determine if the write operation is permitted for each selector user record.
  4. If the access policy passes for the user, the mutator reconciles the normalized changes for each mutator column against existing user data, utilizing full mutation or partial mutation rules according to the column's configuration (see below for more detail).
  5. Any resulting changes to the user's data and associated consents are saved to the store.

FullUpdate vs PartialUpdate Columns

UserClouds columns may either be “single value” or “array” columns (supporting multiple values for each user). Column values are updated using one of two paradigms:

  • FullUpdates (default setting): the Value attribute specifies a comprehensive set of new values for the column. Existing values that are not included in the Value attribute are removed. This is always the approach used for single value columns, and is the default approach for array columns.
  • PartialUpdates: any specified value changes are treated as incremental, leaving any other values for the user and column unchanged. This can be enabled for array columns that are configured to have unique values or to have unique value IDs.

The choice to use full updates or partial updates must be made at column creation time.


Full Update Columns

If PartialUpdates are disabled for the Column, the Value attribute specifies a comprehensive set of new values for the column. Existing values that are not included in the Value attribute are removed. All values in the Value attribute will be associated with an updated set of consents, which is computed by (1) starting with the existing consents, (2) adding any consents specified in PurposeAdditions, and (3) removing any consents specified in PurposeDeletions. If any values or consents are removed, the corresponding value-consent pair will be retained in a soft-deleted state for the retention duration of that consent on that column (assuming the duration is non-zero).

NOTE: An important implication is that full update column values always share the same set of consents for a given user.

SPECIAL CASES: Value can be set to one of three special sentinel values in a mutation request for full update columns. If MutatorColumnCurrentValue is used, it means that any PurposeAdditions or PurposeDeletions should be applied to all current values for the column. If MutatorColumnDefaultValue is used, it means that the value for the column should be set to the configured default value for the column. And if nil is used, it means that all current values for the column should be removed.

Example Update Sequence

For this example, assume we are updating a column configured to be an array of strings, with PartialUpdates disabled.

  1. insert value with operational and marketing consents

    ValueAndPurposes = {  
    	Value: [“foo”, “bar”],  
    	PurposeAdditions: [“operational”, “marketing”],  
    }
    
    Resulting value = \[  
    	("foo", ["operational", "marketing"]),  
    	("bar", ["operational", "marketing"]),  
    ]
    
  2. add data_science and remove marketing consents for existing values

    ValueAndPurposes = {  
    	Value: MutatorColumnCurrentValue,  
    	PurposeAdditions: [“data_science”],  
    	PurposeDeletions: [“marketing”],  
    }
    
    Resulting value = \[  
    	("foo", ["operational", "data_science"]),  
    	("bar", ["operational", "data_science"]),  
    ]
    
  3. update values, adding fraud_prevention consent

    ValueAndPurposes = {  
    	Value: [“bar”, “baz”],  
    	PurposeAdditions: [“fraud_prevention”],  
    }
    
    Resulting value = \[  
    	("bar", ["operational", “data_science”, "fraud_prevention"]),  
    	("baz", ["operational", “data_science”, "fraud_prevention"]),  
    ]
    
  4. delete all values

    ValueAndPurposes = {  
    	Value: nil,  
    }
    
    Resulting value = \[]
    

Partial Update Columns

If PartialUpdates is enabled for the column, any specified changes are treated as incremental, leaving any other values for the user and column unchanged. Value changes are expressed via the ValueAdditions and ValueDeletions attributes of ValueAndPurposes for the column. ValueAdditions includes the set of values to add for the user column, while ValueDeletions contains the set of values to remove for the column. Any consents specified in the PurposeAdditions attribute will be added to values represented by the ValueAdditions attribute, and any consents specified in the PurposeDeletions attribute will be removed for values represented by the ValueDeletions attribute. As with full updates, any removed values and associated consents will be retained in a soft-deleted state if configured to do so.

NOTE: Any existing values and associated consents that are not specified to be added or removed by ValueAndPurposes for a partial update column will remain unchanged. As such, different values may have different associated consents for a partial update column.

SPECIAL CASES:

  1. ValueAdditions and ValueDeletions can be set to the sentinel value MutatorColumnCurrentValue.
    1. If ValueAdditions is set to this value, consents specified in PurposeAdditions will be added to all current values.
    2. If ValueDeletions is set to this value, consents specified in PurposeDeletions will be removed from all current values.
  2. If ValueAdditions or ValueDeletions is set to nil, no consent additions or consent deletions will be made.
  3. If ValueDeletions is set to a non-nil value, but PurposeDeletions is empty, all values specified in ValueDeletions will have all current consents removed for each value.

Example Update Sequence

For this example, assume we are updating a column configured to be an array of unique strings, with partial updates enabled.

  1. insert value with operation and marketing consents

    ValueAndPurposes = {  
    	ValueAdditions: [“foo”, “bar”],  
    	PurposeAdditions: [“operational”, “marketing”],  
    }
    
    Resulting value = \[  
    	("foo", ["operational", "marketing"]),  
    	("bar", ["operational", "marketing"]),  
    ]
    
  2. add data_science and remove marketing consents for existing values

    ValueAndPurposes = {  
    	ValueAdditions: MutatorColumnCurrentValue,  
    	PurposeAdditions: [“data_science”],  
    	ValueDeletions: MutatorColumnCurrentValue,  
    	PurposeDeletions: [“marketing”],  
    }
    
    Resulting value = \[  
    	("foo", ["operational", "data_science"]),  
    	("bar", ["operational", "data_science"]),  
    ]
    
  3. add value with fraud_prevention consent, remove value with data_science consent

    ValueAndPurposes = {  
    	ValueAdditions: [“baz”],  
    	PurposeAdditions: [“fraud_prevention”],  
    	ValueDeletions: [“foo”],  
    	PurposeDeletions: [“data_science”],  
    }
    
    Resulting value = \[  
    	("foo", ["operational"]),  
    	("bar", ["operational", "data_science"]),  
    	("baz", ["fraud_prevention"]),  
    ]
    
  4. delete all values

    ValueAndPurposes = {  
    	ValueDeletions: MutatorColumnCurrentValue,  
    }
    
    Resulting value = \[]