# Trigger design principles

**URL:** <https://forum.canton.network/t/trigger-design-principles/933>\
**Category:** App Development\
**Created:** [July 28, 2020, 2:18pm UTC](https://forum.canton.network/t/trigger-design-principles/933 "2020-07-28T14:18:31Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Leonid\_Rozenberg](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/leonid_rozenberg/32/48_2.png) [@Leonid\_Rozenberg](https://forum.canton.network/u/Leonid_Rozenberg)\
**Post date:** [July 28, 2020, 2:18pm UTC](https://forum.canton.network/t/trigger-design-principles/933/1 "2020-07-28T14:18:31Z")

</div>

[Triggers](https://docs.daml.com/triggers/index.html) are a new but powerful mechanism in DAML. As such, I think that good design principles have not yet been discussed. I want to start this question, to gather feedback, further the discussion and identify gaps in my (and our) knowledge about them.

In my most recent work, I am using triggers to provide a [Materialized view](https://en.wikipedia.org/wiki/Materialized_view) for a user of data that is logically spread out among several other contracts that describe that user’s interaction and obligation with other users. A technique that I have found particular clear is to keep a `ContractId` to that user’s `Role` contract within the state of the trigger, and then react to the creation of new contracts in the ACS that have not been processed. The set of contracts that have been processed (their existence acknowledged in that users view) is also maintained in the trigger state. Imagine the `CopyTrigger` example but 10x crazier.

Some specific questions:

1. In this design the existence of the `Role` contract is a prerequisite for the trigger. I currently `error` during `initialize` instead of keeping an Optional to the role ContractId. Is this the recommended way to signal failure?
2. Instead of keeping that ContractId in state, I could `getContract`s it from the `ACS` every time. Is `getContract` “fast”, should I care?
3. The separation of `updateState` and `rule` is a bit awkward. AFAIU, I can’t change state within the rule ( `... -> TriggerA ()`) . Is the right approach to react to `Message`'s sent to `updateState` as a result of the `Create`s and `Exercise`s that one emits within the rule?

Thanks

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [July 28, 2020, 7:41pm UTC](https://forum.canton.network/t/trigger-design-principles/933/2 "2020-07-28T19:41:26Z")

</div>

1. I would generally recommend to write your triggers such that they gracefully handle this case and don’t crash. This might not be super important in a production setup where this contract will be created once and you never have to worry about it existing afterwards but at least for development it makes things a bit easier since you don’t have to worry about the order in which you spin things up.
2. `getContracts` currently does a linear search through the ACS so it depends on how many contracts are active of the templates you have registered. This will change as soon as DAML-LF stabilizes support for the generic Map type. At this point, this becomes a single lookup. I wouldn’t worry too much about the performance here. If you are doing some expensive computation on the contracts this might be worth caching but I wouldn’t bother caching `getContracts`.
3. I don’t think the API here is quite final so some things might still be changing as more people start using the custom state but here’s the current thinking: Triggers are state-based not event-based. This is crucial imho. Event-based automation is super fragile if it gets shut down and started up again (either you react to old events which probably don’t make sense anymore or you ignore those events which is also bad). The trigger library tracks some state for you (the ACS) and you can track more state if you want but the API deliberately separates tracking state from the state-based rule.

---

<div class="post-metadata">

**Author:** ![Leonid\_Rozenberg](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/leonid_rozenberg/32/48_2.png) [@Leonid\_Rozenberg](https://forum.canton.network/u/Leonid_Rozenberg)\
**Post date:** [July 29, 2020, 2:48pm UTC](https://forum.canton.network/t/trigger-design-principles/933/3 "2020-07-29T14:48:25Z")

</div>

1. Agreed.
2. Noted. It does seem a little weird to `getContract`s for the same Role contract repeatedly. Though, you’re guarding against it being archived. I am starting to think that this weirdness, is really a reflection of the dependence on the `Role` contract and not Triggers.
3. You make some interesting points. While I agree that event based automation can be difficult, it is the dual of the state based one, I don’t think that you get away from the complexity. In particular, can you clarify what you mean by:

> [@cocreature](#):
>
> Triggers are state-based not event-based.

what would “trigger” a `Trigger` if not an event? The way that I understand this, is that the `rule` is state based, but the `updateState` is event based, because the former does not get a `Message` and the latter does. My concern, is that this approach hinders the react to events model. I have incomplete thoughts on this at the moment, so I’ll do some more thinking. My point of comparison is the `DAZL` model, where reacting to events is _really_ easy (ex. [DABL Chess operator bot](https://github.com/digital-asset/dablchess/blob/8d495846b312a97e51da846acbcb3836c360ed00/operator_bot/bot/operator_bot.py#L42)), such as progressing along designed state transitions.

---

<div class="post-metadata">

**Author:** ![georg](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/georg/32/368_2.png) [@georg](https://forum.canton.network/u/georg)\
**Post date:** [July 29, 2020, 3:49pm UTC](https://forum.canton.network/t/trigger-design-principles/933/4 "2020-07-29T15:49:03Z")

</div>

2c on this: I also have the impression that there are cases where you don’t actually need state at all, and event-based is just fine. But likewise I haven’t formed a clear opinion yet, too little data - it just feels like the current trigger implementation is fairly complex / heavyweight to do simple things.

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [July 29, 2020, 3:54pm UTC](https://forum.canton.network/t/trigger-design-principles/933/5 "2020-07-29T15:54:17Z")

</div>

> [@Leonid\_Rozenberg](#):
>
> what would “trigger” a `Trigger` if not an event

Triggers should be written under the assumption that the rule of your trigger can be triggered at any time. The fact that it’s only triggered at events is more of an optimization since only then the state can change so triggering your trigger at another time is useless.

I do see your point that reacting to events is difficult but that is intentional. While there might be cases where the issues of an event-based implementation are fine, this is not what triggers are designed for.

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [July 29, 2020, 4:37pm UTC](https://forum.canton.network/t/trigger-design-principles/933/6 "2020-07-29T16:37:23Z")

</div>

@georg, interesting, maybe we should consider having something like `Daml.Trigger.State` and `Daml.Trigger.Event`.

---

<div class="post-metadata">

**Author:** ![Gary\_Verhaegen](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/gary_verhaegen/32/81_2.png) [@Gary\_Verhaegen](https://forum.canton.network/u/Gary_Verhaegen)\
**Post date:** [August 6, 2020, 11:23am UTC](https://forum.canton.network/t/trigger-design-principles/933/7 "2020-08-06T11:23:35Z")

</div>

Hi @cocreature,

Sort of a small aside here: this kind of design intent behind a system is _really useful_ for users in my opinion, but is often left out of documentation. Based on this thread, I think it would be very useful if you could add a paragraph or two at the top of [the DAML Trigger docs page](https://docs.daml.com/triggers/index.html) to elaborate on these design principles behind the Trigger API.

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [August 6, 2020, 11:25am UTC](https://forum.canton.network/t/trigger-design-principles/933/8 "2020-08-06T11:25:04Z")

</div>

Good point, I’ll try to add a paragraph.

---

<div class="post-metadata">

**Author:** ![Leonid\_Rozenberg](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/leonid_rozenberg/32/48_2.png) [@Leonid\_Rozenberg](https://forum.canton.network/u/Leonid_Rozenberg)\
**Post date:** [April 26, 2021, 2:14pm UTC](https://forum.canton.network/t/trigger-design-principles/933/9 "2021-04-26T14:14:35Z")

</div>

> [@cocreature](#):
>
> I do see your point that reacting to events is difficult but that is intentional. While there might be cases where the issues of an event-based implementation are fine, this is not what triggers are designed for.

@cocreature I’d like to revisit this point. How should we write trigger code that is state based and not event-based? If we have a large ACS, and the trigger keeps firing because of changes to the ledger (avoiding the word “event”), we have to keep scanning the ACS to determine what’s different? Doesn’t that seem wasteful?
