18 Oct 2021

Open Network in Preview

You might have seen the AU class called Two New Features by Forge Design Automation API: Open Network and WebSocket API that spoke about a new feature that is currently available in Preview for all engines.

The following is mentioned in the class handout:

Currently, Open Network feature is still under development, 
there still might be some changes related to this feature before 
it's officially released, please wait for our official announcement 
and we will share all the details and the demo source code when 
it's announced released.

Please contact aps.help@autodesk.com to require allow-list to 
try this new feature. 

The protocols supported: Only HTTP/HTTPS calls are allowed, 
no other protocols are supported.

Currently, it's only available for developers with a Forge subscription.

Before we can get network access enabled for a given Forge app, that needs to have a nickname set using the PATCH forgeapps/:id endpoint. And that requires that the Forge app has no app bundles or activities in it.

Please note that if you use the DELETE forgeapps/:id to delete all your app bundles and activities later on, then we'd have to re-enable network access for the app again - so the best thing is to avoid doing that with the app that you use for testing this new feature.

In order to test network access, I updated my sample talked about in Faster configuration results

It's an ASP.NET core sample and so I wanted to use Tasks and await them, which requires the calling function to be async
If you simply make Run() async, like this, then things seem to work but the whole process will exit pretty quick as the execution will not be kept inside the Run() function:

public async Task Run(Document doc)

What we have to do instead is create a new RunAsync() and start running that from the Run() function:

public void Run(Document doc)
{
    var task = RunAsync(doc);
    task.Wait(60000); // 1 minute
    if (task.Exception != null)
    {
        throw task.Exception;
    }
}

public async Task RunAsync(Document doc)
{
    var data = await GetDataAsync();
    // etc
}

It's a good idea to limit the running time of the work item while testing so that as you keep starting them you won't end up with multiple of them running for the maximum allowed time and costing you money. I'm restricting them to 1 minute.

Inside the Run() function I have a loop that keeps reaching out to my server to see if there are any new parameters that should be used to update the model:

public async Task<JObject> GetData(string url)
{
    LogTrace("[GetData]");
    LogTrace(url);
    using (var client = new HttpClient())
    {
        var response = await client.GetAsync(url);
        LogTrace("[/GetData]");

        var data = await response.Content.ReadAsStringAsync();

        JObject j = JObject.Parse(data);

        return j;
    }
}

Since only HTTP/HTTPS protocols are allowed from an app bundle, therefore, I could not use e.g. WebSockets to have direct communication with my server. Instead of constantly polling the server every second or so from the app bundle for new parameter values, I use something called long polling. When the app bundle asks for new parameter values I do not reply until the client side provides me with new values:

/// <summary>
/// Called by the code in the app bundle to get the latest data 
/// to use for the model configuration
/// </summary>
[HttpGet]
[Route("api/forge/designautomation/data")]
public async Task<IActionResult> GetData([FromQuery] string id)
{
    System.Diagnostics.Debug.WriteLine("GetData");

    _runningWorkitemTasks[id] = new TaskCompletionSource<JObject>();
    JObject data = await _runningWorkitemTasks[id].Task;

    return Ok(data.ToString());
}

The results are sent directly to the server, instead of relying on Design Automation to upload them only when the work item is finished, e.g.:

if (outputJsonUrl != null)
{
    string positionData = SavePositions(asm.ComponentDefinition);
    if (directUpload)
    {
        _ = UploadDataAsync(outputJsonUrl, positionData);
    }
}

You can check out the live version of this sample which now has an extra option: Keep workitem running (max 1 minute)
https://inventor-configurator.autodesk.io/ 
(source code: https://github.com/adamenagy/QuickerAssemblerDA)

If you change the parameter values and click the "Start/Update" button again within a minute then the existing work item will be used to get the new part positions. When the work item stops running the content of its report.txt file will be shown in the text window.

This new functionality will enable you to balance speed vs cost. Where speed is really needed now you will be able to reuse existing work items, but it will cost more as the work item keeps running even if it's not actually doing anything apart from waiting for new input from the customer.

There are many use-cases beyond the one discussed in this article that will benefit from this new feature: getting relevant data directly from databases, accessing additional files if needed, etc.

 

Related Article