Function options builder
Everything Inngest controls about a function, from its triggers to flow control, goes in FunctionOptions, which
the function class can also carry as attributes. When Inngest syncs the app, the SDK turns those options into JSON.
Pick a preset or change the options, and the output shows the C# in both forms and that JSON. Like the other pages,
it shows attributes first unless you picked Code first in one of their tabs.
Valid. The SDK accepts these options and sends the JSON below when Inngest syncs the app.
Attributes
[InngestFunction("sync-account", Name = "Sync account", Retries = 5)]
[EventTrigger("account/updated")]
[Concurrency(20)]
[Concurrency(1, Key = "event.data.accountId")]
[Priority("event.data.plan == 'enterprise' ? 120 : 0")]
[CancelOn("account/deleted", Match = "data.accountId", Timeout = "1d")]
public sealed class SyncAccount : InngestFunction<JsonElement>
{
// ...
}
builder.Services
.AddInngest(options => options.AppId = "shop")
.AddFunction<SyncAccount>();Middleware and checkpointing have no attributes. Pass them to AddFunction in a callback, options => options with { ... }, which starts from the attributes.
Code first
var functionOptions = new FunctionOptions
{
Id = "sync-account",
Name = "Sync account",
Triggers = [Trigger.Event("account/updated")],
Retries = 5,
Concurrency =
[
new ConcurrencyLimit(20),
new ConcurrencyLimit(1) { Key = "event.data.accountId" },
],
Priority = new Priority("event.data.plan == 'enterprise' ? 120 : 0"),
CancelOn = [new CancelOn("account/deleted") { Match = "data.accountId", Timeout = TimeSpan.FromDays(1) }],
};
builder.Services
.AddInngest(options => options.AppId = "shop")
.AddFunction<SyncAccount>(functionOptions);Registration JSON
{
"url": "https://shop.example.com/api/inngest",
"deployType": "ping",
"appName": "shop",
"sdk": "dotnet:v1.0.1-preview",
"v": "0.1",
"framework": "aspnetcore",
"capabilities": {
"trust_probe": "v1"
},
"functions": [
{
"id": "shop-sync-account",
"name": "Sync account",
"triggers": [
{
"event": "account/updated"
}
],
"steps": {
"step": {
"id": "step",
"name": "step",
"runtime": {
"type": "http",
"url": "https://shop.example.com/api/inngest?fnId=shop-sync-account&stepId=step"
},
"retries": {
"attempts": 5
}
}
},
"concurrency": [
{
"limit": 20,
"scope": "fn"
},
{
"limit": 1,
"key": "event.data.accountId",
"scope": "fn"
}
],
"priority": {
"run": "event.data.plan == 'enterprise' ? 120 : 0"
},
"cancel": [
{
"event": "account/deleted",
"timeout": "1d",
"if": "event.data.accountId == async.data.accountId"
}
]
}
]
}How the output is made
Section titled “How the output is made”The builder writes the JSON the same way the SDK’s RegistrationWriter does: the same properties in the same
order, with durations as Inngest time strings (90 minutes becomes "1h30m") and options that are not set left
out, so Inngest applies its defaults. A few details worth knowing:
- A function’s id on the wire is
<app id>-<function id>. retries.attemptsholds the number of retries, not attempts. LeaveRetriesempty to get Inngest’s default of 4 retries.Matchon a cancellation becomes the expressionevent.<path> == async.<path>.- A cron trigger with a time zone is sent with a
TZ=prefix. - A class that implements
IFailureHandlerregisters a second function,<id>-failure, triggered byinngest/function.failed.
The checks are the ones FunctionOptionsValidator makes when the app starts, and the SDK, like the builder, reports
all the problems at once.
Attributes
Section titled “Attributes”As attributes, the options sit on the function class, and AddFunction<TFunction>() reads them into
FunctionOptions when the app starts, so both forms sync to the same JSON and go through the same checks. Each
attribute sets one member:
| Attribute | Sets |
|---|---|
[InngestFunction("id", Name, Retries, Idempotency)] |
Id, Name, Retries, Idempotency |
[EventTrigger("name", If)], [EventTrigger<T>(If)] |
an EventTrigger in Triggers |
[CronTrigger("schedule", Timezone, Jitter)] |
a CronTrigger in Triggers |
[Concurrency(limit, Key, Scope)] |
a ConcurrencyLimit in Concurrency |
[Throttle(limit, "period", Burst, Key)] |
Throttle |
[RateLimit(limit, "period", Key)] |
RateLimit |
[Debounce("period", Key, Timeout)] |
Debounce |
[BatchEvents(maxSize, "timeout", Key, If)] |
BatchEvents |
[Priority("run")] |
Priority |
[Singleton(mode, Key)] |
Singleton |
[CancelOn("name", If, Match, Timeout)], [CancelOn<T>(If, Match, Timeout)] |
a CancelOn in CancelOn |
[Timeouts(Start, Finish)] |
Timeouts |
The trigger, concurrency and cancellation attributes can be repeated. Durations are time strings such as "30s",
"5m" or "1h30m". Middleware and Checkpointing have no attributes; set them with
AddFunction<TFunction>(options => options with { ... }), which starts from the attributes. Options passed as
AddFunction<TFunction>(new FunctionOptions { ... }) replace the attributes. An attribute of your own derives from
FunctionOptionsAttribute, as all of these but [InngestFunction] do;
Functions and triggers shows how.
The site’s build checks this page against the SDK: the snippet check compiles both forms of every preset, registers each in a real app and compares the JSON the SDK sends with the JSON shown here.
Flow control explains each option, and Functions and triggers covers ids, names and triggers.
inngest-dotnet is a community Inngest SDK for .NET. It is not affiliated with or endorsed by Inngest Inc.