# Workflow.InRun (can this code wait?)

> `Workflow.InRun` is true in a workflow's body and in everything that body calls — where `await Workflow.Run(…)` may wait for days — and false everywhere else: a page's action, a function called over the API, a test. A function that may need to wait for somebody reads it to choose: wait in place when the caller can, start the wait and answer "still waiting" when it cannot.

<!-- id: workflow-in-run · area: workflow · stability: preview · html: https://osysharp.com/reference/workflow/in-run/ -->

## Summary        {#summary}
Only a workflow can wait. `await Workflow.Run("sign", signature)` in a workflow's body parks the run until the
signature is in; the same line reached from a page's action has nothing to park, and fails. A function that is called
from both — a kit's "ask a person", "get this approved" — needs to know which it is in:

```osy syntax
if (!Workflow.InRun) { Workflow.Run(signature); return "asked"; }   // start it, and say it is not in yet
await Workflow.Run("sign", signature);                              // wait for it, however long
return "signed";
```

## Signature      {#signature}
```osy syntax
Workflow.InRun -> bool   // true in a workflow's body and in anything it calls
```

## Description    {#description}

### Where is it true?   {#where}
In a workflow's `enter`, `exit`, `on`, `Start` and reminder bodies, and in every function, method and lambda those
call, to any depth. It is the question "would an awaited `Workflow.Run` here have a run to park?", so it is true in a
function exactly when that function was reached from a workflow's body.

It is false in a page's action, in a function called by a page, over the API or by a tool, in an `[On]` handler that
a plain function's change set off, and in a test's own body.

### What is it for?   {#for}
One function with one name for both callers. Without it a kit offers two — "ask and wait" for workflows, "ask and
come back later" for pages — and every caller has to know which it is. With it, the function waits when its caller
can and otherwise hands back something that says the answer is not in yet; the caller that could not wait hears the
answer as an event, or reads it when it looks again.

### It is read, never kept   {#read}
The answer is a fact about the call, not about the function: the same function is in a run for one caller and not
for the next. Read it where you branch.

## Examples       {#examples}
```osy title="one function: it waits in a workflow, and says 'asked' from a page" run app=workflow-in-run
using Osysharp.Workflow;

enum SignStatus { Asked, Signed }
enum LetterStatus { Drafting, Sent, Held }

entity Signature {
  SignStatus Status = SignStatus.Asked;
  security { allow read, create, update when IsAuthenticated || IsAnonymous; }
}

workflow SignFlow {
  Tracks = Signature.Status; Autostart = false; Initial = Asked;
  event Sign();
  state Asked { subscribe Sign(); on Sign { goto Signed; } }
  terminal success Signed { }
}

entity Letter {
  LetterStatus Status;
  [MaxLength(80)] string Note = "";
  security { allow read, create, update when IsAuthenticated || IsAnonymous; }
}

public class Desk {
  /// Get a signature: waits for it where the caller can wait, and says "asked" where it cannot.
  public static async Task<string> GetSigned(Signature s) {
    if (!Workflow.InRun) {
      Workflow.Run(s);                 // start it; whoever signs will find it
      return "asked";
    }
    await Workflow.Run("sign", s);     // the run parks here until it is signed
    return "signed";
  }
}

/// What a page's action calls.
public async Task<string> AskFromAPage(Signature s) { return await Desk.GetSigned(s); }

workflow LetterFlow {
  Tracks = Letter.Status; Autostart = true; Initial = Drafting;
  state Drafting {
    enter {
      var s = Workflow.Once("signature", () => new Signature { });
      this.Item.Note = await Desk.GetSigned(s);
      goto Sent;
    }
  }
  terminal success Sent { }
  terminal cancel  Held { }
}

[Test]
void called_from_a_page_it_cannot_wait_and_says_so() {
  var s = new Signature { };
  Assert.Equal("asked", await AskFromAPage(s));
  Assert.Equal(SignStatus.Asked, s.Status);
}

[Test]
void called_from_a_workflow_it_waits_for_the_signature() {
  var letter = new Letter { };
  Workflow.Settle(letter);
  Assert.Equal(LetterStatus.Drafting, letter.Status);     // parked: nobody has signed

  SignFlow.RaiseSign(Signature.Single());
  Workflow.Settle(letter);
  Assert.Equal(LetterStatus.Sent, letter.Status);
  Assert.Equal("signed", letter.Note);
}
```

## Notes          {#notes}
- It says where the code is running, not who is running it. A workflow's body runs as the app unless it says
  otherwise ([What a workflow body may write](https://osysharp.com/reference/workflow/body-security/)); `Workflow.InRun` has nothing to do with that.
- A task started beside its caller (`var t = F(x);`) in a workflow's body is still in the run, and may wait
  ([Tasks that wait (Task.WhenAll across days)](https://osysharp.com/reference/workflow/tasks-that-wait/)).

## See also       {#see-also}
- [Workflow.Run (start a workflow)](https://osysharp.com/reference/workflow/run/) — the wait itself, and what it answers
- [Tasks that wait (Task.WhenAll across days)](https://osysharp.com/reference/workflow/tasks-that-wait/) — several waits at once
- [async / await and Task](https://osysharp.com/reference/function/async-await/) — `async`, `Task` and `await`
