1
1
import { FunctionInfo } from './FunctionInfo' ;
2
- import { fromRpcHttp , fromTypedData , getNormalizedBindingData , getBindingDefinitions } from './converters' ;
2
+ import { fromRpcHttp , fromTypedData , getNormalizedBindingData , getBindingDefinitions , fromRpcTraceContext } from './converters' ;
3
3
import { AzureFunctionsRpcMessages as rpc } from '../azure-functions-language-worker-protobuf/src/rpc' ;
4
4
import { Request , RequestProperties } from './http/Request' ;
5
5
import { Response } from './http/Response' ;
6
6
import LogLevel = rpc . RpcLog . Level ;
7
7
import LogCategory = rpc . RpcLog . RpcLogCategory ;
8
- import { Context , ExecutionContext , Logger , BindingDefinition , HttpRequest } from './public/Interfaces'
8
+ import { Context , ExecutionContext , Logger , BindingDefinition , HttpRequest , TraceContext } from './public/Interfaces'
9
9
10
10
export function CreateContextAndInputs ( info : FunctionInfo , request : rpc . IInvocationRequest , logCallback : LogCallback , callback : ResultCallback ) {
11
- let context = new InvocationContext ( info , request , logCallback , callback ) ;
12
-
13
- let bindings : Dict < any > = { } ;
14
- let inputs : InputTypes [ ] = [ ] ;
15
- let httpInput : RequestProperties | undefined ;
16
- for ( let binding of < rpc . IParameterBinding [ ] > request . inputData ) {
17
- if ( binding . data && binding . name ) {
18
- let input : InputTypes ;
19
- if ( binding . data && binding . data . http ) {
20
- input = httpInput = fromRpcHttp ( binding . data . http ) ;
21
- } else {
22
- input = fromTypedData ( binding . data ) ;
23
- }
24
- bindings [ binding . name ] = input ;
25
- inputs . push ( input ) ;
11
+ let context = new InvocationContext ( info , request , logCallback , callback ) ;
12
+
13
+ let bindings : Dict < any > = { } ;
14
+ let inputs : InputTypes [ ] = [ ] ;
15
+ let httpInput : RequestProperties | undefined ;
16
+ for ( let binding of < rpc . IParameterBinding [ ] > request . inputData ) {
17
+ if ( binding . data && binding . name ) {
18
+ let input : InputTypes ;
19
+ if ( binding . data && binding . data . http ) {
20
+ input = httpInput = fromRpcHttp ( binding . data . http ) ;
21
+ } else {
22
+ input = fromTypedData ( binding . data ) ;
23
+ }
24
+ bindings [ binding . name ] = input ;
25
+ inputs . push ( input ) ;
26
+ }
27
+ }
28
+
29
+ context . bindings = bindings ;
30
+ if ( httpInput ) {
31
+ context . req = new Request ( httpInput ) ;
32
+ context . res = new Response ( context . done ) ;
33
+ }
34
+ return {
35
+ context : < Context > context ,
36
+ inputs : inputs
26
37
}
27
- }
28
-
29
- context . bindings = bindings ;
30
- if ( httpInput ) {
31
- context . req = new Request ( httpInput ) ;
32
- context . res = new Response ( context . done ) ;
33
- }
34
- return {
35
- context : < Context > context ,
36
- inputs : inputs
37
- }
38
38
}
39
39
40
40
class InvocationContext implements Context {
41
- invocationId : string ;
42
- executionContext : ExecutionContext ;
43
- bindings : Dict < any > ;
44
- bindingData : Dict < any > ;
45
- bindingDefinitions : BindingDefinition [ ] ;
46
- log : Logger ;
47
- req ?: Request ;
48
- res ?: Response ;
49
- done : DoneCallback ;
50
-
51
- constructor ( info : FunctionInfo , request : rpc . IInvocationRequest , logCallback : LogCallback , callback : ResultCallback ) {
52
- this . invocationId = < string > request . invocationId ;
53
- const executionContext = {
54
- invocationId : this . invocationId ,
55
- functionName : < string > info . name ,
56
- functionDirectory : < string > info . directory
57
- } ;
58
- this . executionContext = executionContext ;
59
- this . bindings = { } ;
60
- let _done = false ;
61
- let _promise = false ;
62
-
63
- // Log message that is tied to function invocation
64
- this . log = Object . assign (
65
- < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
66
- {
67
- error : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Error , executionContext , ...args ) ,
68
- warn : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Warning , executionContext , ...args ) ,
69
- info : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
70
- verbose : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Trace , executionContext , ...args )
71
- }
72
- ) ;
73
-
74
- this . bindingData = getNormalizedBindingData ( request ) ;
75
- this . bindingDefinitions = getBindingDefinitions ( info ) ;
76
-
77
- // isPromise is a hidden parameter that we set to true in the event of a returned promise
78
- this . done = ( err ?: any , result ?: any , isPromise ?: boolean ) => {
79
- _promise = isPromise === true ;
80
- if ( _done ) {
81
- if ( _promise ) {
82
- logCallback ( LogLevel . Error , LogCategory . User , "Error: Choose either to return a promise or call 'done'. Do not use both in your script." ) ;
83
- } else {
84
- logCallback ( LogLevel . Error , LogCategory . User , "Error: 'done' has already been called. Please check your script for extraneous calls to 'done'." ) ;
85
- }
86
- return ;
87
- }
88
- _done = true ;
89
-
90
- // Allow HTTP response from context.res if HTTP response is not defined from the context.bindings object
91
- if ( info . httpOutputName && this . res && this . bindings [ info . httpOutputName ] === undefined ) {
92
- this . bindings [ info . httpOutputName ] = this . res ;
93
- }
94
-
95
- callback ( err , {
96
- return : result ,
97
- bindings : this . bindings
98
- } ) ;
99
- } ;
100
- }
41
+ invocationId : string ;
42
+ executionContext : ExecutionContext ;
43
+ bindings : Dict < any > ;
44
+ bindingData : Dict < any > ;
45
+ traceContext : TraceContext ;
46
+ bindingDefinitions : BindingDefinition [ ] ;
47
+ log : Logger ;
48
+ req ?: Request ;
49
+ res ?: Response ;
50
+ done : DoneCallback ;
51
+
52
+ constructor ( info : FunctionInfo , request : rpc . IInvocationRequest , logCallback : LogCallback , callback : ResultCallback ) {
53
+ this . invocationId = < string > request . invocationId ;
54
+ this . traceContext = fromRpcTraceContext ( request . traceContext ) ;
55
+ const executionContext = {
56
+ invocationId : this . invocationId ,
57
+ functionName : < string > info . name ,
58
+ functionDirectory : < string > info . directory
59
+ } ;
60
+ this . executionContext = executionContext ;
61
+ this . bindings = { } ;
62
+ let _done = false ;
63
+ let _promise = false ;
64
+
65
+ // Log message that is tied to function invocation
66
+ this . log = Object . assign (
67
+ < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
68
+ {
69
+ error : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Error , executionContext , ...args ) ,
70
+ warn : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Warning , executionContext , ...args ) ,
71
+ info : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
72
+ verbose : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Trace , executionContext , ...args )
73
+ }
74
+ ) ;
75
+
76
+ this . bindingData = getNormalizedBindingData ( request ) ;
77
+ this . bindingDefinitions = getBindingDefinitions ( info ) ;
78
+
79
+ // isPromise is a hidden parameter that we set to true in the event of a returned promise
80
+ this . done = ( err ?: any , result ?: any , isPromise ?: boolean ) => {
81
+ _promise = isPromise === true ;
82
+ if ( _done ) {
83
+ if ( _promise ) {
84
+ logCallback ( LogLevel . Error , LogCategory . User , "Error: Choose either to return a promise or call 'done'. Do not use both in your script." ) ;
85
+ } else {
86
+ logCallback ( LogLevel . Error , LogCategory . User , "Error: 'done' has already been called. Please check your script for extraneous calls to 'done'." ) ;
87
+ }
88
+ return ;
89
+ }
90
+ _done = true ;
91
+
92
+ // Allow HTTP response from context.res if HTTP response is not defined from the context.bindings object
93
+ if ( info . httpOutputName && this . res && this . bindings [ info . httpOutputName ] === undefined ) {
94
+ this . bindings [ info . httpOutputName ] = this . res ;
95
+ }
96
+
97
+ callback ( err , {
98
+ return : result ,
99
+ bindings : this . bindings
100
+ } ) ;
101
+ } ;
102
+ }
101
103
}
102
104
103
105
// Emit warning if trying to log after function execution is done.
104
106
function logWithAsyncCheck ( done : boolean , log : LogCallback , level : LogLevel , executionContext : ExecutionContext , ...args : any [ ] ) {
105
- if ( done ) {
106
- let badAsyncMsg = "Warning: Unexpected call to 'log' on the context object after function execution has completed. Please check for asynchronous calls that are not awaited or calls to 'done' made before function execution completes. " ;
107
- badAsyncMsg += `Function name: ${ executionContext . functionName } . Invocation Id: ${ executionContext . invocationId } . ` ;
108
- badAsyncMsg += `Learn more: https://go.microsoft.com/fwlink/?linkid=2097909 ` ;
109
- log ( LogLevel . Warning , LogCategory . System , badAsyncMsg ) ;
110
- }
111
- return log ( level , LogCategory . User , ...args ) ;
107
+ if ( done ) {
108
+ let badAsyncMsg = "Warning: Unexpected call to 'log' on the context object after function execution has completed. Please check for asynchronous calls that are not awaited or calls to 'done' made before function execution completes. " ;
109
+ badAsyncMsg += `Function name: ${ executionContext . functionName } . Invocation Id: ${ executionContext . invocationId } . ` ;
110
+ badAsyncMsg += `Learn more: https://go.microsoft.com/fwlink/?linkid=2097909 ` ;
111
+ log ( LogLevel . Warning , LogCategory . System , badAsyncMsg ) ;
112
+ }
113
+ return log ( level , LogCategory . User , ...args ) ;
112
114
}
113
115
114
116
export interface InvocationResult {
115
- return : any ;
116
- bindings : Dict < any > ;
117
+ return : any ;
118
+ bindings : Dict < any > ;
117
119
}
118
120
119
121
export type DoneCallback = ( err ?: Error | string , result ?: any ) => void ;
@@ -123,7 +125,7 @@ export type LogCallback = (level: LogLevel, category: rpc.RpcLog.RpcLogCategory,
123
125
export type ResultCallback = ( err ?: any , result ?: InvocationResult ) => void ;
124
126
125
127
export interface Dict < T > {
126
- [ key : string ] : T
128
+ [ key : string ] : T
127
129
}
128
130
129
131
// Allowed input types
0 commit comments