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:
[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#
[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 aboutDescription#
What does the function answer?#
The full type names of the events the handler cares about — what typeof(TicketArrived).FullName and
Events.Type(e) 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?#
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?#
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?#
A function beside the handler that takes nothing and answers List<string>. Anything else is refused where it is
written, saying what would do:
`[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#
Heard once a watch names it#
A handler of every event that cares only about the types a Watch row names.
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 }); }[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#
- [On] — hear an event, after the commit that raised it — hearing an event, and hearing every one
- Raise(e) — say that something happened — what raising an event costs
- [OncePerDelivery] — a read made once for every event of a delivery — a read made once for every event of a delivery
- [Event] — what happens to a record, declared once —
Events.Type,Events.Catalog