Skip to content

Commit 1b68a25

Browse files
authored
Don't override all output binding data when return result present (#273)
* Don't override all output binding data set through context.bindings if return value present * Update worker version
1 parent af2bb9c commit 1b68a25

File tree

9 files changed

+86
-20
lines changed

9 files changed

+86
-20
lines changed

Worker.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
33
<metadata>
44
<id>Microsoft.Azure.Functions.NodeJsWorker</id>
5-
<version>2.0.0$version$</version>
5+
<version>2.0.1$version$</version>
66
<authors>Microsoft</authors>
77
<owners>Microsoft</owners>
88
<requireLicenseAcceptance>false</requireLicenseAcceptance>

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
variables: {
2-
WORKER_VERSION: '2.0.0',
2+
WORKER_VERSION: '2.0.1',
33
NODE_8: '8.x',
44
NODE_10: '10.x',
55
NODE_12: '12.x'

e2e-nightly-cli-azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
variables: {
2-
WORKER_VERSION: '2.0.0',
2+
WORKER_VERSION: '2.0.1',
33
NODE_12: '12.x'
44
}
55
name: $(WORKER_VERSION)-$(Date:yyyyMMdd)$(Rev:.r)

e2e-nightly-site-azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
variables: {
2-
WORKER_VERSION: '2.0.0',
2+
WORKER_VERSION: '2.0.1',
33
NODE_12: '12.x'
44
}
55
name: $(WORKER_VERSION)-$(Date:yyyyMMdd)$(Rev:.r)

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "azure-functions-nodejs-worker",
33
"author": "Microsoft Corporation",
4-
"version": "1.2.0",
4+
"version": "2.0.1",
55
"description": "Microsoft Azure Functions NodeJS Worker",
66
"license": "(MIT OR Apache-2.0)",
77
"dependencies": {

src/WorkerChannel.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,12 @@ export class WorkerChannel implements IWorkerChannel {
186186
invocationId: msg.invocationId,
187187
result: this.getStatus(err)
188188
}
189+
// explicitly set outputData to empty array to concat later
190+
response.outputData = [];
189191

190192
try {
191193
if (result) {
194+
// Set results from return / context.done
192195
if (result.return) {
193196
if (this._v1WorkerBehavior) {
194197
response.returnValue = toTypedData(result.return);
@@ -208,14 +211,15 @@ export class WorkerChannel implements IWorkerChannel {
208211
}
209212
}
210213
}
211-
// Data from return supersedes data from context.bindings
212-
if (result.bindings && !response.outputData) {
213-
response.outputData = Object.keys(info.outputBindings)
214-
.filter(key => result.bindings[key] !== undefined)
214+
// Set results from context.bindings
215+
if (result.bindings) {
216+
response.outputData = response.outputData.concat(Object.keys(info.outputBindings)
217+
// Data from return prioritized over data from context.bindings
218+
.filter(key => result.bindings[key] !== undefined && (!result.return || result.return[key] === undefined))
215219
.map(key => <rpc.IParameterBinding>{
216220
name: key,
217221
data: info.outputBindings[key].converter(result.bindings[key])
218-
});
222+
}));
219223
}
220224
}
221225
} catch (e) {

test/WorkerChannelTests.ts

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ describe('WorkerChannel', () => {
5252
direction: 1,
5353
dataType: 1
5454
};
55+
const queueOutputBinding = {
56+
type: "queue",
57+
direction: 1,
58+
dataType: 1
59+
};
5560
const httpReturnBinding = {
5661
bindings: {
5762
req: httpInputBinding,
@@ -64,6 +69,14 @@ describe('WorkerChannel', () => {
6469
res: httpOutputBinding
6570
}
6671
};
72+
const multipleBinding = {
73+
bindings: {
74+
req: httpInputBinding,
75+
res: httpOutputBinding,
76+
queueOutput: queueOutputBinding,
77+
overriddenQueueOutput: queueOutputBinding
78+
}
79+
};
6780

6881
beforeEach(() => {
6982
stream = new TestEventStream();
@@ -472,9 +485,63 @@ describe('WorkerChannel', () => {
472485
});
473486
});
474487

488+
it ('serializes multiple output bindings through context.done and context.bindings', () => {
489+
loader.getFunc.returns((context) => {
490+
context.bindings.queueOutput = "queue message";
491+
context.bindings.overriddenQueueOutput = "start message";
492+
context.done(null, {
493+
res: { body: { hello: "world" } },
494+
overriddenQueueOutput: "override"
495+
});
496+
});
497+
loader.getInfo.returns(new FunctionInfo(multipleBinding));
498+
499+
var actualInvocationRequest: rpc.IInvocationRequest = <rpc.IInvocationRequest> {
500+
functionId: 'id',
501+
invocationId: '1',
502+
inputData: [httpInputData],
503+
triggerMetadata: getTriggerDataMock(),
504+
};
505+
506+
stream.addTestMessage({
507+
invocationRequest: actualInvocationRequest
508+
});
509+
510+
sinon.assert.calledWithMatch(stream.written, <rpc.IStreamingMessage> {
511+
invocationResponse: {
512+
invocationId: '1',
513+
result: {
514+
status: rpc.StatusResult.Status.Success
515+
},
516+
outputData: [{
517+
data: {
518+
http: {
519+
body: { json: "{\"hello\":\"world\"}" },
520+
cookies: [],
521+
headers: { },
522+
statusCode: undefined
523+
}
524+
},
525+
name: "res"
526+
},
527+
{
528+
data: {
529+
string: "override"
530+
},
531+
name: "overriddenQueueOutput"
532+
},
533+
{
534+
data: {
535+
string: "queue message"
536+
},
537+
name: "queueOutput"
538+
}]
539+
}
540+
});
541+
});
542+
475543
it ('serializes output binding data through context.done with V2 compat', () => {
476-
let httpResponse;
477-
loader.getFunc.returns((context) => { httpResponse = context.res; context.done(null, { res: { body: { hello: "world" }}})});
544+
loader.getFunc.returns((context) => context.done(null, { res: { body: { hello: "world" }}}));
478545
loader.getInfo.returns(new FunctionInfo(httpResBinding));
479546

480547
stream.addTestMessage({
@@ -503,12 +570,7 @@ describe('WorkerChannel', () => {
503570
result: {
504571
status: rpc.StatusResult.Status.Success
505572
},
506-
outputData: [{
507-
data: {
508-
http: httpResponse
509-
},
510-
name: "res"
511-
}],
573+
outputData: [],
512574
returnValue: {
513575
json: "{\"res\":{\"body\":{\"hello\":\"world\"}}}"
514576
}

types/public/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azure/functions",
3-
"version": "2.0.0",
3+
"version": "2.0.1",
44
"description": "Azure Functions types for Typescript",
55
"repository": {
66
"type": "git",

0 commit comments

Comments
 (0)