Skip to content

Commit

Permalink
WIP: just a backup.
Browse files Browse the repository at this point in the history
  • Loading branch information
MattEdwardsWaggleBee committed Oct 21, 2024
1 parent b7c87e7 commit 5c4998c
Show file tree
Hide file tree
Showing 37 changed files with 1,016 additions and 317 deletions.
2 changes: 1 addition & 1 deletion src/Hyperbee.Pipeline.Auth/Hyperbee.Pipeline.Auth.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<PackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="9.0.0-rc.2.24474.3" />
<ProjectReference Include="..\Hyperbee.Pipeline\Hyperbee.Pipeline.csproj" />
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
Expand Down
88 changes: 78 additions & 10 deletions src/Hyperbee.Pipeline/Binders/Abstractions/Binder.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,94 @@
using Hyperbee.Pipeline.Context;
using Hyperbee.Pipeline.Extensions.Implementation;
using System.Linq.Expressions;
using Hyperbee.Pipeline.Context;

using static System.Linq.Expressions.Expression;
using static Hyperbee.Expressions.AsyncExpression;


namespace Hyperbee.Pipeline.Binders.Abstractions;

internal abstract class Binder<TInput, TOutput>
{
protected FunctionAsync<TInput, TOutput> Pipeline { get; }
protected Action<IPipelineContext> Configure { get; }
protected Expression<FunctionAsync<TInput, TOutput>> Pipeline { get; }
protected Expression<Action<IPipelineContext>> Configure { get; }

protected Binder( FunctionAsync<TInput, TOutput> function, Action<IPipelineContext> configure )
protected Binder( Expression<FunctionAsync<TInput, TOutput>> function, Expression<Action<IPipelineContext>> configure )
{
Pipeline = function;
Configure = configure;
}

protected virtual async Task<(TOutput Result, bool Canceled)> ProcessPipelineAsync( IPipelineContext context, TInput argument )
// protected virtual Task<(TOutput Result, bool Canceled)> ProcessPipelineAsync( IPipelineContext context, TInput argument )
// {
// var result = await Pipeline( context, argument ).ConfigureAwait( false );
//
// var contextControl = (IPipelineContextControl) context;
// var canceled = contextControl.HandleCancellationRequested( result );
//
// return (canceled ? default : result, canceled);
// }

protected virtual Expression ProcessPipelineAsync( ParameterExpression context, ParameterExpression argument )
{
var result = await Pipeline( context, argument ).ConfigureAwait( false );
var tupleCtor = typeof(ValueTuple<TOutput, bool>).GetConstructor( [typeof(TOutput), typeof(bool)] )!;

var resultVariable = Variable( typeof( TOutput ), "result" );
var canceledVariable = Variable( typeof( bool ), "canceled" );

var contextControl = Convert( context , typeof( IPipelineContextControl ) );

var contextControl = (IPipelineContextControl) context;
var canceled = contextControl.HandleCancellationRequested( result );
var body = BlockAsync(
[resultVariable, canceledVariable],
Assign( resultVariable, Await( Invoke( Pipeline, context, argument ), configureAwait: false ) ),
Assign( canceledVariable, HandleCancellationRequested( contextControl, resultVariable ) ),

return (canceled ? default : result, canceled);
Condition(
canceledVariable,
New( tupleCtor, Default( typeof( TOutput ) ), canceledVariable ),
New( tupleCtor, resultVariable, canceledVariable )
)
);

return body;
}



/*
public static bool HandleCancellationRequested<TOutput>( this IPipelineContextControl control, TOutput value )
{
if ( !control.CancellationToken.IsCancellationRequested )
return false;
if ( !control.HasCancellationValue )
control.CancellationValue = value;
return true;
}
*/


private Expression HandleCancellationRequested( Expression contextControl, Expression resultVariable )
{
var hasCancellationValue = Property( contextControl, "HasCancellationValue" );
var cancellationTokenProperty = Property( contextControl, "CancellationToken" );
var cancellationValueProperty = Property( contextControl, "CancellationValue" );

var conditionalExpression = Condition(
Not( Property( cancellationTokenProperty, "IsCancellationRequested" ) ),
Constant( false ),

Block(
IfThen(
Not( hasCancellationValue ),
Assign( cancellationValueProperty, resultVariable )
),
// After the assignment, return true
Constant( true )
)
);

return conditionalExpression;
}

}
20 changes: 16 additions & 4 deletions src/Hyperbee.Pipeline/Binders/Abstractions/BlockBinder.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using Hyperbee.Pipeline.Context;
using System.Linq.Expressions;
using Hyperbee.Pipeline.Context;

using static System.Linq.Expressions.Expression;
using static Hyperbee.Expressions.AsyncExpression;

namespace Hyperbee.Pipeline.Binders.Abstractions;

internal abstract class BlockBinder<TInput, TOutput> : Binder<TInput, TOutput>
{
protected BlockBinder( FunctionAsync<TInput, TOutput> function, Action<IPipelineContext> configure )
protected BlockBinder( Expression<FunctionAsync<TInput, TOutput>> function, Expression<Action<IPipelineContext>> configure )
: base( function, configure )
{
}
Expand All @@ -13,8 +17,16 @@ protected BlockBinder( FunctionAsync<TInput, TOutput> function, Action<IPipeline
// use cases where the next argument is not the same as the output type
// like ReduceBlockBinder and ForEachBlockBinder

protected virtual async Task<TNext> ProcessBlockAsync<TArgument, TNext>( FunctionAsync<TArgument, TNext> blockFunction, IPipelineContext context, TArgument nextArgument )
// protected virtual async Task<TNext> ProcessBlockAsync<TArgument, TNext>( Expression<FunctionAsync<TArgument, TNext>> blockFunction, IPipelineContext context, TArgument nextArgument )
// {
// return await blockFunction( context, nextArgument ).ConfigureAwait( false );
// }
protected virtual Expression<Task<TNext>> ProcessBlockAsync<TArgument, TNext>( Expression<FunctionAsync<TArgument, TNext>> blockFunction, ParameterExpression context, Expression nextArgument )
{
return await blockFunction( context, nextArgument ).ConfigureAwait( false );
var body = BlockAsync(
Await( Invoke( blockFunction, context, nextArgument ), configureAwait: false )
);

return Lambda<Task<TNext>>( body );
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,51 @@
using System.Runtime.CompilerServices;
using System.Linq.Expressions;
using Hyperbee.Pipeline.Context;
using static System.Linq.Expressions.Expression;

namespace Hyperbee.Pipeline.Binders.Abstractions;

internal abstract class ConditionalBlockBinder<TInput, TOutput> : BlockBinder<TInput, TOutput>
{
protected Function<TOutput, bool> Condition { get; }
protected Expression<Function<TOutput, bool>> Condition { get; }

protected ConditionalBlockBinder( Function<TOutput, bool> condition, FunctionAsync<TInput, TOutput> function, Action<IPipelineContext> configure )
protected ConditionalBlockBinder( Expression<Function<TOutput, bool>> condition, Expression<FunctionAsync<TInput, TOutput>> function, Expression<Action<IPipelineContext>> configure )
: base( function, configure )
{
Condition = condition;
}

protected override async Task<TNext> ProcessBlockAsync<TArgument, TNext>( FunctionAsync<TArgument, TNext> blockFunction, IPipelineContext context, TArgument nextArgument )
{
if ( Condition != null && !Condition( context, CastTypeArg<TArgument, TOutput>( nextArgument ) ) )
{
return CastTypeArg<TArgument, TNext>( nextArgument );
}
// protected override async Task<TNext> ProcessBlockAsync<TArgument, TNext>( FunctionAsync<TArgument, TNext> blockFunction, IPipelineContext context, TArgument nextArgument )
// {
// if ( Condition != null && !Condition( context, CastTypeArg<TArgument, TOutput>( nextArgument ) ) )
// {
// return CastTypeArg<TArgument, TNext>( nextArgument );
// }
//
// return await base.ProcessBlockAsync( blockFunction, context, nextArgument ).ConfigureAwait( false );
// }

return await base.ProcessBlockAsync( blockFunction, context, nextArgument ).ConfigureAwait( false );
}
// [MethodImpl( MethodImplOptions.AggressiveInlining )]
// private static TResult CastTypeArg<TType, TResult>( TType input )
// {
// return (TResult) (object) input;
// }

[MethodImpl( MethodImplOptions.AggressiveInlining )]
private static TResult CastTypeArg<TType, TResult>( TType input )
protected override Expression<Task<TNext>> ProcessBlockAsync<TArgument, TNext>(
Expression<FunctionAsync<TArgument, TNext>> blockFunction,
ParameterExpression context,
Expression nextArgument )
{
return (TResult) (object) input;
if ( Condition == null )
return base.ProcessBlockAsync( blockFunction, context, nextArgument );

var nextArgumentExpression = Constant( nextArgument );

return Lambda<Task<TNext>>(
IfThenElse(
Not( Invoke( Condition, Constant( context ),
Convert( Convert( nextArgumentExpression, typeof(object) ), typeof(TOutput) ) ) ),
Convert( Convert( Constant( nextArgument ), typeof(object) ), typeof(TNext) ),
base.ProcessBlockAsync( blockFunction, context, nextArgument )
) );
}
}
121 changes: 107 additions & 14 deletions src/Hyperbee.Pipeline/Binders/Abstractions/StatementBinder.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,124 @@
using Hyperbee.Pipeline.Context;
using Hyperbee.Pipeline.Extensions.Implementation;
using System.Linq.Expressions;
using Hyperbee.Pipeline.Context;
using static System.Linq.Expressions.Expression;
using static Hyperbee.Expressions.AsyncExpression;

namespace Hyperbee.Pipeline.Binders.Abstractions;

internal abstract class StatementBinder<TInput, TOutput> : Binder<TInput, TOutput>
{
protected MiddlewareAsync<object, object> Middleware { get; }
protected Expression<MiddlewareAsync<object, object>> Middleware { get; }

protected StatementBinder( FunctionAsync<TInput, TOutput> function, MiddlewareAsync<object, object> middleware, Action<IPipelineContext> configure )
protected StatementBinder( Expression<FunctionAsync<TInput, TOutput>> function, Expression<MiddlewareAsync<object, object>> middleware, Expression<Action<IPipelineContext>> configure )
: base( function, configure )
{
Middleware = middleware;
}

protected virtual async Task<TNext> ProcessStatementAsync<TNext>( FunctionAsync<TOutput, TNext> nextFunction, IPipelineContext context, TOutput nextArgument, string frameName )
// protected MiddlewareAsync<object, object> Middleware1 { get; }
// protected virtual async Task<TNext> ProcessStatementAsync<TNext>( FunctionAsync<TOutput, TNext> nextFunction, IPipelineContext context, TOutput nextArgument, string frameName )
// {
// var contextControl = (IPipelineContextControl) context;
//
// using var _ = contextControl.CreateFrame( context, Configure, frameName );
//
// if ( Middleware1 == null )
// return await nextFunction( context, nextArgument ).ConfigureAwait( false );
//
// return (TNext) await Middleware1(
// context,
// nextArgument,
// async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false )
// ).ConfigureAwait( false );
// }

protected virtual Expression ProcessStatementAsync<TNext>( Expression<FunctionAsync<TOutput, TNext>> nextFunction,
ParameterExpression context, Expression nextArgument, string frameName )
{
var contextControl = (IPipelineContextControl) context;
// if ( Middleware == null )
// return await nextFunction( context, nextArgument ).ConfigureAwait( false );
if ( Middleware == null )
{
return Invoke( nextFunction, context, nextArgument ); //, configureAwait: false );

using var _ = contextControl.CreateFrame( context, Configure, frameName );
//using var _ = contextControl.CreateFrame( context, Configure, frameName );
// return CreateFrameExpression(
// Convert( context, typeof(IPipelineContextControl) ),
// context,
// Configure,
// Await( Invoke( nextFunction, context, nextArgument ), configureAwait: false ),
// frameName );
}

if ( Middleware == null )
return await nextFunction( context, nextArgument ).ConfigureAwait( false );
// async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false )
var context1 = Parameter( typeof(IPipelineContext), "context1" );
var argument1 = Parameter( typeof(object), "argument1" );

var middlewareNext = Lambda<FunctionAsync<object, object>>(
BlockAsync(
Convert( Await(
Invoke( nextFunction, context1, Convert( argument1, typeof(TOutput) ) ),
configureAwait: false ),
typeof(object) )
),
parameters: [context1, argument1]
);

// return (TNext) await Middleware(
// context,
// nextArgument,
// middlewareNext
// ).ConfigureAwait( false );
return
//using var _ = contextControl.CreateFrame( context, Configure, frameName );
// CreateFrameExpression(
// Convert( Constant( context ), typeof(IPipelineContextControl) ),
// context,
// Configure,
BlockAsync(
Convert(
Await(
Invoke( Middleware,
context,
nextArgument,
middlewareNext
),
configureAwait: false ),
typeof(TNext) )); //,
// frameName ); //);
}

public static Expression CreateFrameExpression(
Expression controlParam,
Expression contextParam,
Expression<Action<IPipelineContext>> config,
Expression body,
string defaultName = null
)
{
var nameVariable = Variable( typeof( string ), "originalName" );
var idVariable = Variable( typeof( int ), "originalId" );

var idProperty = Property( controlParam, "Id" );
var nameProperty = Property( controlParam, "Name" );

return (TNext) await Middleware(
context,
nextArgument,
async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false )
).ConfigureAwait( false );
return BlockAsync(
[nameVariable, idVariable],
Assign( idVariable, idProperty ),
Assign( nameVariable, nameProperty ),
TryFinally(
Block(
Assign( idProperty, Call( controlParam, "GetNextId", Type.EmptyTypes ) ),
Assign( nameProperty, Constant( defaultName ) ),
config != null
? Invoke( config, contextParam )
: Empty(),
body
),
Block(
Assign( idProperty, idVariable ),
Assign( nameProperty, nameVariable )
) )
);
}
}
Loading

0 comments on commit 5c4998c

Please sign in to comment.