# [Interest] — the events a handler of every event cares about

> `[Interest(nameof(Triggers))]` beside the `[On]` of a handler of EVERY event names a function that answers which event types it cares about now — the ones a rule is on, the ones a subscription takes. An event that only such handlers hear, none of them caring about it, is never written: no outbox row, no delivery, no statement. The answer is kept between requests and dropped the moment a table it read is written, so a rule saved now is heard on the very next event.

<!-- id: function-interest · area: function · stability: preview · html: https://osysharp.com/reference/function/interest/ -->

## Summary        {#summary}
A handler of `Event` hears everything — and so every event it could hear is written and delivered for it, even when
it does nothing with most of them. `[Interest]` says which ones it actually cares about:

```osy syntax
[On] [Interest(nameof(RuleTriggers))]
void RunRules(Event e) { … }

/// The events some rule that is on runs on.
List<string> RuleTriggers() { return Rule.Where(r => !r.Off).Select(r => r.When).ToList(); }
```

An event no handler cares about is dropped before anything is written. With no rules at all, the app pays for its events
exactly what it paid before it had any.

## Signature      {#signature}
```osy syntax
[On]
[Interest(nameof(<Fn>))]       // or [Interest("<Fn>")]
void <Name>(Event e) { … }

List<string> <Fn>() { … }      // beside the handler; takes nothing; the full type names of the events it cares about
```

## Description    {#description}

### What does the function answer?   {#answer}
The full type names of the events the handler cares about — what `typeof(TicketArrived).FullName` and
[`Events.Type(e)`](https://osysharp.com/reference/function/event/) give, and what `Events.Catalog()` lists as `Type`. It is ordinary code: it reads the
handler's own rows (rules, subscriptions), and may ask `Events.Catalog()` to turn names it stores into types.

### When is it asked?   {#when}
At the commit that raised an event, before the outbox is written — but not every time. Its answer is KEPT, for the
database it was read from, until a table it read is written (by anyone, on any node), and never longer than half a
minute. So the first event after a rule is saved reads it again; every other event costs nothing to check. A commit that
itself writes a table the answer read — a rule saved and an event raised in one piece of work — treats the handler as
caring about every event for that commit, since the answer cannot see what has not committed yet.

### What if another handler hears the event anyway?   {#others}
Then the event is written and delivered as always, and a handler of every event that does not care about it is not run
on it — so it does not read its rules for it. A typed handler (`[On] void H(TicketArrived e)`) always hears its event,
and so does a handler of every event with no `[Interest]`.

### What may it name?   {#refusals}
A function beside the handler that takes nothing and answers `List<string>`. Anything else is refused where it is
written, saying what would do:

```text
`[Interest]` on 'Misspelt' names 'Wached', and there is no function of that name beside it — it must take nothing and answer `List<string>`, the events the handler cares about. The functions here that do: `Watched`.
'Typed' hears `LampLit` only, so it is interested in nothing else already — `[Interest]` narrows a handler of EVERY event: `[On] [Interest(nameof(Triggers))] void Typed(Event e)`.
```

## Examples       {#examples}

### Heard once a watch names it   {#example}
A handler of every event that cares only about the types a `Watch` row names.

```osy title="a catch-all that cares about what its rows name" test app=function-interest
entity Lamp {
  [MaxLength(40)] string Name = "";
  security { allow read, create, update when IsAnonymous || IsAuthenticated; }
}

entity Watch {
  [MaxLength(200)] string Type = "";
  security { allow read, create when IsAnonymous || IsAuthenticated; }
}

entity Heard {
  [MaxLength(200)] string Type = "";
  security { allow read, create when IsAnonymous || IsAuthenticated; }
}

[Event] public sealed class LampLit { public Lamp Lamp; }

[On] [Interest(nameof(Watched))]
void Remember(Event e) { new Heard { Type = Events.Type(e) }; }

/// The events some watch names — what Remember cares about.
List<string> Watched() { return Watch.Select(w => w.Type).ToList(); }

void Light(Lamp l) { Raise(new LampLit { Lamp = l }); }
```

```osy title="nothing is heard until a watch names the event" run app=function-interest
[Test]
void A_raise_is_heard_only_once_a_watch_names_it() {
  var lamp = new Lamp { Name = "Porch" };
  Light(lamp);
  Background.Settle();
  Assert.Equal(0, Heard.Count());
  new Watch { Type = typeof(LampLit).FullName };
  Background.Settle();
  Light(lamp);
  Background.Settle();
  Assert.Equal(1, Heard.Count());
}
```

## See also       {#see-also}
- [[On] — hear an event, after the commit that raised it](https://osysharp.com/reference/function/on/) — hearing an event, and hearing every one
- [Raise(e) — say that something happened](https://osysharp.com/reference/function/raise/) — what raising an event costs
- [[OncePerDelivery] — a read made once for every event of a delivery](https://osysharp.com/reference/function/once-per-delivery/) — a read made once for every event of a delivery
- [[Event] — what happens to a record, declared once](https://osysharp.com/reference/function/event/) — `Events.Type`, `Events.Catalog`
