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

Provide a hook for invoke #1167

Closed
wants to merge 1 commit into from
Closed

Provide a hook for invoke #1167

wants to merge 1 commit into from

Conversation

MikeStall
Copy link
Contributor

Resolves #1140

if (hook != null)
{
IFunctionInvoker invoker = new InvokeWrapper(instance.Invoker, hook);
instance = new FunctionInstance(instance.Id, instance.ParentId, instance.Reason, instance.BindingSource, invoker, instance.FunctionDescriptor);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is bypassing the instance factory. I don't think we should do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? This doesn't need any factory services. What did you have in mind? An alternative approaches could be to make Invoker a mutable property and just change it on the existing instance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have a factory pattern, then all creation should go through it. You might sidestep this problem by having the factory interface take the TriggeredFunctionData so it has access to the value as well as the callback. The interface is internal.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Host.Protocols;
using Microsoft.Azure.WebJobs.Host.Triggers;

namespace Microsoft.Azure.WebJobs.Host.Executors
{
internal class TriggeredFunctionExecutor<TTriggerValue> : ITriggeredFunctionExecutor
internal class TriggeredFunctionExecutor<TTriggerValue> : ITriggeredFunctionExecutor, ITriggeredFunctionExecutorWithHook
Copy link
Member

@mathewc mathewc Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should find a more general solution to this, rather than hack in this hook. Let's give it some thought. E.g. @fabiocav had some ideas about introducing an Owin like middelware model to allow people to plug in at various places in our pipeline. If we don't go that far, perhaps an interface people can register in our services collection that we call at various points in our pipeline for extensibility. Even the work we're doing now for Invoke Filters applies to this scenario if we were to allow filters to be registered host level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very open to alternatives. The criteria for me was the simplest solution that
a) fulfilled some strict scenario requirements (it needs to be dispatched exactly at this spot in the pipeline);
b) was relatively isolated and had a clear 'opt-in' model.
This is a rocket-science case and I specifically didn't want it to get broad traction except from things that really needed it. I didn't want to create a matrix of feature interactions.

Copy link
Member

@mathewc mathewc Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative to consider would be to extend the existing TriggeredFunctionData parameter by adding your callback on there. Easy for consumer to specify the callback, and below you just check for it and use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that, but it would violate #b - this is a very powerful hook and I don't want to make it easy or tempting to get at it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're adding a new public ITriggeredFunctionExecutorWithHook interface that we need to maintain going forward. It feels pretty hacky. If we really need to add this capability then I think we should add it in a clean way and commit to it.

/// </summary>
/// <param name="input">The trigger invocation details.</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <param name="hook">a hook that wraps the underlying invocation</param>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does a custom trigger specify this hook?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The binding provides a listener which is in full control of making calls on ITriggerFunctionExecutor*. So it's imperative calls; not registered.

@MikeStall
Copy link
Contributor Author

Closing, we'll go with #1178 instead

@MikeStall MikeStall closed this Jun 19, 2017
@MikeStall MikeStall deleted the invokehook branch July 20, 2017 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants