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.
The job contract
Section titled “The job contract”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.
How global functions are invoked
Section titled “How global functions are invoked”- 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 onPOST /api/workspace/functions/{functionKey}/enqueue. Callers observe the job withGET /api/workspace/functions/jobs/{jobId}and cancel it withPOST /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
IFunctionQueueand callEnqueueAsync(functionKey, args)only for a published globalJob. The method returns the job id; pollGET /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.
Example: scheduled daily digest
Section titled “Example: scheduled daily digest”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}."); }}Related installation-level surfaces
Section titled “Related installation-level surfaces”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.