# Raise(e) — say that something happened

> `Raise(e)` says that the event `e` happened — an instance of a class marked `[Event]`. It is written in the same commit as the work around it, and every `[On]` handler of its class hears it after that commit. An event no handler hears costs nothing: no row, no statement.

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

## Summary        {#summary}
`Raise(new QuoteAccepted { Quote = q })` says the event happened. It returns at once; nothing hears it yet. When the
work around it commits, every [[function-on|`[On]`]] handler of `QuoteAccepted` — in the app, or in any package that sees
the class — runs, after that commit.

```osy syntax
public void AcceptQuote(Quote q) {
  q.Status = QuoteStatus.Accepted;
  Raise(new QuoteAccepted { Quote = q });      // heard once this work has committed
}
```

`Raise` is the [[function-event|`[Event]`]]'s. `Workflow.Raise` and `<Workflow>.Raise<Event>` are a different thing:
they move ONE workflow run along ([Raising a workflow event](https://osysharp.com/reference/workflow/raise/)).

## Signature      {#signature}
```osy syntax
void Raise(<an instance of a class marked [Event]>)
```

## Description    {#description}

### When does a handler hear it?   {#after-commit}
After the commit that carries it — never before, and never for work that did not commit. The event is written in the
same transaction as the rows around it, so the two land together or not at all; then its handlers run, in process
straight after the commit. If the process stops between the two, the platform delivers it later from what was
committed.

A handler therefore reads the record as it stands after the work — a quote raised as accepted is read accepted.

### And inside a workflow's step?   {#in-a-step}
Then its handlers run when the **step** has ended, not at the first commit inside it. One step of a run — a start, an
event's arm, an entry, a timer's body — may commit more than once: a function it calls may commit, and so does a
function marked [[function-commits-alone|`[CommitsAlone]`]]. Every event those commits carry is kept until the
step is over and then delivered together, in the order raised.

So a handler never meets a run half-way through the step that raised to it, and it follows that a row a handler
writes lands **after** the rows the body went on to write in the same step — even when the event was raised in a
function whose own unit of work committed first. If something must be on record at that earlier moment, write it in
the function that raises, not in a handler.

### What if the work is rolled back?   {#rolled-back}
Then it was never raised. `Raise` moves with the rows written around it: a `try` that throws takes back what it wrote
and the events it raised alike, and a function that fails raises nothing.

### What does it cost?   {#cost}
An event no handler hears costs nothing — the compiler knows every handler, so a `Raise` of one nobody hears writes
no row and sends no statement. One somebody hears costs the same however many handlers hear it: its row is written
with the commit, then read, run and marked delivered once — what each handler writes is that handler's own cost.

A handler of EVERY event (a rule engine, a webhook sender) says which events it cares about with
[[function-interest|`[Interest]`]] — and an event heard only by such handlers, none of which cares about it now, costs
nothing either: no row, no delivery, no statement. With no rule and no subscription, an app using them pays for its
events exactly what it paid before it had any.

Several events raised by one piece of work are written in one statement and delivered in ONE transaction: read
together, each record they share read once, one commit. Each further event adds its own mark and whatever its handlers
read and write — not another transaction.

Raising does not cost the person a request: it all happens on the server, after the request's own commit.

### How long is it kept?   {#retention}
The platform keeps a delivered event a week — long enough for an operator to see what a handler did not do, short
enough that it never grows with the app's age or holds an event's personal content past its use — and then lets it go,
with what was recorded against it. A record's history is not kept here: a timeline that shows what happened to a record
keeps its own, for as long as its own setting says ([The RecordTimeline kit — what happened to a record, on its own timeline](https://osysharp.com/reference/ui/activity-kit/)).

### Who may raise one?   {#who}
Any code that can see the class — the kit that declares it, an app or package that uses that kit. The event row is the
platform's and nobody's grant creates one, so no caller can forge an event: it exists only because code raised it.

### What must the argument be?   {#refusals}
An instance of an `[Event]` class. Anything else is refused where it is written:

```text
`NotAnEvent` is not an event — `Raise(…)` takes an instance of a class marked `[Event]`. Mark it: `[Event] public
sealed class NotAnEvent { … }` …
```

## Examples       {#examples}

### Raised inside a `try` that fails   {#example-try}
The `try` takes back the order it placed and the event it raised; the function goes on and commits what it wrote after.

```osy title="an event taken back with its work" test app=function-raise
entity Order {
  [Required, MaxLength(40)] string Code;
  security { allow read, create when IsAnonymous || IsAuthenticated; }
}

entity Heard {
  [Required, MaxLength(100)] string What;
  security { allow read, create when IsAnonymous || IsAuthenticated; }
}

[Event]
public sealed class OrderPlaced { public Order Order; }

[On]
void Note(OrderPlaced e) { new Heard { What = "placed " + e.Order.Code }; }

string PlaceTwo() {
  var kept = new Order { Code = "kept" };
  Raise(new OrderPlaced { Order = kept });
  try {
    var o = new Order { Code = "dropped" };
    Raise(new OrderPlaced { Order = o });
    throw new ValidationException("not this one");
  }
  catch (ValidationException) { }
  return "done";
}
```

```osy title="only the kept order was heard" run app=function-raise
[Test]
void The_try_took_back_its_event() {
  PlaceTwo();
  Background.Settle();
  Assert.Equal(["placed kept"], Heard.Select(h => h.What).ToList());
}
```

## See also       {#see-also}
- [[Event] — what happens to a record, declared once](https://osysharp.com/reference/function/event/) — declaring an event
- [[On] — hear an event, after the commit that raised it](https://osysharp.com/reference/function/on/) — hearing one
- [try / catch / finally](https://osysharp.com/reference/function/try-catch/) — what a `try` takes back
- [Raising a workflow event](https://osysharp.com/reference/workflow/raise/) — moving one workflow run along, which is a different thing
- [The RecordTimeline kit — what happened to a record, on its own timeline](https://osysharp.com/reference/ui/activity-kit/) — a record's history, kept as long as the app says
