580
Views
11
Comments
Asynchronous programming in .net Extensions
Question

Does anyone have experience with or examples of using Asynchronous programming in OutSystems .net extensions?

I want to call the SendGrid (email) service. The SendGrid interface is request/response based. Here is their example C# code:

// using SendGrid's C# Library
// https://github.com/sendgrid/sendgrid-csharp
using SendGrid;
using SendGrid.Helpers.Mail;
using System;
using System.Threading.Tasks;

namespace Example
{
    internal class Example
    {
        private static void Main()
        {
            Execute().Wait();
        }

        static async Task Execute()
        {
            var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
            var client = new SendGridClient(apiKey);
            var from = new EmailAddress("test@example.com", "Example User");
            var subject = "Sending with SendGrid is Fun";
            var to = new EmailAddress("test@example.com", "Example User");
            var plainTextContent = "and easy to do anywhere, even with C#";
            var htmlContent = "<strong>and easy to do anywhere, even with C#</strong>";
            var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
            var response = await client.SendEmailAsync(msg);
        }
    }
}

Pretty simple code. I have a concern that introducing the System.Thread.Tasks dependency and using async and await C# features may not play well with the OutSystems extensions.

I'm looking for any documentation or examples that would help me best understand how to use, if possible, asynchronous programming in a OutSystems extension.


Thanks



mvp_badge
MVP
Rank: #2

Hi Timothy,

Extensions run in the context of the eSpace that references them, and are to be used as simple libraries for one-shot tasks. I don't think you can reliably use them as background services or the like.

Rank: #238

Hello,

First up - why are you concerned about using threading and/or async-await in OS extensions? As Kilian said, extensions are one-shot, but so far I've been able to use every trick I've had in my C# pockets.

In that example,

private static void Main()

is synchronous and will not return the control to Outsystems side of things until Execute.Wait() call returns. I would at least try implementing this action as Outsystems extension, basically defining this as an endpoint in integration studio and calling that Execute.Wait() from there.

Execute() in your example returns Task, for Task.Wait() documentation in MSDN, see https://msdn.microsoft.com/en-us/library/dd235606(v=vs.110).aspx

If this is something you would like to call from UI, then it's of course a blocking call. If this is the case and you are building a Mobile app, I'd see what JS promises could offer to you:

https://success.outsystems.com/Documentation/10/Extensibility_and_Integration/JavaScript/Extend_Your_Mobile_App_Using_JavaScript/Defining_Asynchronous_JavaScript_Code

Note that the link above applies only to OS Mobile apps. I've not so far used (or tried to use) JS promises in web side of things.

---

For this specific library, I see they also offer WebHooks approach (https://sendgrid.com/docs/API_Reference/Webhooks/event.html), which in some cases might be the preferred way to integrate with Outsystems.

mvp_badge
MVP
Rank: #2

Hi Timothy,

I wonder whether what you're doing is really needed in an Extension? Sending e-mail can be done from the platform, so why put it in an Extension?

mvp_badge
MVP
Rank: #2

Thanks for the comprehensive answer. One thing though:

"the platform isn't really the right tool to handle large, fully constructed, email pass-through campaigns (100,000+ per)." - I'm not sure I agree. It depends on the use case of course, but there's no obvious reason the platform couldn't handle this volume per se.

mvp_badge
MVP
Rank: #7

OK, good news:

have done this and it can work just fine.

I wrote a heavily multi-threaded extension (firing dozens of threads off at once to parse out a document, run search engine queries in parallel, collate the results, download the text from the returned URLs, perform additional analylsis).

The way I did it, was to have an Action in my Extension that accepted all of the needed information. In it, I did all of the needed queries (this was before asyc/await, I was using the multi-threaded ForEach from TPL), returned to the main thread to collate results, then used the same pattern to download and analyze the results, then collated the analysis into a structure as output.

To call this (because it could take a while), I used a timer. The UI was effectively building a record to be batched, then kicking off the timer to pick up the batches and run them. The new lightweight processes in BPT would be perfect for this instead of the timer, by the way.

J.Ja

Rank: #20457

Filipe,

Sorry - I did not. I used REST calls instead. I see others in the thread have succeeded though. 

Rank: #8845

Timothy , i just made it! You have to use .ConfigureAwait(false);
"Await resumes execution in the Synchronization context (essentially the thread) that started awaiting. If that thread is already blocked, eg. by awaiting itself on something else, the code deadlocks.": https://stackoverflow.com/questions/17202709/iis-failing-when-await-task-used