# Development

## List of Methods

### OnUpdate methods

These functions are triggered during the initialization of the Datamart Function and whenever a new activity, profile update, or computed field modification occurs, updating the `State` accordingly.

{% hint style="warning" %}
These methods must be **commutative** to ensure consistency during initial loading, where event order is not guaranteed. It should always produce the same result, regardless of the sequence in which events are processed.
{% endhint %}

{% hint style="danger" %}
To prevent system overload, the `State` size is restricted to a maximum of **1 MB**. If this limit is exceeded, the update will be discarded and not saved.
{% endhint %}

#### onUpdateActivity

`onUpdateActivity(state: State, userActivity: UserActivity): State`

* **Inputs**:
  * `state`: Current state object.
  * `userActivity`: New user activity data.
* **Outputs**: Updated state object.
* **What It Does**: Updates the state with new user activities and removes outdated activities.
* **Example**:

<pre class="language-jsx"><code class="lang-jsx"><strong>// Trigger by a new activity
</strong><strong>onUpdateActivity(state, userActivity) {
</strong>    // Logic to update state
    return updatedState;
}
</code></pre>

{% hint style="info" %}
The activities or profiles received by the plugin are raw data, so you can't rely on the structure defined in your schema to understand its design. However, you can refer to the structure outlined on the **User Lookup** page.
{% endhint %}

#### onUpdateUserProfile

`onUpdateUserProfile(state: State, userProfile: UserProfile, operation: core.Operation): State`

* **Inputs**:
  * `state`: Current state object.
  * `userProfile`: Updated userProfile data.
  * `operation`: Operation type (enum: UPDATE | DELETE).
* **Outputs**: Updated state object.
* **What It Does**: Handles updates to userProfile.
* **Example**:

```jsx
// Trigger by an update on the UserProfile
onUpdateUserProfile(state, userProfile, operation) {
    // Logic to handle UserProfile updates
    return updatedState;
}
```

#### onUpdateComputedFields

`onUpdateComputedFields(state: State | null): Result`

* **Inputs**: `state`: Current state object or null.
* **Outputs**: Result object.
* **What It Does**: Computes the result from the current state.
* **Example**:

```jsx
// Trigger by the result computation of another computed field
onUpdateComputedFields(state) {
    // Logic to compute result
    return state;
}
```

{% hint style="danger" %}
This method must be implemented, even if it not currently used.

Please return the same state.
{% endhint %}

### buildResult

`buildResult(state: State | null): Result`

* **Inputs**: `state`: Current state object or null.
* **Outputs**: Result object.
* **What It Does**: Computes the result from the current state.
* **Example**:

```jsx
buildResult(state) {
    // Logic to compute result
    return result;
}
```

## Test

Before deploying the plugin, create tests to ensure the function behaves as expected.

Test cases might include:

* Adding new activities, and update profiles and verifying the state is updated correctly. Check that the order we send profile updates and activities has no impact.
* Checking that activities which are no more relevant to compute the result are removed from the state.
* Validating that the correct values are returned in the result.

## Best Practices

* How to decide if we create 1 or several plugin(s)? *(example with 2 scores)*
  * If the required data in the state is the same for both scores → 1 plugin
  * If the required data in the state is different (state is polymorph) → 2 plugins
* Always return the same state in case of error, or null. Otherwise, we delete the state, and so reset the result.
* Maximize the number of scores calculated by a Computed Field Function to optimize performance. Therefore, the same state is used to calculate multiple scores, and we avoid storing the same state multiple times.
* Ensure that the state is designed to store relevant information efficiently
* Ensure that the state is commutative to maintain consistency while building the result.\
  ie. state activities and profiles data updates can happend in any order
* Be sure to have a cleaning rule to update the state base on the defined lookback window for both userProfile and userActivities.
  * In other words, when updating the state, be sure to remove the data that are no more useful to compute the result, in order to limit the state size.
* When editing a live computed field, you must relaunch an Initial Loading through API.
