Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Isolated process - Definite documentation on how to write custom binding and triggers, and troubleshoot section #2092

Open
Kryptos-FR opened this issue Nov 23, 2023 · 14 comments
Assignees
Labels

Comments

@Kryptos-FR
Copy link

Kryptos-FR commented Nov 23, 2023

Hello, I have a hard time making anything work in the isolated worker model. All the available doc is about the in-process model, which is ironic since Microsoft is pushing us towards the other one.

Where can I find a definitive documentation on how to write custom bindings and triggers for the isolated worker?

For example, I just want to be able to inject a class into my functions. But the only place it works is on the class constructor, while I want one per-function call.

Pseudo code:

// Types to inject
public interface IMyType {}
public class MyType : IMyType {}

// Register them
[assembly: WorkerExtensionStartup(typeof(MyExtensionStartup))]
public sealed class MyExtensionStartup : WorkerExtensionStartup
{
    public override void Configure(IFunctionsWorkerApplicationBuilder applicationBuilder)
    {
        applicationBuilder.Services.AddSingleton(typeof(IMyType), typeof(MyType));
    }
}

// Function
public class MyFunction
{
    private readonly IMyType _my;
    public MyFunction(IMyType> my)
    {
        _my = my; // OK
    }
    
    [Function("Try_Get")]
    public async Task<HttpResponseData> Get(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestData request,
        CancellationToken token,
        IMyType? my = null
    )
    {
        // my is always null
        return request.CreateResponse(HttpStatusCode.OK);
    }
}

I also tried using an attribute but I don't know how to make it work and there is no documentation for that:

[AttributeUsage(AttributeTargets.Parameter)]
public class MyBindingAttribute : BindingAttribute
{

}

// In MyFunction class

    [Function("Try_Get")]
    public async Task<HttpResponseData> Get(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestData request,
        CancellationToken token,
        [MyBinding] IMyType? my = null
    )

Using an "input" binding instead brings an error:

[AttributeUsage(AttributeTargets.Parameter)]
public class MyBindingInputAttribute : InputBindingAttribute
{

}

// In MyFunction class

    [Function("Try_Get")]
    public async Task<HttpResponseData> Get(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestData request,
        CancellationToken token,
        [MyBindingInput] IMyType? my = null
    )

The 'Try_Get' function is in error: The binding type(s) 'myBinding' are not registered. Please ensure the type is correct and the binding extension is installed.

Would be nice to have a documentation page to troubleshoot those errors. It is pointless to report them if there is no way to find a solution.

@Kryptos-FR Kryptos-FR changed the title Definite documentation on how to write custom binding and triggers, and troubleshoot section Isolated process - Definite documentation on how to write custom binding and triggers, and troubleshoot section Nov 23, 2023
@gallivantor
Copy link

Agreed. There seems to be no documentation at all for how to build a custom binding with the isolated worker model. The best I could find was that building on top of your example you need to build a class that implements IInputConverter and then attach it to the InputAttribute using this:
[InputConverter(typeof(MyInputConverter))]

But that is also not enough to get the binding registered, I get the same error message as you:

The 'Try_Get' function is in error: The binding type(s) 'myBinding' are not registered. Please ensure the type is correct and the binding extension is installed.

@liliankasem liliankasem added the area: documentation Improvements or additions to documentation label Nov 28, 2023
@DadvDadv
Copy link

DadvDadv commented Dec 1, 2023

Do you know if there is any IExtensionConfigProvider equivalent ?

@fabiocav
Copy link
Member

fabiocav commented Dec 5, 2023

@Kryptos-FR can you share more details about the scenario you expect to handle with your custom binding? I'm assuming the one you've shared above is a simple example, so it would be good to understand your concrete requirement.

The reason why I'm asking is because custom bindings, and particularly triggers, have very limited support in Functions (this is not specific to isolated, as it applies to the in-proc model as well), and there are new extensibility options exposed by isolated that we might be able to recommend if we better understand your scenario.

@Kryptos-FR
Copy link
Author

Kryptos-FR commented Dec 11, 2023

@fabiocav Let me setup a small repo to illustrate our use. I'll edit this comment once it's ready.

edit: available at https://github.com/Kryptos-FR/azure-functions-dotnet-worker-2092

@mikoskinen
Copy link

Ended up in this issue after trying to find documentation on how to convert our existing WebJobs based function trigger to work with this new model.

Let's say that I would like to develop a custom trigger that works with something like Apache Pulsar or NATS or something which isn't available out of the box. Where do I start? For example I have a custom NATS trigger working but it uses the webjob based sdk and now with the new model, there's this:

Error AZFW0001 : The attribute 'NatsTriggerAttribute' is a WebJobs attribute and not supported in the .NET Worker (Isolated Process). (https://aka.ms/azfw-rules?ruleid=AZFW0001)

Is there a migration guide about this subject?

Thanks in advance.

@Kryptos-FR
Copy link
Author

@fabiocav do you have any guidance on the subject, especially regarding the sample I provided? What are the others ways you mentioned?

@mattramsay-ice
Copy link

mattramsay-ice commented Feb 16, 2024

Currently encountering the same black hole regarding documentation on custom trigger bindings in the world of isolated worker functions.

It's currently blocking us from migrating to the isolated worker model.

Other than a couple of articles and trying to reverse engineer the existing worker extensions for OOTB triggers/input/output bindings, there really isn't anything out there.

If custom triggers is something the Azure functions team don't intend to support going forward (as alluded to in an earlier comment), then that should be stated explicitly.

@DadvDadv
Copy link

For input binding, i found that we could use InputConverterAttribute

using Microsoft.Azure.Functions.Worker.Converters;

 public class FromIfMatchHeaderAttribute : InputConverterAttribute
 {
     /// <summary>
     /// Creates an instance of the <see cref="FromEtagAttribute"/>.
     /// </summary>
     public FromIfMatchHeaderAttribute()
         : base(typeof(IfMatchConverter))
     {
         
     }
 }


    internal class IfMatchConverter : IInputConverter
    {
        public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
        {
            var httpRequestData = context.FunctionContext.GetHttpRequestDataAsync().GetAwaiter().GetResult();

            if (httpRequestData != null)
            {
                var etag = httpRequestData.IfMatchHeader(); //Custom code for catch IFMatch header

                return new ValueTask<ConversionResult>(ConversionResult.Success(etag));
            }

            return new ValueTask<ConversionResult>(ConversionResult.Success(null));
        }
    }

Usage :

       public async Task<HttpResponseData> Update(
           [HttpTrigger(AuthorizationLevel.Function, "put", Route = "customers/{id}")] HttpRequestData req,
           [FromBody] UpdateDictionaryCommand model, //From Body it's the only one attribute i've found in the new isolated process
           string? id, //From Route by default
           [FromIfMatchHeader] string? etag //From header
           )
{
...
}

Unfortunatly, you couldn't replace the "req" variable (i didn't use it but it's requiered for HttpTrigger.

It's not perfect, but it could do the job some time

I try to use TriggerBindingAttribute to create my own, but without success (I think we need to create some kind of middleware to do the data conversion).

@molinomatteo
Copy link

Hello, same problem here.
We have many custom bindings that we need to migrate to Workers.

For example we implemented Coap, Mqtt, Mongo, OpcUa, Redis, IotHub (fe: registry input, ack trigger and cloud to device messages).

By reading some articles and looking at your workers implementation (EventHub, ServiceBus, Blob etc) I understood that in every new project I have to:

  • create new Attributes to "pass" configuration settings
  • create an implementation of IInputConverter for each trigger or input bindings
  • create an implementation of IOutputConverter for each output binding
  • add [assembly: ExtensionInformation("<My.CustomBinding.Extension>", "X.X.X")] to refer to my custom, binding

So my questions are:

  • Are my assumptions correct?
  • Are the IInputConverters and IOutputConverters the classes to allow rich bindings? Or what is the pourpose of these interfaces?
  • How can i control the way the binding object is passed from host to isolated process?
  • The most complete example i found is the blob trigger, when you are going to provide documentation about how to implement a custom binding?
  • For example in the Coap binding for the in-process function I bind the "Request" and after that I write the response by using that object, what is the strategy or what changes do I have to make to to my custom binding to support this feature in isolated process too?

@ivelten
Copy link

ivelten commented Apr 15, 2024

I am having the same problem here.

Our company uses in-proc input and output bindings that we want to migrate to the isolated worker, but the documentation we found so far is not enough, especially to help understand how to create and use custom output bindings.

@jaliyaudagedara
Copy link

Stumbled upon this.

Any update guys?

@perum
Copy link

perum commented Jun 11, 2024

This is a serious problem... We use custom INPUT bindings to parse auth tokens/Claims.
To convert to net8 / isolated, these need to work, and there is NO documentation, or even mention of a breaking change.

@Joseph-Steven-S
Copy link

Hello,

Is there any update on this?

@kkdubey
Copy link

kkdubey commented Aug 26, 2024

Hello,

Any update on this issue?
Is there any document to implement Custom attribute trigger?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests