EnergyAtlas Wiki
WebAPI
Quick Start Workflows Python WebAPI Library User Stories Wiki Guide
  • Web API Reference
  • Development Guide
  • Architecture
  • Core
  • Web Development
    • Overview
    • Execution Modes
    • GUI Jobs
    • GUI-less Jobs
    • Local File Access
    • Report Logs
  • Grasshopper Development
    • Components
    • Component Standards
    • Live Preview

WebAPI

EnergyAtlasWeb Job (Single-Click, No GUI)¶

A GUI-less job is a pre-configured background task that the user triggers with a single click. It has no input form — parameters are hard-coded in the factory or read from server-side configuration. The only user-facing surface is a Start button, a real-time log stream, and (optionally) a completion status.

Architecture overview¶

1
2
3
4
5
┌──────────────┐   POST /api/jobList/{name}/start   ┌─────────────────────┐
│   Frontend   │ ──────────────────────────────────► │ JobRouterController  │
│  (one-click) │                                     │  → IJobFactory       │
│              │ ◄── SignalR (jobEvent) ────────────  │  → IControllerJob    │
└──────────────┘                                     └─────────────────────┘
  1. Frontend shows a list of registered jobs (from GET /api/jobList).
  2. User clicks Start — POST /api/jobList/{jobName}/start.
  3. The controller resolves the factory, creates the job, runs it on a background thread.
  4. Progress is streamed to the client via SignalR (JobHub).

Key interfaces¶

IJobFactory¶

EnergyAtlasWeb/Jobs/Abstractions/IJobFactory.cs

1
2
3
4
5
6
public interface IJobFactory
{
    string JobName { get; }
    string JobDescription { get; }
    IControllerJob Create(ILogger logger, IJobReporter reporter);
}

The factory is a singleton registered in DI. It provides a name/description for the job list and creates a fresh IControllerJob instance for each run.

IControllerJob¶

EnergyAtlasWeb/Jobs/Abstractions/IControllerJob.cs

1
2
3
4
public interface IControllerJob
{
    void Run();
}

No inputs, no outputs. The job does its work and reports progress via the IJobReporter it received at construction time.

Factory registration¶

Factories are registered as singletons in Program.cs:

1
2
3
4
builder.Services.AddSingleton<IJobFactory, TiledVoxelShadingJobFactory>();
builder.Services.AddSingleton<IJobFactory, TiledLidarVoxelizationJobFactory>();
builder.Services.AddSingleton<IJobFactory, TqdmStressTestJobFactory>();
builder.Services.AddSingleton<JobRegistry>();   // collects all IJobFactory

JobRegistry receives IEnumerable<IJobFactory> via constructor injection and builds a lookup dictionary keyed by JobName.

Adding a new one-click job¶

  1. Create a class that implements IJobFactory.
  2. In Create(...), return a new instance of your job (implementing IControllerJob).
  3. Register it in Program.cs: builder.Services.AddSingleton<IJobFactory, MyJobFactory>();.
  4. It automatically appears in the job list.

Minimal code template¶

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// ─── Factory ────────────────────────────────
public class MyJobFactory : IJobFactory
{
    public string JobName => "MyJob";
    public string JobDescription => "Does something useful with one click.";

    public IControllerJob Create(ILogger logger, IJobReporter reporter)
        => new MyJob(logger, reporter);
}

// ─── Job ────────────────────────────────────
public class MyJob : IControllerJob
{
    private readonly ILogger _log;
    private readonly IJobReporter _reporter;

    public MyJob(ILogger log, IJobReporter reporter)
    {
        _log = log;
        _reporter = reporter;
    }

    public void Run()
    {
        _reporter.Report(JobSignal.Start(message: "MyJob starting"));

        using (var bp = new BinaryProgress(_reporter, label: "Loading data"))
        {
            // ... work ...
        }

        using (var tq = new TQDM(_reporter, total: 100, label: "Processing items"))
        {
            for (int i = 0; i < 100; i++)
            {
                // ... work per item ...
                tq.Increment();
            }
        }

        _reporter.Report(JobSignal.Log(message: "All done."));
    }
}

See SignalR Logging for the full reference on BinaryProgress, TQDM, JobSignal, and how each log type renders in the frontend.

Execution flow (controller side)¶

JobRouterController.StartJob (POST /api/jobList/{jobName}/start):

  1. Resolve factory from JobRegistry.
  2. Generate a jobId (GUID).
  3. Create JobRuntimeState via JobStore.Create(jobId, jobName).
  4. Spawn Task.Run:
  5. Create SignalRJobReporter(_hub, jobId).
  6. Call factory.Create(logger, reporter) → IControllerJob.
  7. Call job.Run().
  8. On success: JobStore.Complete(jobId).
  9. On failure: JobStore.Fail(jobId, ex.Message).
  10. Return { success: true, jobId } immediately.

The frontend connects to SignalR (JoinJob(jobId)) and renders signals in real time.

When to use this vs a GUI job¶

Criterion GUI-less job GUI job
User-provided parameters None (or server config) Yes — typed input form
Output artefacts None (results are side effects) Yes — text, charts, files
Use case Batch processing, cron-like tasks, infrastructure Analysis, reports, interactive tools

If the job needs any user input or produces downloadable output, use a GUI Job instead.

See also¶

  • GUI Job — auto-generated job pages with inputs and outputs
  • SignalR Logging — reporter, signal types, progress bars
  • Working with Local Files — file picking, artifact sink, execution mode differences
  • Execution Modes — browser vs local mode
GUI Jobs Previous Local File Access Next

Last page update GMT-04:00 05:00 Jul 19 2026
Last website update GMT-04:00 05:00 Jul 19 2026

Found an issue on this page? Please open an issue on GitHub.

On this page

  • EnergyAtlasWeb Job (Single-Click, No GUI)
    • Architecture overview
    • Key interfaces
      • IJobFactory
      • IControllerJob
    • Factory registration
      • Adding a new one-click job
    • Minimal code template
    • Execution flow (controller side)
    • When to use this vs a GUI job
    • See also

WIP EnergyAtlas Wiki

EnergyAtlas Wiki is still under active development. Thank you for your patience while we improve the documentation. If you have any questions, please contact us.