Skip to content

Global functions

Global functions are workspace-level units of C# business logic. Unlike entity-scoped functions, they run with no record context — no entity snapshots and no save pipeline. Each published global function has the Job contract. Production invocation through a schedule, API enqueue publication, or IFunctionQueue creates a queued worker job that finishes with a FunctionResult: success, skip, or failure plus an optional summary message and JSON payload. The administrative test-invocation route is the deliberate exception: it executes a direct test call and records a run without representing a scheduled or API-enqueued job. Global functions are authored in the workspace Net Operation Project using the Moltaro .NET SDK programming model.

A global function derives from GlobalFunction (no arguments) or GlobalFunction<TArgs> (a JSON-serializable argument type the runtime deserializes before the call) and implements a single method:

public override Task<FunctionResult> OnRunAsync(CancellationToken cancellationToken)

The result comes from the FunctionResult factories: Ok(message) for plain success, OkData(data, message) for success with a structured JSON payload, Skipped(message) / SkippedData(data, message) when the function intentionally did no work, and Failed(message) for a failed run. The class is declared with [MoltaroFunction], which assigns the durable function id, an optional stable callable key (the id is used when omitted), and the name and description administrators see.

  • Function Schedules. A CRON schedule runs the function on a recurring plan. Schedules are managed on the Function Schedules page in the Constructor area, group “Automation & logic”; see Schedules. Schedule-triggered runs may have no original user in the FunctionContext.
  • API enqueue. A function marked with [MoltaroApiEnqueue] is published on POST /api/workspace/functions/{functionKey}/enqueue. Callers observe the job with GET /api/workspace/functions/jobs/{jobId} and cancel it with POST /api/workspace/functions/jobs/{jobId}/cancel. Access is declared in code — exactly one of a permission key or an any-authenticated-user flag; anonymous invocation is never supported. An optional 1–86400 second timeout is captured on the queued job and preserved for every retry. See Commands and API functions.
  • Test invocation. Administrators run a global function directly from the Function Catalog page in the Constructor area, group “Automation & logic”.
  • Function-to-function enqueue. A function can inject IFunctionQueue and call EnqueueAsync(functionKey, args) only for a published global Job. The method returns the job id; poll GET /api/workspace/functions/jobs/{jobId}. It is not synchronous function composition.

For synchronous reuse, put the common C# behavior in a project service, register it from IMoltaroNetOperationProjectStartup, and inject that service into both functions. This keeps one call stack and one observable result without manufacturing a background job.

Every run is recorded with its result message and data and can be inspected on the Function operations monitoring page in the Administration area; see Operations.

GlobalFunction.OnRunAsync returning Task is not, by itself, proof that an HTTP caller receives a background job. The invocation surface decides that: API enqueue, schedules, and IFunctionQueue create jobs, while an administrator’s test invocation is a direct test call. After publishing, read CurrentPublishedContract from the Function Catalog and the publication or schedule metadata. See Asynchronous operations and polling.

A schedule-compatible function that reads the workspace-local date from the runtime clock and writes a developer-log entry. FunctionContext.Operation tells the function which invocation source triggered the run:

using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using Moltaro.Package.NET;
using Moltaro.Package.NET.Functions;
using Moltaro.Package.NET.ModuleRuntime.Runtime;
[MoltaroFunction(
"ops.dailyTicketDigest",
Name = "Daily ticket digest",
Description = "Schedule-compatible global function for a daily operational digest.")]
public sealed class DailyTicketDigestFunction(
IMoltaroRuntimeClock clock,
FunctionContext context,
IDevLog devLog) : GlobalFunction
{
public override async Task<FunctionResult> OnRunAsync(CancellationToken cancellationToken)
{
var today = clock.GetLocalToday();
await devLog.LogInformationAsync(
"Daily ticket digest ran.",
new JsonObject
{
["LocalDate"] = today.ToString("yyyy-MM-dd"),
["Operation"] = context.Operation.ToString()
},
cancellationToken: cancellationToken);
return FunctionResult.Ok($"Daily ticket digest completed for {today:yyyy-MM-dd}.");
}
}

Example: typed query with structured result data

Section titled “Example: typed query with structured result data”

A function that queries the generated, strongly typed workspace DbContext and returns a structured payload with FunctionResult.OkData. The payload and message are stored on the run:

using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Moltaro.Operational.Generated;
using Moltaro.Package.NET;
using Moltaro.Package.NET.Functions;
[MoltaroFunction(
"ops.logWorkspaceSummary",
Name = "Log workspace summary",
Description = "Writes a compact workspace summary to the DevLog.")]
public sealed class LogWorkspaceSummaryFunction(
GeneratedWorkspaceContext dbContext,
IDevLog devLog) : GlobalFunction
{
public override async Task<FunctionResult> OnRunAsync(CancellationToken cancellationToken)
{
var userCount = await dbContext.Users
.AsNoTracking()
.CountAsync(cancellationToken);
await devLog.LogInformationAsync(
"Workspace summary calculated.",
new JsonObject { ["UserCount"] = userCount },
cancellationToken: cancellationToken);
return FunctionResult.OkData(new { UserCount = userCount }, $"Workspace users: {userCount}.");
}
}

Global functions are one of several installation-level logic surfaces. Commands and API functions covers direct API invocation — synchronous command functions and the enqueue/job endpoints in detail. Actions covers functions invoked by users from the product UI. HTTP endpoints covers inbound webhook-style endpoints that external systems call. Schedules covers CRON schedule management. Moltaro has no separate outbound webhook feature: outbound calls to other systems are made in C# from global or trigger functions.